gpt4 book ai didi

python - 使用 numpy 计算成对互信息的最佳方法

转载 作者:IT老高 更新时间:2023-10-28 20:36:49 32 4
gpt4 key购买 nike

对于 m x n 矩阵,计算所有列对 (n x n) 的互信息的最佳(最快)方法是什么?

作者 mutual information ,我的意思是:

I(X, Y) = H(X) + H(Y) - H(X,Y)

其中H(X)指的是X的香农熵。

目前我正在使用 np.histogram2dnp.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 的列(计算它们的成对互信息)?

我也想知道:

  1. 是否有高效的方法来映射函数对np.arrays的列(或行)进行操作(可能像np.vectorize,看起来更像装饰师)?

  2. 对于这个特定的计算(互信息)是否还有其他优化的实现方式?

最佳答案

我不能建议对 n*(n-1)/2 的外循环进行更快的计算向量,但您的 calc_MI(x, y, bins) 实现可以简化如果您可以使用 scipy 版本 0.13 或 scikit-learn .

在 scipy 0.13 中,lambda_ 参数被添加到 scipy.stats.chi2_contingency此参数控制函数计算的统计量。如果您使用 lambda_="log-likelihood"(或 lambda_=0),即对数似然比被退回。这通常也称为 G 或 G2 统计量。以外2*n 的因子(其中 n 是意外事件中的样本总数表),这互信息。所以你可以实现 calc_MI如:

from scipy.stats import chi2_contingency

def calc_MI(x, y, bins):
c_xy = np.histogram2d(x, y, bins)[0]
g, p, dof, expected = chi2_contingency(c_xy, lambda_="log-likelihood")
mi = 0.5 * g / c_xy.sum()
return mi

这个和你的实现之间的唯一区别是这个实现使用自然对数而不是以 2 为底的对数(所以它用“nats”而不是“bits”来表达信息)。如果你真的更喜欢位,只需将 mi 除以 log(2)。

如果你有(或可以安装)sklearn(即 scikit-learn),你可以使用 sklearn.metrics.mutual_info_score ,并将 calc_MI 实现为:

from sklearn.metrics import mutual_info_score

def calc_MI(x, y, bins):
c_xy = np.histogram2d(x, y, bins)[0]
mi = mutual_info_score(None, None, contingency=c_xy)
return mi

关于python - 使用 numpy 计算成对互信息的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20491028/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com