长度不等的两个离散概率分布之间的JS散度



我正在实现一个在线主题建模,如论文中所述-主题模型的在线趋势分析:#twitter趋势检测主题模型在线我需要找到更新前后每个主题t的单词分布之间的Jensen Shannon散度测度,如果该测度超过阈值,则将主题归类为新颖主题。在每次更新时,词汇表都会更新,因此在每次更新后,词汇表上的单词分布具有不同的长度。如何计算两个不等长度分布之间的JS散度?

Jensen Shannon散度是两个概率分布的相对熵,它是Kullback-Leibler(KL)散度的对称形式。这是当你正在比较的关于散度的两个自变量交换时,KL散度的平均值。

在继续之前,您需要对KL分歧有一个很好的了解。这里有一个很好的起点:

给定两种概率分布,即p和Q。

P=(p1....pi), Q=(q1....qi)
KL(P||Q)= sum([pi * log(pi/qi) for i in P if i in Q])

KL不是对称的,因此它不是度量。为了使KL对称,Jensen和Shannon提出了Jensen Shannon散度,这是当两个自变量交换时KL散度的平均值,即

JSd(P||Q)= (KL(P,Z) + KL(Q,Z))/2
where Z=(P + Q)/2

简言之,Jensen Shannon散度是两个概率分布之间的平均KL散度的平均值。

我希望这能有所帮助。

使用随机选择样本数据使p和q 的分布长度相同

def jsd(p, q, base=np.e):
    '''
        Implementation of pairwise `jsd` based on  
        https://en.wikipedia.org/wiki/Jensen%E2%80%93Shannon_divergence
    '''
    if len(p)>len(q):
        p = np.random.choice(p,len(q)) # random.choice make same length to p/q
    elif len(q)>len(p):
        q = np.random.choice(q,len(p))
    ## convert to np.array
    p, q = np.asarray(p), np.asarray(q)
    ## normalize p, q to probabilities
    p, q = p/p.sum(), q/q.sum()
    m = 1./2*(p + q)
    return scipy.stats.entropy(p,m, base=base)/2. +  scipy.stats.entropy(q, m, base=base)/2.

最新更新