一. 前言
又GET了一项技能。在做聚类算法的时候,由于要评估所提出的聚类算法的好坏,于是需要与一些已知的算法对比,或者用一些人工标注的标签来比较,于是用到了聚类结果的评估指标。我了解了以下几项。
首先定义几个量:(借鉴该博客:http://blog.csdn.net/luoleicn/article/details/5350378)
TP:是指被聚在一类的两个量被正确的分类了(即在标准标注里属于一类的两个对象被聚在一类)
TN:是指不应该被聚在一类的两个对象被正确地分开了(即在标准标注里不是一类的两个对象在待测结果也没聚在一类)
FP:指不应该放在一类的对象被错误的放在了一类。(即在标准标注里不是一类,但在待测结果里聚在一类)
FN:指不应该分开的对象被错误的分开了。(即在标准标注里是一类,但在待测结果里没聚在一类)
P = TP + FP
N = TN + FN
1.准确率、识别率:(rank Index) RI
accuracy = (TP + TN)/(P + N)
2.错误率、误分类率
error rate = (FP + FN)/(P + N)
3.敏感度
sensitivity = TP / P
4.特效性
specificity = TN / N
5.精度
precision = TP / (TP + FP)
6.召回率
recall = TP / (TP + FN)
7.RI 其实就是 1 的 accuracy
8.F度量
P为precision
R为recall
9.NMI(normalized mutual information)
10 Jaccard
J = TP / (TP + F)
二、JAVA实现(未优化)
其中很多重复代码,还没有优化。。。
package others;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.rmi.CORBA.Util;
import org.graphstream.algorithm.measure.NormalizedMutualInformation;
/*function:常用的聚类评价指标有purity, precision, recall, RI 和 F-score,jaccard
* @param:
* @author:Wenbao Li
* @Data:2015-07-13
*/
public class ClusterEvaluation {
public static void main(String[] args){
int[] A = {1,3,3,3,3,3,3,2,1,0,2,0,2,0,2,1,1,0,1,1};
int[] B = {2,2,0,0,0,3,2,2,3,1,3,1,0,1,2,1,0,1,3,3};
double purity = Purity(A,B);
System.out.println("purity\t\t"+purity);
System.out.println("Pre\t\t"+Precision(A,B));
System.out.println("Recall\t\t"+Recall(A,B));
System.out.println("RI(Accuracy)\t\t"+RI(A,B));
System.out.println("Fvalue\t\t"+F_score(A,B));
System.out.println("NMI\t\t"+NMI(A,B));
}
/*
* 计算一个聚类结果的簇的个数,以及每一簇中的对象个数,
*/
public static Map<Integer,Set<Integer>> clusterDistri(int[] A){
Map<Integer,Set<Integer>> clusterD = new HashMap<Integer,Set<Integer>>();
int max = -1;
for(int i = 0;i< A.length;i++){
if(max < A[i]){
max = A[i];
}
}
for(int i = 0;i< A.length;i++){
int temp = A[i];
if(temp < max+1){
if(clusterD.containsKey(temp)){
Set<Integer> set = clusterD.get(temp);
set.add(i+1);
clusterD.put(temp, set);
}else{
Set<Integer> set = new HashSet<Integer>();
set.add