2013-04-08 33 views
8

我還有一個問題,我希望有人能幫助我。Jensen-Shannon Divergence

我使用Jensen-Shannon-Divergence來測量兩個概率分佈之間的相似度。相似性得分似乎是正確的,因爲它們落在1和0之間,1表示分佈是相等的。

但是,我不確定實際上是否存在某個錯誤,並想知道某人是否能夠說'是的,這是正確的'或'不,你做錯了什麼'。

下面是代碼:

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, 1.0/10, 0] 
    q = [0, 1.0/10, 9.0/10] 
    print J.Jensen_Shannon_divergence(p, q) 

的問題是,我覺得成績比較兩個文本文檔時,例如不夠高。但是,這純粹是一種主觀的感覺。

任何幫助,一如既往,讚賞。

+1

也許嘗試輸出比較(https://www.mathworks.com/matlabcentral/fileexchange/20689-jensen-shannon-divergence)或者在Octave中運行它。 – 2013-04-08 13:22:09

+0

'if p [x]!= 0.0或p [x]!= 0'看起來很奇怪。 – 2013-04-08 13:31:24

+0

如果使用p [x]!= 0.0或p [x]!= 0來確保我們不考慮條目是零,無論它們是浮點數還是整數,那麼您所指的是?或者你的意思是說這條線很奇怪嗎?非常感謝。 – Martyn 2013-04-08 14:03:15

回答

6

獲取已知散度分佈的一些數據,並將結果與​​這些已知值進行比較。

BTW:在KL_divergence總和可以使用zip built-in function這樣被改寫:

sum(_p * log(_p/_q) for _p, _q in zip(p, q) if _p != 0) 

這有很多「噪音」的確,距離也更「Python化」。與0.00的雙重比較是沒有必要的。

14

請注意,下面的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)) 

還要注意的是測試用例的問題看起來犯錯? p分佈的總和不會增加到1.0。

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

+1

不需要導入和使用'norm',因爲如果熵不等於1,熵就會使分佈正常化(參見http://docs.scipy.org/doc/scipy-dev/reference/generated/scipy .stats.entropy.html)。然而,像這樣計算'_M','_P'和'_Q'需要是'numpy.ndarray'對象。 – Tur1ng 2015-07-09 18:03:32

+4

@ Tur1ng注意規範是必要的,因爲'_M'的計算要求'_P'和'_Q'是概率分佈(已經規範化)。還要注意,列表被強制爲numpy數組,所以這很好:'[2,4]/np.array([1,2])' – 2015-07-14 17:13:35

+0

正確。注意,謝謝 – Tur1ng 2015-07-16 13:33:13

0

明確以下的Wikipedia article數學:[?這個MATLAB腳本]

def jsdiv(P, Q): 
    """Compute the Jensen-Shannon divergence between two probability distributions. 

    Input 
    ----- 
    P, Q : array-like 
     Probability distributions of equal length that sum to 1 
    """ 

    def _kldiv(A, B): 
     return np.sum([v for v in A * np.log2(A/B) if not np.isnan(v)]) 

    P = np.array(P) 
    Q = np.array(Q) 

    M = 0.5 * (P + Q) 

    return 0.5 * (_kldiv(P, M) +_kldiv(Q, M)) 
相關問題