private static Instances convertToInstances( final IScope scope, final IList<String> attributes, final IAddressableContainer<Integer, IAgent, Integer, IAgent> agents) throws GamaRuntimeException { FastVector attribs = new FastVector(); for (String att : attributes) { attribs.addElement(new Attribute(att)); } Instances dataset = new Instances(scope.getAgentScope().getName(), attribs, agents.length(scope)); for (IAgent ag : agents.iterable(scope)) { int nb = attributes.size(); double vals[] = new double[nb]; for (int i = 0; i < nb; i++) { String attrib = attributes.get(i); Double var = Cast.asFloat(scope, ag.getDirectVarValue(scope, attrib)); vals[i] = var; } Instance instance = new Instance(1, vals); dataset.add(instance); } return dataset; }
/** * Handles the various button clicking type activities. * * @param e a value of type 'ActionEvent' */ public void actionPerformed(ActionEvent e) { if (e.getSource() == m_ConfigureBut) { selectProperty(); } else if (e.getSource() == m_StatusBox) { // notify any listeners for (int i = 0; i < m_Listeners.size(); i++) { ActionListener temp = ((ActionListener) m_Listeners.elementAt(i)); temp.actionPerformed( new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "Editor status change")); } // Toggles whether the custom property is used if (m_StatusBox.getSelectedIndex() == 0) { m_Exp.setUsePropertyIterator(false); m_ConfigureBut.setEnabled(false); m_ArrayEditor.setEnabled(false); m_ArrayEditor.setValue(null); validate(); } else { if (m_Exp.getPropertyArray() == null) { selectProperty(); } if (m_Exp.getPropertyArray() == null) { m_StatusBox.setSelectedIndex(0); } else { m_Exp.setUsePropertyIterator(true); m_ConfigureBut.setEnabled(true); m_ArrayEditor.setEnabled(true); } validate(); } } }
/** * Gets the scheme paramter with the given index. * * @param index the index for the parameter * @return the scheme parameter */ public String getCVParameter(int index) { if (m_CVParams.size() <= index) { return ""; } return ((CVParameter) m_CVParams.elementAt(index)).toString(); }
/** * Tests the ThresholdCurve generation from the command line. The classifier is currently * hardcoded. Pipe in an arff file. * * @param args currently ignored */ public static void main(String[] args) { try { Instances inst = new Instances(new java.io.InputStreamReader(System.in)); if (false) { System.out.println(ThresholdCurve.getNPointPrecision(inst, 11)); } else { inst.setClassIndex(inst.numAttributes() - 1); ThresholdCurve tc = new ThresholdCurve(); EvaluationUtils eu = new EvaluationUtils(); Classifier classifier = new weka.classifiers.functions.Logistic(); FastVector predictions = new FastVector(); for (int i = 0; i < 2; i++) { // Do two runs. eu.setSeed(i); predictions.appendElements(eu.getCVPredictions(classifier, inst, 10)); // System.out.println("\n\n\n"); } Instances result = tc.getCurve(predictions); System.out.println(result); } } catch (Exception ex) { ex.printStackTrace(); } }
/** * Produces a shallow copy of this vector. * * @return the new vector */ public final Object copy() { FastVector copy = new FastVector(m_Objects.length, m_CapacityIncrement, m_CapacityMultiplier); copy.m_Size = m_Size; System.arraycopy(m_Objects, 0, copy.m_Objects, 0, m_Size); return copy; }
/** * Create the options array to pass to the classifier. The parameter values and positions are * taken from m_ClassifierOptions and m_CVParams. * * @return the options array */ protected String[] createOptions() { String[] options = new String[m_ClassifierOptions.length + 2 * m_CVParams.size()]; int start = 0, end = options.length; // Add the cross-validation parameters and their values for (int i = 0; i < m_CVParams.size(); i++) { CVParameter cvParam = (CVParameter) m_CVParams.elementAt(i); double paramValue = cvParam.m_ParamValue; if (cvParam.m_RoundParam) { // paramValue = (double)((int) (paramValue + 0.5)); paramValue = Math.rint(paramValue); } if (cvParam.m_AddAtEnd) { options[--end] = "" + Utils.doubleToString(paramValue, 4); options[--end] = "-" + cvParam.m_ParamChar; } else { options[start++] = "-" + cvParam.m_ParamChar; options[start++] = "" + Utils.doubleToString(paramValue, 4); } } // Add the static parameters System.arraycopy(m_ClassifierOptions, 0, options, start, m_ClassifierOptions.length); return options; }
/** * Get the data after filtering the given rule * * @param index the index of the rule * @return the data covered and uncovered by the rule */ public Instances[] getFiltered(int index) { if ((m_Filtered != null) && (index < m_Filtered.size())) return (Instances[]) m_Filtered.elementAt(index); return null; }
/** * Gets the current settings of the Classifier. * * @return an array of strings suitable for passing to setOptions */ public String[] getOptions() { String[] superOptions; if (m_InitOptions != null) { try { ((OptionHandler) m_Classifier).setOptions((String[]) m_InitOptions.clone()); superOptions = super.getOptions(); ((OptionHandler) m_Classifier).setOptions((String[]) m_BestClassifierOptions.clone()); } catch (Exception e) { throw new RuntimeException( "CVParameterSelection: could not set options " + "in getOptions()."); } } else { superOptions = super.getOptions(); } String[] options = new String[superOptions.length + m_CVParams.size() * 2 + 2]; int current = 0; for (int i = 0; i < m_CVParams.size(); i++) { options[current++] = "-P"; options[current++] = "" + getCVParameter(i); } options[current++] = "-X"; options[current++] = "" + getNumFolds(); System.arraycopy(superOptions, 0, options, current, superOptions.length); return options; }
/** * Get the class distribution predicted by the rule in given position * * @param index the position index of the rule * @return the class distributions */ public double[] getDistributions(int index) { if ((m_Distributions != null) && (index < m_Distributions.size())) return (double[]) m_Distributions.elementAt(index); return null; }
/** * Sets up the structure for the plot instances. Sets m_PlotInstances to null if instances are not * saved for visualization. * * @see #getSaveForVisualization() */ protected void determineFormat() { FastVector hv; Attribute predictedClass; Attribute classAt; FastVector attVals; int i; if (!m_SaveForVisualization) { m_PlotInstances = null; return; } hv = new FastVector(); classAt = m_Instances.attribute(m_ClassIndex); if (classAt.isNominal()) { attVals = new FastVector(); for (i = 0; i < classAt.numValues(); i++) attVals.addElement(classAt.value(i)); predictedClass = new Attribute("predicted" + classAt.name(), attVals); } else { predictedClass = new Attribute("predicted" + classAt.name()); } for (i = 0; i < m_Instances.numAttributes(); i++) { if (i == m_Instances.classIndex()) hv.addElement(predictedClass); hv.addElement(m_Instances.attribute(i).copy()); } m_PlotInstances = new Instances(m_Instances.relationName() + "_predicted", hv, m_Instances.numInstances()); m_PlotInstances.setClassIndex(m_ClassIndex + 1); }
/** * Set the output format. Takes the current average class values and m_InputFormat and calls * setOutputFormat(Instances) appropriately. */ private void setOutputFormat() { Instances newData; FastVector newAtts, newVals; // Compute new attributes newAtts = new FastVector(getInputFormat().numAttributes()); for (int j = 0; j < getInputFormat().numAttributes(); j++) { Attribute att = getInputFormat().attribute(j); if (!m_AttIndices.isInRange(j) || !att.isString()) { // We don't have to copy the attribute because the // attribute index remains unchanged. newAtts.addElement(att); } else { // Compute list of attribute values newVals = new FastVector(att.numValues()); for (int i = 0; i < att.numValues(); i++) { newVals.addElement(att.value(i)); } newAtts.addElement(new Attribute(att.name(), newVals)); } } // Construct new header newData = new Instances(getInputFormat().relationName(), newAtts, 0); newData.setClassIndex(getInputFormat().classIndex()); setOutputFormat(newData); }
public weka.core.Instances toWekaInstances() { // attributes FastVector wattrs = new FastVector(); Iterator itr = attributes.iterator(); while (itr.hasNext()) { Attribute attr = (Attribute) itr.next(); wattrs.addElement(attr.toWekaAttribute()); } // data instances weka.core.Instances winsts = new weka.core.Instances(name, wattrs, instances.size()); itr = instances.iterator(); while (itr.hasNext()) { Instance inst = (Instance) itr.next(); Iterator itrval = inst.getValues().iterator(); Iterator itrmis = inst.getMissing().iterator(); double[] vals = new double[wattrs.size()]; for (int i = 0; i < wattrs.size(); i++) { double val = (Double) itrval.next(); if ((Boolean) itrmis.next()) { vals[i] = weka.core.Instance.missingValue(); } else { vals[i] = val; } } weka.core.Instance winst = new weka.core.Instance(1, vals); winst.setDataset(winsts); winsts.add(winst); } winsts.setClassIndex(this.class_index); return winsts; }
/** * Remove the last rule in the ruleset as well as it's stats. It might be useful when the last * rule was added for testing purpose and then the test failed */ public void removeLast() { int last = m_Ruleset.size() - 1; m_Ruleset.removeElementAt(last); m_Filtered.removeElementAt(last); m_SimpleStats.removeElementAt(last); if (m_Distributions != null) m_Distributions.removeElementAt(last); }
/** * Set the labels for nominal attribute creation. * * @param labelList a comma separated list of labels * @throws IllegalArgumentException if the labelList was invalid */ public void setNominalLabels(String labelList) { FastVector labels = new FastVector(10); // Split the labelList up into the vector int commaLoc; while ((commaLoc = labelList.indexOf(',')) >= 0) { String label = labelList.substring(0, commaLoc).trim(); if (!label.equals("")) { labels.addElement(label); } else { throw new IllegalArgumentException( "Invalid label list at " + labelList.substring(commaLoc)); } labelList = labelList.substring(commaLoc + 1); } String label = labelList.trim(); if (!label.equals("")) { labels.addElement(label); } // If everything is OK, make the type change m_Labels = labels; if (labels.size() == 0) { m_AttributeType = Attribute.NUMERIC; } else { m_AttributeType = Attribute.NOMINAL; } }
/** * Finds the best parameter combination. (recursive for each parameter being optimised). * * @param depth the index of the parameter to be optimised at this level * @param trainData the data the search is based on * @param random a random number generator * @throws Exception if an error occurs */ protected void findParamsByCrossValidation(int depth, Instances trainData, Random random) throws Exception { if (depth < m_CVParams.size()) { CVParameter cvParam = (CVParameter) m_CVParams.elementAt(depth); double upper; switch ((int) (cvParam.m_Lower - cvParam.m_Upper + 0.5)) { case 1: upper = m_NumAttributes; break; case 2: upper = m_TrainFoldSize; break; default: upper = cvParam.m_Upper; break; } double increment = (upper - cvParam.m_Lower) / (cvParam.m_Steps - 1); for (cvParam.m_ParamValue = cvParam.m_Lower; cvParam.m_ParamValue <= upper; cvParam.m_ParamValue += increment) { findParamsByCrossValidation(depth + 1, trainData, random); } } else { Evaluation evaluation = new Evaluation(trainData); // Set the classifier options String[] options = createOptions(); if (m_Debug) { System.err.print("Setting options for " + m_Classifier.getClass().getName() + ":"); for (int i = 0; i < options.length; i++) { System.err.print(" " + options[i]); } System.err.println(""); } ((OptionHandler) m_Classifier).setOptions(options); for (int j = 0; j < m_NumFolds; j++) { // We want to randomize the data the same way for every // learning scheme. Instances train = trainData.trainCV(m_NumFolds, j, new Random(1)); Instances test = trainData.testCV(m_NumFolds, j); m_Classifier.buildClassifier(train); evaluation.setPriors(train); evaluation.evaluateModel(m_Classifier, test); } double error = evaluation.errorRate(); if (m_Debug) { System.err.println("Cross-validated error rate: " + Utils.doubleToString(error, 6, 4)); } if ((m_BestPerformance == -99) || (error < m_BestPerformance)) { m_BestPerformance = error; m_BestClassifierOptions = createOptions(); } } }
/** * Calculates the performance stats for the default class and return results as a set of * Instances. The structure of these Instances is as follows: * * <p> * * <ul> * <li><b>True Positives </b> * <li><b>False Negatives</b> * <li><b>False Positives</b> * <li><b>True Negatives</b> * <li><b>False Positive Rate</b> * <li><b>True Positive Rate</b> * <li><b>Precision</b> * <li><b>Recall</b> * <li><b>Fallout</b> * <li><b>Threshold</b> contains the probability threshold that gives rise to the previous * performance values. * </ul> * * <p>For the definitions of these measures, see TwoClassStats * * <p> * * @see TwoClassStats * @param predictions the predictions to base the curve on * @return datapoints as a set of instances, null if no predictions have been made. */ public Instances getCurve(FastVector predictions) { if (predictions.size() == 0) { return null; } return getCurve( predictions, ((NominalPrediction) predictions.elementAt(0)).distribution().length - 1); }
private FastVector attFromStream(StreamElement data) { FastVector fv = new FastVector(); for (int i = 0; i < data.getFieldNames().length; i++) { Attribute a = new Attribute(data.getFieldNames()[i]); fv.addElement(a); } return fv; }
/** * Returns an enumeration describing the available options. * * @return an enumeration of all the available options. */ public Enumeration listOptions() { String string1 = "\tThe required number of rules. (default = " + (m_numRules - 5) + ")"; FastVector newVector = new FastVector(1); newVector.addElement(new Option(string1, "N", 1, "-N <required number of rules output>")); return newVector.elements(); }
private List<Instance> myExtractKeyphrases(String document, int numOfPhrases) throws Exception { // Check whether there is actually any data // if (document.length() == 0 || document.equals("")) { throw new Exception("Couldn't find any data!"); } FastVector atts = new FastVector(3); atts.addElement(new Attribute("doc", (FastVector) null)); atts.addElement(new Attribute("keyphrases", (FastVector) null)); Instances data = new Instances("keyphrase_training_data", atts, 0); List<Instance> myInstances = new ArrayList<Instance>(); double[] newInst = new double[2]; newInst[0] = (double) data.attribute(0).addStringValue(document); newInst[1] = Instance.missingValue(); data.add(new Instance(1.0, newInst)); m_KEAFilter.input(data.instance(0)); data = data.stringFreeStructure(); ke.setNumPhrases(numOfPhrases); int numPhrases = numOfPhrases; // ke.getNumPhrases(); Instance[] topRankedInstances = new Instance[numPhrases]; Instance inst; // Iterating over all extracted keyphrases (inst) while ((inst = m_KEAFilter.output()) != null) { int index = (int) inst.value(m_KEAFilter.getRankIndex()) - 1; if (index < numPhrases) { topRankedInstances[index] = inst; } } double numExtracted = 0, numCorrect = 0; for (int i = 0; i < numPhrases; i++) { if (topRankedInstances[i] != null) { if (!topRankedInstances[i].isMissing(topRankedInstances[i].numAttributes() - 1)) { numExtracted += 1.0; } if ((int) topRankedInstances[i].value(topRankedInstances[i].numAttributes() - 1) == 1) { numCorrect += 1.0; } myInstances.add(topRankedInstances[i]); } } return myInstances; }
/** * Adds the statistics encapsulated in the supplied Evaluation object into this one. Does not * perform any checks for compatibility between the supplied Evaluation object and this one. * * @param evaluation the evaluation object to aggregate */ public void aggregate(Evaluation evaluation) { m_Incorrect += evaluation.incorrect(); m_Correct += evaluation.correct(); m_Unclassified += evaluation.unclassified(); m_MissingClass += evaluation.m_MissingClass; m_WithClass += evaluation.m_WithClass; if (evaluation.m_ConfusionMatrix != null) { double[][] newMatrix = evaluation.confusionMatrix(); if (newMatrix != null) { for (int i = 0; i < m_ConfusionMatrix.length; i++) { for (int j = 0; j < m_ConfusionMatrix[i].length; j++) { m_ConfusionMatrix[i][j] += newMatrix[i][j]; } } } } double[] newClassPriors = evaluation.m_ClassPriors; if (newClassPriors != null) { for (int i = 0; i < this.m_ClassPriors.length; i++) { m_ClassPriors[i] = newClassPriors[i]; } } m_ClassPriorsSum = evaluation.m_ClassPriorsSum; m_TotalCost += evaluation.totalCost(); m_SumErr += evaluation.m_SumErr; m_SumAbsErr += evaluation.m_SumAbsErr; m_SumSqrErr += evaluation.m_SumSqrErr; m_SumClass += evaluation.m_SumClass; m_SumSqrClass += evaluation.m_SumSqrClass; m_SumPredicted += evaluation.m_SumPredicted; m_SumSqrPredicted += evaluation.m_SumSqrPredicted; m_SumClassPredicted += evaluation.m_SumClassPredicted; m_SumPriorAbsErr += evaluation.m_SumPriorAbsErr; m_SumPriorSqrErr += evaluation.m_SumPriorSqrErr; m_SumKBInfo += evaluation.m_SumKBInfo; double[] newMarginCounts = evaluation.m_MarginCounts; if (newMarginCounts != null) { for (int i = 0; i < m_MarginCounts.length; i++) { m_MarginCounts[i] += newMarginCounts[i]; } } m_SumPriorEntropy += evaluation.m_SumPriorEntropy; m_SumSchemeEntropy += evaluation.m_SumSchemeEntropy; m_TotalSizeOfRegions += evaluation.m_TotalSizeOfRegions; m_TotalCoverage += evaluation.m_TotalCoverage; FastVector predsToAdd = evaluation.m_Predictions; if (predsToAdd != null) { if (m_Predictions == null) { m_Predictions = new FastVector(); } for (int i = 0; i < predsToAdd.size(); i++) { m_Predictions.addElement(predsToAdd.elementAt(i)); } } }
/** * Clones the vector and shallow copies all its elements. The elements have to implement the * Copyable interface. * * @return the new vector */ public final Object copyElements() { FastVector copy = new FastVector(m_Objects.length, m_CapacityIncrement, m_CapacityMultiplier); copy.m_Size = m_Size; for (int i = 0; i < m_Size; i++) { copy.m_Objects[i] = ((Copyable) m_Objects[i]).copy(); } return copy; }
/** * Trains the classifier on the array of Signal objects. Implementations of this method should * also produce an ordered list of the class names which can be returned with the <code> * getClassNames</code> method. * * @param inputData the Signal array that the model should be trained on. * @throws noMetadataException Thrown if there is no class metadata to train the Gaussian model * with */ public void train(Signal[] inputData) { List classNamesList = new ArrayList(); for (int i = 0; i < inputData.length; i++) { try { String className = inputData[i].getStringMetadata(Signal.PROP_CLASS); if ((className != null) && (!classNamesList.contains(className))) { classNamesList.add(className); } } catch (noMetadataException ex) { throw new RuntimeException("No class metadata found to train model on!", ex); } } Collections.sort(classNamesList); classnames = (String[]) classNamesList.toArray(new String[classNamesList.size()]); FastVector classValues = new FastVector(classnames.length); for (int i = 0; i < classnames.length; i++) { classValues.addElement(classnames[i]); } classAttribute = new Attribute(Signal.PROP_CLASS, classValues); Instances trainingDataSet = new Instances(Signal2Instance.convert(inputData[0], classAttribute)); if (inputData.length > 1) { for (int i = 1; i < inputData.length; i++) { Instances aSignalInstance = Signal2Instance.convert(inputData[i], classAttribute); for (int j = 0; j < aSignalInstance.numInstances(); j++) trainingDataSet.add(aSignalInstance.instance(j)); } } trainingDataSet.setClass(classAttribute); inputData = null; theRule = new MISMO(); // parse options StringTokenizer stOption = new StringTokenizer(this.MISMOOptions, " "); String[] options = new String[stOption.countTokens()]; for (int i = 0; i < options.length; i++) { options[i] = stOption.nextToken(); } try { theRule.setOptions(options); } catch (Exception ex) { throw new RuntimeException("Failed to set MISMO classifier options!", ex); } try { theRule.buildClassifier(trainingDataSet); System.out.println("WEKA: outputting MISMO classifier; " + theRule.globalInfo()); } catch (Exception ex) { throw new RuntimeException("Failed to train classifier!", ex); } }
public FastVector buildCosineAttributes() { FastVector attributes = new FastVector(2); attributes.addElement(new Attribute("cosine")); FastVector classVal = new FastVector(); classVal.addElement("1"); classVal.addElement("0"); Attribute label = new Attribute("label", classVal); attributes.addElement(label); return attributes; }
public Instances initializeInstances() { FastVector wekaAttributes = buildCosineAttributes(); Attribute label = (Attribute) wekaAttributes.lastElement(); Instances data = new Instances("semantic-space", wekaAttributes, 1000); data.setClass(label); return data; }
/** * @param predictions the predictions to use * @param classIndex the class index * @return the probabilities */ private double[] getProbabilities(FastVector predictions, int classIndex) { // sort by predicted probability of the desired class. double[] probs = new double[predictions.size()]; for (int i = 0; i < probs.length; i++) { NominalPrediction pred = (NominalPrediction) predictions.elementAt(i); probs[i] = pred.distribution()[classIndex]; } return probs; }
/** 构造分类器,主要及时对数据格式,类标,类别数目等进行说明 */ public MessageClassify() throws Exception { String nameOfDataset = "MessageClassification"; FastVector attributes = new FastVector(2); attributes.addElement(new Attribute("Message", (FastVector) null)); FastVector classValues = new FastVector(2); // 类标向量,共有两类 classValues.addElement("0"); classValues.addElement("1"); attributes.addElement(new Attribute("Class", classValues)); instances = new Instances(nameOfDataset, attributes, 100); // 可以把instance认为是行,attribute认为是列 instances.setClassIndex(instances.numAttributes() - 1); // 类表在instance中的那列 }
public void testEvaluationMode() throws Exception { int cind = 0; for (int i = 0; i < ThresholdSelector.TAGS_EVAL.length; i++) { ((ThresholdSelector) m_Classifier) .setEvaluationMode( new SelectedTag(ThresholdSelector.TAGS_EVAL[i].getID(), ThresholdSelector.TAGS_EVAL)); m_Instances.setClassIndex(1); FastVector result = useClassifier(); assertTrue(result.size() != 0); } }
/** * Get the list of labels for nominal attribute creation. * * @return the list of labels for nominal attribute creation */ public String getNominalLabels() { String labelList = ""; for (int i = 0; i < m_Labels.size(); i++) { if (i == 0) { labelList = (String) m_Labels.elementAt(i); } else { labelList += "," + (String) m_Labels.elementAt(i); } } return labelList; }
public void testDesignatedClass() throws Exception { int cind = 0; for (int i = 0; i < ThresholdSelector.TAGS_OPTIMIZE.length; i++) { ((ThresholdSelector) m_Classifier) .setDesignatedClass( new SelectedTag( ThresholdSelector.TAGS_OPTIMIZE[i].getID(), ThresholdSelector.TAGS_OPTIMIZE)); m_Instances.setClassIndex(1); FastVector result = useClassifier(); assertTrue(result.size() != 0); } }
/** * Determines the output format based on the input format and returns this. In case the output * format cannot be returned immediately, i.e., hasImmediateOutputFormat() returns false, then * this method will called from batchFinished() after the call of preprocess(Instances), in which, * e.g., statistics for the actual processing step can be gathered. * * @param inputFormat the input format to base the output format on * @return the output format * @throws Exception in case the determination goes wrong */ protected Instances determineOutputFormat(Instances inputFormat) throws Exception { Instances result; FastVector atts; int i; int numAtts; Vector<Integer> indices; Vector<Integer> subset; Random rand; int index; // determine the number of attributes numAtts = inputFormat.numAttributes(); if (inputFormat.classIndex() > -1) numAtts--; if (m_NumAttributes < 1) { numAtts = (int) Math.round((double) numAtts * m_NumAttributes); } else { if (m_NumAttributes < numAtts) numAtts = (int) m_NumAttributes; } if (getDebug()) System.out.println("# of atts: " + numAtts); // determine random indices indices = new Vector<Integer>(); for (i = 0; i < inputFormat.numAttributes(); i++) { if (i == inputFormat.classIndex()) continue; indices.add(i); } subset = new Vector<Integer>(); rand = new Random(m_Seed); for (i = 0; i < numAtts; i++) { index = rand.nextInt(indices.size()); subset.add(indices.get(index)); indices.remove(index); } Collections.sort(subset); if (inputFormat.classIndex() > -1) subset.add(inputFormat.classIndex()); if (getDebug()) System.out.println("indices: " + subset); // generate output format atts = new FastVector(); m_Indices = new int[subset.size()]; for (i = 0; i < subset.size(); i++) { atts.addElement(inputFormat.attribute(subset.get(i))); m_Indices[i] = subset.get(i); } result = new Instances(inputFormat.relationName(), atts, 0); if (inputFormat.classIndex() > -1) result.setClassIndex(result.numAttributes() - 1); return result; }