/*
* This file is part of ELKI:
* Environment for Developing KDD-Applications Supported by Index-Structures
*
* Copyright (C) 2017
* ELKI Development Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.lmu.ifi.dbs.elki.evaluation.clustering;
import de.lmu.ifi.dbs.elki.evaluation.clustering.ClusterContingencyTable.Util;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
/**
* BCubed measures.
*
* Reference:
* <p>
* A. Bagga and B. Baldwin<br />
* Entity-based cross-document coreferencing using the Vector Space Model<br />
* Proc. COLING '98 Proceedings of the 17th international conference on
* Computational linguistics
* </p>
*
* @author Sascha Goldhofer
* @since 0.5.0
*/
@Reference(authors = "A. Bagga and B. Baldwin", //
title = "Entity-based cross-document coreferencing using the Vector Space Model", //
booktitle = "Proc. COLING '98 Proceedings of the 17th international conference on Computational linguistics", //
url = "http://dx.doi.org/10.3115/980451.980859")
public class BCubed {
/**
* Result cache
*/
protected double bCubedPrecision = -1.0, bCubedRecall = -1.0;
/**
* Constructor.
*
* @param table Contingency table
*/
protected BCubed(ClusterContingencyTable table) {
super();
bCubedPrecision = 0.0;
bCubedRecall = 0.0;
for(int i1 = 0; i1 < table.size1; i1++) {
final int[] row = table.contingency[i1];
for(int i2 = 0; i2 < table.size2; i2++) {
final int c = row[i2];
if(c > 0) {
// precision of one item
double precision = 1.0 * c / row[table.size2];
// precision for all items in cluster
bCubedPrecision += (precision * c);
// recall of one item
double recall = 1.0 * c / table.contingency[table.size1][i2];
// recall for all items in cluster
bCubedRecall += (recall * c);
}
}
}
final int total = table.contingency[table.size1][table.size2];
bCubedPrecision = bCubedPrecision / total;
bCubedRecall = bCubedRecall / total;
}
/**
* Get the BCubed Precision (first clustering) (normalized, 0 = unequal)
*
* @return BCubed Precision
*/
public double precision() {
return bCubedPrecision;
}
/**
* Get the BCubed Recall (first clustering) (normalized, 0 = unequal)
*
* @return BCubed Recall
*/
public double recall() {
return bCubedRecall;
}
/**
* Get the BCubed F1-Measure
*
* @return BCubed F1-Measure
*/
public double f1Measure() {
return Util.f1Measure(precision(), recall());
}
}