计算Kullback的有效方法–;Python中的Leibler分歧
我必须计算数千个离散概率向量之间的(KLD)。目前,我正在使用以下代码,但它的方式太慢,我的目的。我想知道是否有更快的方法来计算KL散度计算Kullback的有效方法–;Python中的Leibler分歧,python,performance,numpy,scipy,statistics,Python,Performance,Numpy,Scipy,Statistics,我必须计算数千个离散概率向量之间的(KLD)。目前,我正在使用以下代码,但它的方式太慢,我的目的。我想知道是否有更快的方法来计算KL散度 import numpy as np import scipy.stats as sc #n is the number of data points kld = np.zeros(n, n) for i in range(0, n): for j in range(0, n):
import numpy as np
import scipy.stats as sc
#n is the number of data points
kld = np.zeros(n, n)
for i in range(0, n):
for j in range(0, n):
if(i != j):
kld[i, j] = sc.entropy(distributions[i, :], distributions[j, :])
默认情况下,Scipy以1D数组的形式邀请输入,给我们一个标量,这在列出的问题中完成。在内部,这个函数也允许,我们可以在这里滥用它来获得矢量化的解决方案
从-
scipy.stats.entropy(pk,qk=None,base=None)
如果只有概率pk
如果给定,熵计算为S=-sum(pk*log(pk),
轴=0)
如果qk不是None,则计算Kullback-Leibler散度S=
总和(pk*log(pk/qk),轴=0)
在我们的例子中,我们针对所有行对每一行进行熵计算,对这两个嵌套循环执行求和归约,以便在每次迭代时都有一个标量。因此,输出数组的形状为(M,M)
,其中M
是输入数组中的行数
现在,这里的问题是,stats.entropy()
将沿着轴=0
求和,因此我们将向它提供两个版本的分布
,这两个版本的分布都将把生长维度带到轴=0
,以便沿着它进行缩减,另外两个轴交错-(M,1)
&(1,M)
给我们一个(M,M)
形状的输出阵列,使用广播
因此,解决我们的问题的矢量化且更有效的方法是-
from scipy import stats
kld = stats.entropy(distributions.T[:,:,None], distributions.T[:,None,:])
运行时测试和验证-
In [15]: def entropy_loopy(distrib):
...: n = distrib.shape[0] #n is the number of data points
...: kld = np.zeros((n, n))
...: for i in range(0, n):
...: for j in range(0, n):
...: if(i != j):
...: kld[i, j] = stats.entropy(distrib[i, :], distrib[j, :])
...: return kld
...:
In [16]: distrib = np.random.randint(0,9,(100,100)) # Setup input
In [17]: out = stats.entropy(distrib.T[:,:,None], distrib.T[:,None,:])
In [18]: np.allclose(entropy_loopy(distrib),out) # Verify
Out[18]: True
In [19]: %timeit entropy_loopy(distrib)
1 loops, best of 3: 800 ms per loop
In [20]: %timeit stats.entropy(distrib.T[:,:,None], distrib.T[:,None,:])
10 loops, best of 3: 104 ms per loop
美丽的。谢谢你。@Amir很乐意帮忙。甚至我都不知道scipy的熵会支持广播,它确实支持,这是NumPy最好的东西!这正是我的想法,这让我甚至不去尝试它!你能给我一个关于你为什么写这样的矩阵变量“distrib.T[:,:,None]”和“distrib.T[:,None,:]”的参考吗?“无”的作用是什么?为什么要转置这两个矩阵?@Amir表示“无”或将引入单体维度,或是将维度从现有二维数组形状扩展到三维数组的方法。这种转置是必要的,因为在内部,函数求和横轴=0,这是为了复制所有元素相乘元素的和,我们将在每次迭代的问题循环代码中得到这些元素。希望这是有意义的@KillianTattan我猜
stats.entropy(分布[0,无].T,分布[1:].T)
。如何使用scipy获得python中具有最小KL散度的概率分布生成器?