【发布时间】:2013-12-27 18:24:11
【问题描述】:
对于 m x n 矩阵,计算所有列对 (n x n) 的互信息的最佳(最快)方法是什么?
mutual information,我的意思是:
I(X, Y) = H(X) + H(Y) - H(X,Y)
其中H(X)指的是X的香农熵。
目前我正在使用 np.histogram2d 和 np.histogram 来计算联合 (X,Y) 和单个 (X 或 Y) 计数。对于给定的矩阵 A(例如 250000 X 1000 的浮点矩阵),我正在做一个嵌套的 for 循环,
n = A.shape[1]
for ix = arange(n)
for jx = arange(ix+1,n):
matMI[ix,jx]= calc_MI(A[:,ix],A[:,jx])
肯定有更好/更快的方法来做到这一点?
顺便说一句,我还在数组的列(按列或按行操作)上寻找映射函数,但还没有找到一个好的通用答案。
这是我的完整实现,遵循the Wiki page 中的约定:
import numpy as np
def calc_MI(X,Y,bins):
c_XY = np.histogram2d(X,Y,bins)[0]
c_X = np.histogram(X,bins)[0]
c_Y = np.histogram(Y,bins)[0]
H_X = shan_entropy(c_X)
H_Y = shan_entropy(c_Y)
H_XY = shan_entropy(c_XY)
MI = H_X + H_Y - H_XY
return MI
def shan_entropy(c):
c_normalized = c / float(np.sum(c))
c_normalized = c_normalized[np.nonzero(c_normalized)]
H = -sum(c_normalized* np.log2(c_normalized))
return H
A = np.array([[ 2.0, 140.0, 128.23, -150.5, -5.4 ],
[ 2.4, 153.11, 130.34, -130.1, -9.5 ],
[ 1.2, 156.9, 120.11, -110.45,-1.12 ]])
bins = 5 # ?
n = A.shape[1]
matMI = np.zeros((n, n))
for ix in np.arange(n):
for jx in np.arange(ix+1,n):
matMI[ix,jx] = calc_MI(A[:,ix], A[:,jx], bins)
虽然我的嵌套for 循环的工作版本以合理的速度完成它,但我想知道是否有更优化的方法将calc_MI 应用于A 的所有列(以成对计算它们互信息)?
我也想知道:
是否有有效的方法来映射函数以对
np.arrays的列(或行)进行操作(可能像np.vectorize,看起来更像一个装饰器)?对于这个特定的计算(互信息)是否还有其他优化的实现方式?
【问题讨论】:
-
您能否扩展您的示例代码以包含
calc_MI和A的示例输入?制作它,以便我们可以复制、粘贴和运行。将极大地帮助任何试图回答您的问题的人。 -
请阅读此sscce.org 并更新您的示例代码以包含
calc_MI和A的示例输入。 -
我之前的评论是在我打算回应建议时无意中输入的。感谢您指向 sscce.org。
-
对于您当前的方法,这是一个准确的自包含示例吗? pastebin.com/kbzyvA6K.
-
如果您的矩阵大小为
(n, m),则没有简单的方法可以仅对您所追求的n * (n - 1) / 2唯一值的计算进行矢量化,尽管进行矢量化计算通常更快完整笛卡尔积中的n * n值,即使有重复项。这样做的问题是它需要一次创建所有中间计算对象。使用上述方法,您将不得不想出一种创建 4Dhistogramdd的方法...我认为它不适用于您的庞大数据集。我会研究 Cython 或 C 扩展...
标签: python performance numpy scipy information-theory