I(A,B)=H(A)-H(A|B)=sigma x p(x)*log(1/p(x)) - sigma y p(y) sigma x p(x|y)*log(1/p(x|y))=
则把B改成[4 1 4 4 4 4 4 1 1 1 1 7 4 4 7 7 7], NMI不变。
NMI的最大值为1,当A,B两个向量完全一样时取到。此时I(A,B)=H(A)=H(B),NMI=2*I(A,B)/(H(A)+H(B)=1.
当A = [1,1,1,1,1];
当A = [1,1,1,1,1];
用C++写了一个比较10个不同结果的两两的NMI的平均值。
#include
#include
#include
#include
#include
using std::map;
using std::vector;
#define MAXN 76000
int result[MAXN][10];
map hash1[10];
int cnt[10];
int n;
int px[MAXN];
int py[MAXN];
struct
{
int other_one;
int times;
joint_p()
{
other_one=-1;
}
};
vector joint_ps[MAXN];
map hash2[MAXN];
int index[MAXN];
int main()
{
//scanf("%d",&n);
for(int i=0;i<10;i++)
{
char name[100];
name[0]=i+'0';
name[1]='.';
name[2]='o';
name[3]='\0';
freopen(name,"r",stdin);
//printf("name: %s\n",name);
int cur=0;
cnt[i]=0;
while(scanf("%d",&cluster)!=EOF)
{
if(!hash1[i][cluster]){
hash1[i][cluster]=++cnt[i];
}
result[++cur][i]=hash1[i][cluster];
}
n=cur;
}
//printf("n:%d\n",n);
int total_times=0;
double total=0;
for(int i=0;i<10;i++)
for(int j=i+1;j<10;j++)
{
total_times++;
int max_cluster_ID=cnt[i]>cnt[j]?cnt[i]:cnt[j];
for(int k=1;k<=max_cluster_ID;k++){
joint_ps[k].clear();
hash2[k].clear();
joint_p no_use;
joint_ps[k].push_back(no_use);
index[k]=0;
px[k]=0;
py[k]=0;
}
for(int k=1;k<=n;k++)
{
px[result[k][i]]++;
py[result[k][j]]++;
}
for(int k=1;k<=n;k++)
{
joint_p p;
if(!hash2[result[k][i]][result[k][j]])
{
hash2[result[k][i]][result[k][j]]=++index[result[k][i]];
joint_p p;
p.other_one=result[k][j];
p.times=1;
joint_ps[result[k][i]].push_back(p);
}
else
{
joint_ps[result[k][i]][hash2[result[k][i]][result[k][j]]].times++;
}
}
double I=0;
for(int k=1;k<=max_cluster_ID;k++)
{
if(joint_ps[k].size()>1)
{
for(int l=1;l
{
//printf("%d %d %d\n",k,joint_ps[k][l].other_one,joint_ps[k][l].times);
I+=(double)joint_ps[k][l].times/n*log((double)joint_ps[k][l].times/(px[k]*py[joint_ps[k][l].other_one])*n)/log(2.0);
}
}
}
double Hx=0,Hy=0;
for(int k=1;k<=max_cluster_ID;k++)
{
if(px[k]>0)
{
//printf("%d/%d
Hx-=(double)px[k]/n*log((double)px[k]/n)/log(2.0);
}
if(py[k]>0)
{
Hy-=(double)py[k]/n*log((double)py[k]/n)/log(2.0);
}
}
//printf("I: %.3lf
double NMI;
total+=NMI;
printf("%d and %d
}
printf("average NMI: %.3lf\n",total/total_times);
return 0;
}
对于A = [1 1 1 1 1 1 2 2 2 2 2 2 3 3 3 3 3];