我在实现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教程网站上找到的示例:
该网站在这里:http://nlp.stanford.edu/IR-book/html/htmledition/mutual-information-1.html#mifeatsel2
问题是我不断得到不同的结果,尚未找出原因。
我理解互信息和特征选择的概念,我只是不明白它在Python中是如何实现的。我所做的是根据NLP网站的示例向mutual_info_score方法提供两个数组,但它输出了不同的结果。另一个有趣的事实是,无论你如何调整和更改这些数组中的数字,你很可能会得到相同的结果。我应该使用Python特定的另一种数据结构,还是有什么问题?如果有人过去成功使用过这个函数,对我将会有很大帮助,感谢你的时间。
回答:
我今天遇到了同样的问题。经过几次尝试后,我找到了真正的原因:如果你严格按照NLP教程,你会使用log2,但sklearn.metrics.mutual_info_score使用的是自然对数(以e为底,欧拉数)。我在sklearn文档中没有找到这个细节…
我通过以下方式验证了这一点:
import numpy as npdef 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
也使用log,而不是log2
编辑:至于“相同的结果”,我不确定你真正指的是什么。一般来说,矢量中的值并不重要,重要的是值的“分布”。你关心的是P(X=x), P(Y=y)和P(X=x,Y=y),而不是值x,y。