Jensen-Shannon分歧

Mar*_*tyn 14 python metrics distance

我有另一个问题,我希望有人可以帮助我.

我正在使用Jensen-Shannon-Divergence来测量两个概率分布之间的相似性.相似性得分似乎是正确的,因为它们在1和0之间,假设一个使用基数2对数,0表示分布相等.

但是,我不确定某个地方是否确实存在错误,并且想知道某人是否可以说"是的,这是正确的"或"不,你做错了什么".

这是代码:

from numpy import zeros, array
from math import sqrt, log


class JSD(object):
    def __init__(self):
        self.log2 = log(2)


    def KL_divergence(self, p, q):
        """ Compute KL divergence of two vectors, K(p || q)."""
        return sum(p[x] * log((p[x]) / (q[x])) for x in range(len(p)) if p[x] != 0.0 or p[x] != 0)

    def Jensen_Shannon_divergence(self, p, q):
        """ Returns the Jensen-Shannon divergence. """
        self.JSD = 0.0
        weight = 0.5
        average = zeros(len(p)) #Average
        for x in range(len(p)):
            average[x] = weight * p[x] + (1 - weight) * q[x]
            self.JSD = (weight * self.KL_divergence(array(p), average)) + ((1 - weight) * self.KL_divergence(array(q), average))
        return 1-(self.JSD/sqrt(2 * self.log2))

if __name__ == '__main__':
    J = JSD()
    p = [1.0/10, 9.0/10, 0]
    q = [0, 1.0/10, 9.0/10]
    print J.Jensen_Shannon_divergence(p, q)
Run Code Online (Sandbox Code Playgroud)

例如,在比较两个文本文档时,我觉得分数不够高.然而,这纯粹是一种主观感受.

任何帮助一如既往地受到赞赏.

Dou*_*ore 20

请注意,下面的scipy熵调用是Kullback-Leibler分歧.

请参阅:http://en.wikipedia.org/wiki/Jensen%E2%80%93Shannon_divergence

#!/usr/bin/env python
from scipy.stats import entropy
from numpy.linalg import norm
import numpy as np

def JSD(P, Q):
    _P = P / norm(P, ord=1)
    _Q = Q / norm(Q, ord=1)
    _M = 0.5 * (_P + _Q)
    return 0.5 * (entropy(_P, _M) + entropy(_Q, _M))
Run Code Online (Sandbox Code Playgroud)

还要注意问题中的测试用例看起来有误吗?p分布的总和不会增加到1.0.

见:http://www.itl.nist.gov/div898/handbook/eda/section3/eda361.htm

  • @ Tur1ng注意到需要规范,因为`_M`的计算要求`_P`和`_Q`是概率分布(已经规范化).还要注意列表被强制为numpy数组,所以这很好:`[2,4]/np.array([1,2])` (4认同)

Xav*_*hot 12

由于Jensen-Shannon 距离( distance.jensenshannon) 已包含在 中Scipy 1.2,因此Jensen-Shannon 散度可作为 Jensen-Shannon 距离的平方获得:

from scipy.spatial import distance

distance.jensenshannon([1.0/10, 9.0/10, 0], [0, 1.0/10, 9.0/10]) ** 2
# 0.5306056938642212
Run Code Online (Sandbox Code Playgroud)


Ber*_*Ber 7

获取具有已知差异的分布的一些数据,并将结果与​​已知值进行比较.

BTW:KL_divergence中的总和可以使用zip内置函数重写,如下所示:

sum(_p * log(_p / _q) for _p, _q in zip(p, q) if _p != 0)
Run Code Online (Sandbox Code Playgroud)

这消除了许多"噪音",也更加"pythonic".双重比较,0.00没有必要.