计算矩阵行之间的KL散度

2024-10-17 08:24:44 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个矩阵(numpy2darray),其中每一行都是一个有效的概率分布。我有另一个向量(numpy1d数组),又是一个prob dist,我需要计算矩阵每行和向量之间的KL散度。不使用for循环可以做到这一点吗?在

This question问了同样的问题,但没有一个答案能解决我的问题。其中一个建议使用for循环,因为我有大量数据,所以我想避免这个循环。另一个答案在tensorflow中提供了一个解决方案,但是我想要numpy数组。在

scipy.stats.entropy计算两个向量之间的KL散度,但当其中一个向量是矩阵时,我不知道如何使用它。在


Tags: 答案fordist矩阵数组this向量建议
1条回答
网友
1楼 · 发布于 2024-10-17 08:24:44

实际上,函数^{}可以进行矢量化计算,但必须适当地改变参数的形状才能使其工作。当输入是二维数组时,entropy期望保存概率向量。在p是二维,q是一维的情况下,必须在q中添加一个平凡的维度,以使参数与广播兼容。在

举个例子。首先,进口:

In [10]: import numpy as np                                                     

In [11]: from scipy.stats import entropy                                        

创建一个二维p,其行是概率向量,以及一维概率向量q

^{pr2}$

为了与矢量化结果进行比较,下面是使用Python循环计算的结果。在

In [19]: [entropy(t, q) for t in p]                                             
Out[19]: [0.32253909299531597, 0.17897138916539493, 0.2627905326857023]

为了使entropy进行矢量化计算,第一个参数的必须是概率向量,所以我们将p进行转置。然后,为了使qp.T兼容,我们将其重塑为具有形状(5,1)的二维数组(即它包含一个列):

In [20]: entropy(p.T, q.reshape(-1, 1))                                         
Out[20]: array([0.32253909, 0.17897139, 0.26279053])

注意:使用q.T作为第二个参数是很诱人的,但这行不通。在NumPy中,转置操作只交换现有维度的长度,而不会创建新维度。所以一维数组的转置就是它本身。也就是说,q.T与{}的形状相同。在


这个答案的旧版本如下。。。

您可以使用^{}^{}来执行此操作。这里有一个例子。在

In [17]: import numpy as np 
    ...: from scipy.stats import entropy 
    ...: from scipy.special import kl_div, rel_entr 

p和{}为例。 p具有形状(3,5);行是概率分布。q是长度为5的一维数组。在

In [18]: np.random.seed(8675309) 
    ...: p = np.random.rand(3, 5) 
    ...: p /= p.sum(axis=1, keepdims=True) 
    ...: q = np.random.rand(5) 
    ...: q /= q.sum()

这是您想要的计算,使用Python循环和scipy.stats.entropy。我在这里包括这个,这样可以将结果与下面的矢量化计算进行比较。在

In [19]: [entropy(t, q) for t in p]                                                                                                          
Out[19]: [0.32253909299531597, 0.17897138916539493, 0.2627905326857023]

我们构造了p和{},使得概率向量 每个和等于1。在这种情况下,上述结果也可以 用scipy.special.rel_entrscipy.special.kl_div进行矢量化计算。(我建议rel_entrkl_div添加和减去最终将在和中抵消的附加项,因此它所做的工作比必要的要多一些。) 这些函数只计算计算计算的逐点部分; 你必须对结果求和才能得到实际的熵或散度。在

In [20]: rel_entr(p, q).sum(axis=1)                                                                              
Out[20]: array([0.32253909, 0.17897139, 0.26279053])

In [21]: kl_div(p, q).sum(axis=1)                                                                                
Out[21]: array([0.32253909, 0.17897139, 0.26279053])

相关问题 更多 >