2013-08-22 15 views
10

Moim celem jest, aby obliczyć odległość KL pomiędzy następującymi dokumentami tekstowymi:Obliczanie Kullback-Leiblera (KL) odległości między tekstem dokumentów elektronicznych za pomocą 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 

I przede wszystkim wektoryzowane dokumenty w celu łatwego mają zastosowanie 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] 

następnie zastosowano następujący kod do obliczania KL odległość między tekstami:

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 

Oto wynik powyższego kodu: [0.0, 0.602059991328, 0.0]. Teksty 1 i 3 są całkowicie różne, ale odległość między nimi wynosi 0, natomiast teksty 1 i 2, które są bardzo powiązane, mają odległość 0.602059991328. To nie jest dokładne.

Czy ktoś ma pojęcie o tym, co nie robię dobrze w odniesieniu do KL? Wielkie dzięki za twoje sugestie.

+1

Cóż, v [0] == v [2], zatem w funkcji kl p-q wynosi 0, wtedy suma wynosi 0. Co rozumiesz przez "wektoryzację dokumentów"? Twoje wektory 1 i 3 są równe. –

+0

@ J.Martinot_Lagarde dzięki za twoją obserwację. tu wektoryzacja oznacza posiadanie liczby częstotliwości każdego słowa w dokumencie i użycie wartości do przedstawienia dokumentu. Problem polega na tym, jak przedstawić każdy dokument w taki sposób, aby odległość między dwoma dokumentami można było dokładnie obliczyć za pomocą KL. – Tiger1

Odpowiedz

1

Po nieco googlowania, aby podkreślić koncepcję KL, myślę, że twój problem wynika z wektoryzacji: porównujesz liczbę pojawień się różnych słów. Powinieneś albo połączyć indeks kolumny z jednym słowem, albo użyć słownika:

# 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] 

Następnie możesz użyć swojej funkcji kl.

Aby automatycznie wektoryzować do dyktafonu, zobacz How to count the frequency of the elements in a list? (collections.Counter jest dokładnie tym, czego potrzebujesz). Następnie możesz zapętlić zjednoczenie kluczy słowników, aby obliczyć odległość KL.

+0

To nie zadziała ... Zgodnie z [wikipedia] (http://en.wikipedia.org/wiki/Kullback%E2%80%93Leibler_divergence#Definition): "Rozbieżność K-L jest określona tylko jeśli P i Q zarówno sumy do 1, a jeśli Q (i) = 0 oznacza P (i) = 0. " Nie wiem, jak to zrobić. – Jaime

+1

Dobrze. Najbardziej przydatny artykuł, jaki znalazłem, to http://staff.science.uva.nl/~tsagias/?p=185. Obliczają na przecięciu słownictwa zamiast związku i dodają "workaroud", gdy słownictwo jest zbyt różne. Na końcu jest nawet kod. W każdym razie problem leży w części "wektoryzacji". –

+0

Dzięki @ J.Martinot-Lagarde, przyjrzę się temu artykułowi. – Tiger1

0

Potencjalny problem może dotyczyć definicji KL użytkownika KL. Przeczytaj stronę wikipedii, aby uzyskać wzór: http://en.wikipedia.org/wiki/Kullback%E2%80%93Leibler_divergence

Należy pamiętać, że pomnożenie (p-q) przez wynik logu. Zgodnie z formułą KL, powinno to być tylko p:

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

To może pomóc ...

+2

formuła, którą tam masz, służy do niesymetrycznego rozbieżności KL. Wystarczy rzucić okiem na symetryczną rozbieżność KL, zrozumiesz mnie lepiej. – Tiger1

+1

Rozumiem potrzebę symetrycznego KL, ale uważam, że to, co robisz, nie da ci tego. Aby uzyskać wersję, sprawdź rozbieżności Jensen-Shannon: http://en.wikipedia.org/wiki/Jensen%E2%80%93Shannon_divergence – dpb

+0

Mam już rozbieżność Jensen-Shannon na miejscu. Odpowiedziałem nawet na pytanie dotyczące rozbieżności JS na przepełnieniu stosu. Oprócz rozbieżności JS istnieją inne symetryczne wersje rozbieżności KL. – Tiger1

25

Choć nienawidzę, aby dodać kolejną odpowiedź, istnieją dwa punkty tutaj. Po pierwsze, jak zauważył Jaime w komentarzach, dywergencja KL (lub odległość - zgodnie z poniższą dokumentacją są takie same) służy do pomiaru różnicy między rozkładem prawdopodobieństwa. Oznacza to w zasadzie, że to, co przekazujesz do funkcji, powinno być dwiema tablicopodobnymi elementami, z których każda suma wynosi 1.

Po drugie, scipy najwidoczniej to zaimplementuje, ze schematem nazewnictwa bardziej powiązanym z obszarem informacji teoria. Funkcja "entropia":

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

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

Z dokumentów:

Jeśli qk nie Brak, a następnie obliczyć względną entropii (znany również jako dywergencja kullbacka-leiblera lub Odległość Kullback-Leibler) S = suma (pk * log (pk/qk), oś = 0).

Bonus z tej funkcji, a także to, że będzie normalizacji wektorów Państwo przekazać go jeśli nie sumują się do 1 (choć oznacza to, że trzeba być ostrożnym z tablicami ty przebieg - to znaczy, w jaki sposób są one zbudowany z danych).

Mam nadzieję, że to pomoże, a przynajmniej biblioteka to zapewnia, więc nie trzeba kodu własnego.

Powiązane problemy