2013-08-22 21 views
10

我的目標是計算下面的文本文檔之間的KL距離:庫勒巴克 - 萊布勒(KL)文本的文檔之間的距離的計算使用numpy的

1)The boy is having a lad relationship 
2)The boy is having a boy relationship 
3)It is a lovely day in NY 

我首先的矢量化的文件,以便輕鬆所適用numpy的

1)[1,1,1,1,1,1,1] 
2)[1,2,1,1,1,2,1] 
3)[1,1,1,1,1,1,1] 

我然後應用以下代碼用於計算文本之間KL距離:

import numpy as np 
import math 
from math import log 

v=[[1,1,1,1,1,1,1],[1,2,1,1,1,2,1],[1,1,1,1,1,1,1]] 
c=v[0] 
def kl(p, q): 
    p = np.asarray(p, dtype=np.float) 
    q = np.asarray(q, dtype=np.float) 
    return np.sum(np.where(p != 0,(p-q) * np.log10(p/q), 0)) 
for x in v: 
    KL=kl(x,c) 
    print KL 

以上是上述代碼的結果:[0.0, 0.602059991328, 0.0]。 文本1和3完全不同,但它們之間的距離爲0,而高度相關的文本1和2的距離爲0.602059991328。這是不準確的。

有沒有人有一個想法,我不正確地對待吉隆坡?非常感謝您的建議。

+1

那麼,v [0] == v [2],因此在kl函數p-q中是0,那麼和就是0.你是什麼意思「矢量化文檔」?你的載體1和3是相等的。 –

+0

@ J.Martinot_Lagarde感謝您的觀察。在此處進行矢量化意味着要對文檔中的每個單詞進行頻率計數,並使用這些值來表示文檔。這裏的問題是如何以這樣的方式表示每個文檔,使得使用KL可以精確計算兩個文檔之間的距離。 – Tiger1

回答

1

經過一番谷歌搜索以瞭解KL的概念後,我認爲你的問題是由於矢量化:你正在比較不同單詞的出現次數。你要麼你列指數之鏈接到一個字,或使用dictionnary:

# The boy is having a lad relationship It lovely day in NY 
1)[1 1 1 1  1 1 1   0 0  0 0 0] 
2)[1 2 1 1  1 0 1   0 0  0 0 0] 
3)[0 0 1 0  1 0 0   1 1  1 1 1] 

然後你可以使用你的KL功能。

要自動矢量化爲一個詞典,請參見How to count the frequency of the elements in a list?collections.Counter正是您需要的)。然後,您可以遍歷字典鍵的聯合來計算KL距離。

+0

這將無法正常工作...根據[wikipedia](http://en.wikipedia.org/wiki/Kullback%E2%80%93Leibler_divergence#Definition):「K-L散度只在P和Q均加1,如果Q(i)= 0意味着P(i)= 0。不知道該怎麼去做。 – Jaime

+1

對。我找到的最有用的文章是http://staff.science.uva.nl/~tsagias/?p=185。他們計算詞彙而不是聯合的交集,並且當詞彙太不同時添加「workaroud」。最後還有代碼。無論如何,問題在於這裏的「矢量化」部分。 –

+0

謝謝@ J.Martinot-Lagarde,我會看看這篇文章。 – Tiger1

0

潛在的問題可能出現在您對吉隆坡的NP定義中。請閱讀維基百科頁面獲取公式:http://en.wikipedia.org/wiki/Kullback%E2%80%93Leibler_divergence

請注意,您將(p-q)乘以日誌結果。按照KL公式,這應該只是號碼:

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

這可以幫助...

+2

您有的公式是針對非對稱KL散度。只要看看對稱的KL分歧,你會更好地理解我。 – Tiger1

+1

我明白對稱KL的必要性,但我相信你在做什麼不會給你。對於一個版本,請查看Jensen-Shannon分歧:http://en.wikipedia.org/wiki/Jensen%E2%80%93Shannon_divergence – dpb

+0

我已經有了Jensen-Shannon的定義。我甚至回答了有關堆棧溢出JS分歧的問題。除了JS分歧外,還有KL分歧的其他對稱版本。 – Tiger1

25

雖然我討厭添加另一種答案,有兩點在這裏。首先,正如Jaime在評論中指出的那樣,KL分歧(或距離 - 根據以下文獻,它們是相同的)旨在衡量概率分佈之間的差異。這基本上意味着你傳遞給函數的東西應該是兩個數組類似的東西,其中每一個的元素總和爲1.

其次,scipy顯然確實實現了這一點,命名方案與信息領域更相關理論。的功能是「熵」:

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

http://docs.scipy.org/doc/scipy-dev/reference/generated/scipy.stats.entropy.html

從文檔:

如果QK不是無,然後計算相對熵(也稱爲 相對熵或Kullback-Leibler距離)S = sum(pk * log(pk/qk),axis = 0)。

此功能以及的好處是,它會歸你通過它的載體,如果他們不和爲1(儘管這意味着你必須要小心你傳遞的陣列 - 即他們是如何從數據構建)。

希望這會有所幫助,至少有一個圖書館提供它,所以不必編寫自己的代碼。