Python中互信息的实现

13 投票
2 回答
25893 浏览
提问于 2025-04-18 12:52

我在使用Python的机器学习库中的互信息函数时遇到了一些问题,特别是这个函数:
sklearn.metrics.mutual_info_score(labels_true, labels_pred, contingency=None)

(http://scikit-learn.org/stable/modules/generated/sklearn.metrics.mutual_info_score.html)

我正在尝试实现我在斯坦福NLP教程网站上找到的一个例子:

example

这个网站在这里:http://nlp.stanford.edu/IR-book/html/htmledition/mutual-information-1.html#mifeatsel2

问题是我总是得到不同的结果,但还没搞清楚原因。

我理解互信息和特征选择的概念,但我就是不明白它在Python中是怎么实现的。我做的是根据NLP网站的例子,给mutual_info_score方法提供两个数组,但它输出的结果却不一样。还有一个有趣的事实是,不管你怎么改变这些数组中的数字,结果往往都是一样的。我是不是应该使用Python特定的其他数据结构,或者说这个问题的根源是什么?如果有人以前成功使用过这个函数,对我来说会非常有帮助,谢谢你的时间。

2 个回答

-4

下面的代码应该能给出一个结果: 0.00011053558610110256

c=np.concatenate([np.ones(49), np.zeros(27652), np.ones(141), np.zeros(774106) ])
t=np.concatenate([np.ones(49), np.ones(27652), np.zeros(141), np.zeros(774106)])

computeMI(c,t)
13

我今天遇到了同样的问题。经过几次尝试,我发现真正的原因是:如果你严格按照自然语言处理(NLP)的教程,你会使用log2,但实际上,sklearn.metrics.mutual_info_score使用的是自然对数(以e为底,欧拉数)。我在sklearn的文档中没有找到这个细节……

我通过以下方式验证了这一点:

import numpy as np
def computeMI(x, y):
    sum_mi = 0.0
    x_value_list = np.unique(x)
    y_value_list = np.unique(y)
    Px = np.array([ len(x[x==xval])/float(len(x)) for xval in x_value_list ]) #P(x)
    Py = np.array([ len(y[y==yval])/float(len(y)) for yval in y_value_list ]) #P(y)
    for i in xrange(len(x_value_list)):
        if Px[i] ==0.:
            continue
        sy = y[x == x_value_list[i]]
        if len(sy)== 0:
            continue
        pxy = np.array([len(sy[sy==yval])/float(len(y))  for yval in y_value_list]) #p(x,y)
        t = pxy[Py>0.]/Py[Py>0.] /Px[i] # log(P(x,y)/( P(x)*P(y))
        sum_mi += sum(pxy[t>0]*np.log2( t[t>0]) ) # sum ( P(x,y)* log(P(x,y)/( P(x)*P(y)) )
    return sum_mi

如果你把这个np.log2改成np.log,我觉得结果会和sklearn的一样。唯一的区别是,当这个方法返回0时,sklearn会返回一个非常接近0的数字。(当然,如果你不在乎对数的底数,直接用sklearn就好,我的这段代码只是演示,效果不太好……)

顺便说一下,1)sklearn.metrics.mutual_info_score可以接受列表和np.array;2)sklearn.metrics.cluster.entropy也使用对数,而不是log2。

补充一下,关于“相同的结果”,我不太确定你具体指的是什么。一般来说,向量中的值并不是最重要的,重要的是值的“分布”。你关注的是P(X=x)、P(Y=y)和P(X=x,Y=y),而不是具体的值x和y。

撰写回答