Python:快速/高效地实现Kullback Leibler散度,用于多个分布计算

时间:2014-07-23 14:35:40

标签: python performance algorithm statistics histogram

我有以下问题:我有一个20K离散分布矩阵(直方图),我需要计算这些对之间的KL分歧(KLD)。这样做的简单方法是使用两个for循环并通过标准KLD计算在每两个分布之间计算KLD。这需要时间。很多的时间。我想知道有一种基于矩阵/数组的计算方法。当然,我不是第一个遇到这个问题的人。不幸的是我是python的新手。任何帮助将不胜感激。 谢谢! 甲

3 个答案:

答案 0 :(得分:5)

我发现Computation of Kullback-Leibler (KL) distance between text-documents using numpy注意到SciPy实施了KLD

scipy.stats.entropy(pk, qk=None, base=None)

和文档可以在http://docs.scipy.org/doc/scipy-dev/reference/generated/scipy.stats.entropy.html找到;这应该使计算本身更快。

或者,an implementation in numpy

import numpy as np

def kl(p, q):
"""Kullback-Leibler divergence D(P || Q) for discrete distributions

Parameters
----------
p, q : array-like, dtype=float, shape=n
Discrete probability distributions.
"""
p = np.asarray(p, dtype=np.float)
q = np.asarray(q, dtype=np.float)

return np.sum(np.where(p != 0, p * np.log(p / q), 0))

请注意,将数据转换为numpy数组或从numpy数组转换数据的速度相对较慢;我不知道保留一个20k 1D numpy数组列表(可能是内存非常密集),或保留一个2D numpy数组并在切片上运行会更好。

答案 1 :(得分:1)

itertools是一个功能强大的工具,适用于不同实体之间的所有类型的排列等。除此之外,它通过产品功能实现双重“for”循环:

from itertools import product
KL = [kl(hist_mat[:,i],hist_mat[:,j]) for i,j in product( range(0,K), range(0,K) )]

K 是以成对方式比较的直方图的数量,
hist_mat 包含每个列中的直方图 kl =你对kullback leibler divergence的选择实现

唯一的缺点是,对于大型数据集,它仍然运行缓慢。

干杯, 甲

答案 2 :(得分:0)

这应该有用。

def kullback_leibler_divergence(X):

    """
    Finds the pairwise Kullback-Leibler divergence
    matrix between all rows in X.

    Parameters
    ----------
    X : array_like, shape (n_samples, n_features)
        Array of probability data. Each row must sum to 1.

    Returns
    -------
    D : ndarray, shape (n_samples, n_samples)
        The Kullback-Leibler divergence matrix. A pairwise matrix D such that D_{i, j}
        is the divergence between the ith and jth vectors of the given matrix X.

    Notes
    -----
    Based on code from Gordon J. Berman et al.
    (https://github.com/gordonberman/MotionMapper)

    References:
    -----------
    Berman, G. J., Choi, D. M., Bialek, W., & Shaevitz, J. W. (2014). 
    Mapping the stereotyped behaviour of freely moving fruit flies. 
    Journal of The Royal Society Interface, 11(99), 20140672.
    """

    X_log = np.log(X)
    X_log[np.isinf(X_log) | np.isnan(X_log)] = 0

    entropies = -np.sum(X * X_log, axis=1)

    D = np.matmul(-X, X_log.T)
    D = D - entropies
    D = D / np.log(2)
    D *= (1 - np.eye(D.shape[0]))

    return D
相关问题