2013-08-22 21 views
10

私の目標をされてnumpyの使用:カルバック・ライブラー(KL)テキスト文書間の距離の計算は、次のテキスト文書間のKL距離を計算するために

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です。これは正確ではありません。

KLに関して私が何をしていないのか誰にも分かりますか?あなたの提案に感謝します。

+1

さて、v [0] == v [2]で、kl関数p-qが0の場合、合計は0です。「ドキュメントをベクトル化する」とはどういう意味ですか?あなたのベクトル1と3は等しいです。 –

+0

@ J.Martinot_Lagardeあなたの観察に感謝します。ここでベクトル化するとは、ドキュメント内の各単語の頻度カウントを持ち、その値を使用してドキュメントを表すことを意味します。ここでの問題は、KLを使用して2つのドキュメント間の距離を正確に計算できるように各ドキュメントを表現する方法です。 – Tiger1

答えて

1

KLのコンセプトに甘んじると、私はあなたの問題はベクトル化によるものだと考えています。異なる単語の出現数を比較しています。列インデクスを1つの単語にリンクするか、辞書を使用してください:

# 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

それは動作しません... [ウィキペディア](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でした。それらは、組合の代わりに語彙の交わりを計算し、語彙があまりにも異なっている場合には「ワークラウド」を追加します。最後にコードがあります。とにかく問題はここの「ベクトル化」部分にあります。 –

+0

ありがとう@ J.Martinot-Lagarde、私は記事を見てみましょう。 – Tiger1

0

NPのKL定義に潜在的な問題がある可能性があります。式のためのウィキペディアページを読む:http://en.wikipedia.org/wiki/Kullback%E2%80%93Leibler_divergence

ログ結果に(p-q)を乗算することに注意してください。私は別の答えを追加するために嫌いますが、2つの点がここにあります

役立つかもしれ
return np.sum(np.where(p != 0,(p) * np.log10(p/q), 0)) 

...

+2

あなたが持っている数式は、非対称KL分岐のためのものです。対称KL発散を見るだけで、あなたは私をより良く理解できます。 – Tiger1

+1

私は対称KLの必要性を理解していますが、あなたがやっていることはあなたにそれを与えることはないと信じています。バージョンについては、Jensen-Shannon divergenceをチェックしてください:http://en.wikipedia.org/wiki/Jensen%E2%80%93Shannon_divergence – dpb

+0

私はすでにJensen-Shannonのデバージェンスを行っています。スタックオーバーフローに関するJSの相違に関する質問にも答えました。 JS発散に加えて、KL発散の他の対称バージョンが存在する。 – Tiger1

25

:KL式に従い、これが唯一のpでなければなりません。まず、Jaimeがコメントで指摘したように、KL発散(または距離 - 以下の文書によれば同じもの)は、確率分布の差を測定するように設計されています。これは、基本的に、関数に渡すものは2つの配列のようなものでなければならず、各要素の合計は1になることを意味します。

第2に、scipyは明らかに情報フィールドに関連した命名規則を実装しています理論。 QKがNoneでない場合

、その後も カルバック・ライブラー情報量として知られている相対的エントロピーを(計算または:ドキュメントから

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

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

:関数は、 "エントロピー" でありますKullback-Leibler distance)S = sum(pk * log(pk/qk)、axis = 0)。

また、この関数のボーナスは、合計すると1にならないベクトルを正規化するということです(ただし、渡す配列には注意する必要があります。データから構築される)。

これは役に立ちます。少なくとも、ライブラリで提供されているので、独自のコードを作成する必要はありません。

関連する問題