如何计算大型稀疏概率矩阵的列信息熵

问题描述

我已使用 sklearn 的 CountVectorizer 将我的语料库(200 万个文档)转换为词袋稀疏矩阵。稀疏矩阵的形状约为 2000000 x 170000(即:语料库词汇中的 170k 个单词)。

我没有处理稀疏矩阵的经验,但已经设法对其执行简单的计算,例如计算整个语料库中每个单词的方差,因为它涉及简单的均值和平方运算矩阵。

我现在遇到的问题是我不知道如何有效地计算稀疏矩阵的逐列熵。目前,我正在遍历每一列并将单词出现概率作为列表提供给 scipy.stats.entropy,由于稀疏矩阵的大小,这需要很长时间。

为了清楚起见,举个例子:

# P: Column-wise word probability sparse matrix
P = [[0.2,0.0,0.5,0.3,0.0],[0.5,0.6,1.0,[0.0,0.1,0.5],[0.3,0.5]]

from scipy.stats import entropy
entropy_list = []
for index in range(P.shape[1]):
    entropy_list.append(entropy(P[:,index].todense()))

我希望获得一个长度为 170000 的数组,因为我正在计算语料库词汇中每个单词的熵。到目前为止,对我当前的代码进行计时,计算 10000 个单词的熵大约需要 25 分钟。按照这个速度,完成我的计算需要 7 个小时。谁能帮我找到更有效的方法

解决方法

使用 axis 参数,可以计算整个数组的逐列熵:

In [9]: x=np.random.rand(80,100)
In [13]: e1=entropy(x,axis=0)
In [14]: e2=np.array([entropy(x[:,i]) for i in range(100)])
In [15]: np.allclose(e1,e2)

次数:

In [16]: timeit e1=entropy(x,axis=0)
240 µs ± 13.5 µs per loop (mean ± std. dev. of 7 runs,1000 loops each)
In [17]: timeit e2=np.array([entropy(x[:,i]) for i in range(100)])
3.42 ms ± 7.1 µs per loop (mean ± std. dev. of 7 runs,100 loops each)

您的稀疏 P 可能太大而无法执行 P.A (toarray),但是您可以使用夹头、列块而不是一次一个来执行此操作.

对于 (2000000,170000) 形状,该矩阵的 csc 格式应该消耗更少的内存(小 indptr 数组),并且按列(或列集)迭代可能会更快。一般而言,稀疏矩阵索引涉及提取器矩阵和矩阵乘法,尽管 csc (.getcol) 或切片的列索引可能会有一些增强。

,

熵 H(X) = - sum(p(X) * log(p(X)))

  ion-slides {
    height: 95% !important;
  }

注意:如果列的总和不为 1,scipy.stats.entropy 会将它们归一化。

编辑:对于logP = np.ma.log(P).filled(0) entropy_list = -np.sum(np.multiply(P,logP),axis=0)

scipy.sparse.csr_matrix