/// <summary> Calculates the performance stats for the desired class and return /// results as a set of Instances. /// /// </summary> /// <param name="classIndex">index of the class of interest. /// </param> /// <returns> datapoints as a set of instances. /// </returns> public virtual Instances getCurve(FastVector predictions, int classIndex) { if ((predictions.size() == 0) || (((NominalPrediction) predictions.elementAt(0)).distribution().Length <= classIndex)) { return null; } double totPos = 0, totNeg = 0; double[] probs = getProbabilities(predictions, classIndex); // Get distribution of positive/negatives for (int i = 0; i < probs.Length; i++) { NominalPrediction pred = (NominalPrediction) predictions.elementAt(i); if (pred.actual() == weka.classifiers.evaluation.Prediction_Fields.MISSING_VALUE) { System.Console.Error.WriteLine(GetType().FullName + " Skipping prediction with missing class value"); continue; } if (pred.weight() < 0) { System.Console.Error.WriteLine(GetType().FullName + " Skipping prediction with negative weight"); continue; } if (pred.actual() == classIndex) { totPos += pred.weight(); } else { totNeg += pred.weight(); } } Instances insts = makeHeader(); int[] sorted = Utils.sort(probs); TwoClassStats tc = new TwoClassStats(totPos, totNeg, 0, 0); double threshold = 0; double cumulativePos = 0; double cumulativeNeg = 0; for (int i = 0; i < sorted.Length; i++) { if ((i == 0) || (probs[sorted[i]] > threshold)) { tc.TruePositive = tc.TruePositive - cumulativePos; tc.FalseNegative = tc.FalseNegative + cumulativePos; tc.FalsePositive = tc.FalsePositive - cumulativeNeg; tc.TrueNegative = tc.TrueNegative + cumulativeNeg; threshold = probs[sorted[i]]; insts.add(makeInstance(tc, threshold)); cumulativePos = 0; cumulativeNeg = 0; if (i == sorted.Length - 1) { break; } } NominalPrediction pred = (NominalPrediction) predictions.elementAt(sorted[i]); if (pred.actual() == weka.classifiers.evaluation.Prediction_Fields.MISSING_VALUE) { System.Console.Error.WriteLine(GetType().FullName + " Skipping prediction with missing class value"); continue; } if (pred.weight() < 0) { System.Console.Error.WriteLine(GetType().FullName + " Skipping prediction with negative weight"); continue; } if (pred.actual() == classIndex) { cumulativePos += pred.weight(); } else { cumulativeNeg += pred.weight(); } /* System.out.println(tc + " " + probs[sorted[i]] + " " + (pred.actual() == classIndex)); */ /*if ((i != (sorted.length - 1)) && ((i == 0) || (probs[sorted[i]] != probs[sorted[i - 1]]))) { insts.add(makeInstance(tc, probs[sorted[i]])); }*/ } return insts; }
private Instance makeInstance(TwoClassStats tc, double prob) { int count = 0; double[] vals = new double[11]; vals[count++] = tc.TruePositive; vals[count++] = tc.FalseNegative; vals[count++] = tc.FalsePositive; vals[count++] = tc.TrueNegative; vals[count++] = tc.FalsePositiveRate; vals[count++] = tc.TruePositiveRate; vals[count++] = tc.Precision; vals[count++] = tc.Recall; vals[count++] = tc.Fallout; vals[count++] = tc.FMeasure; vals[count++] = prob; return new Instance(1.0, vals); }