package cc.mallet.cluster.evaluate;
import cc.mallet.cluster.Clustering;
import cc.mallet.types.InstanceList;
/**
* Evaluate a Clustering using the B-Cubed evaluation metric. See
* Bagga & Baldwin, "Algorithms for scoring coreference chains."
*
* Unlike other metrics, this evaluation awards points to correct
* singleton clusters.
*
* @author "Aron Culotta" <culotta@degas.cs.umass.edu>
* @version 1.0
* @since 1.0
* @see ClusteringEvaluator
*/
public class BCubedEvaluator extends ClusteringEvaluator {
double macroPrecision;
double macroRecall;
int macroNumInstances;
public BCubedEvaluator () {
macroPrecision = macroRecall = 0.0;
macroNumInstances = 0;
}
public String evaluate (Clustering truth, Clustering predicted) {
double[] vals = getEvaluationScores(truth, predicted);
return "pr=" + vals[0] + " re=" + vals[1] + " f1=" + vals[2];
}
public String evaluateTotals () {
double pr = macroPrecision / macroNumInstances;
double re = macroRecall / macroNumInstances;
double f1 = (2 * pr * re) / (pr + re);
return "pr=" + pr + " re=" + re + " f1=" + f1;
}
@Override
public double[] getEvaluationScores(Clustering truth, Clustering predicted) {
double precision = 0.0;
double recall = 0.0;
InstanceList instances = truth.getInstances();
for (int i = 0; i < instances.size(); i++) {
int trueLabel = truth.getLabel(i);
int predLabel = predicted.getLabel(i);
int[] trueIndices = truth.getIndicesWithLabel(trueLabel);
int[] predIndices = predicted.getIndicesWithLabel(predLabel);
int correct = 0;
for (int j = 0; j < predIndices.length; j++) {
for (int k = 0; k < trueIndices.length; k++)
if (trueIndices[k] == predIndices[j])
correct++;
}
precision += (double)correct / predIndices.length;
recall += (double)correct / trueIndices.length;
}
macroPrecision += precision;
macroRecall += recall;
macroNumInstances += instances.size();
precision /= instances.size();
recall /= instances.size();
return new double[]{precision, recall, (2 * precision * recall / (precision + recall))};
}
}