St_Hakky’s blog

Data Science / Human Resources / Web Applicationについて書きます

自然言語処理する時に計算するJaccard係数をPythonで計算する方法まとめ

こんにちは。

Jaccard係数についてPythonで実装する時にありそうなパターンをまとめてみました。また、自然言語処理の分野からJaccard係数についても調べました。

Jaccard係数

まず、Jaccard係数について説明して、その後実装の部分に入っていきます。

読み方

ジャッカード係数と呼びます。

Jaccard係数の定義

Jaccard係数を計算するには、ドキュメントをトークンのセットとして扱います。数式は次のとおりです。

$$
J (A, B) = \frac{|A \cap B|}{|A \cup B|}
$$

分母に和集合、分子に積集合の大きさをそれぞれ入れて計算します。これにより、要素 $A$ と $B$ の集合中にどの程度同じ要素があるかがわかり、この同じ要素が多いほど、値は1に近くなります。

Jaccard距離の定義

Jaccard係数に対してJaccard距離ということになると、似ているほど0に近くなって欲しいので、1-類似度ということになる。

$$
1 - J( A, B ) = \frac { \mid A \cup B \mid - \mid A \cap B \mid } { \mid A \cup B \mid }
$$

Jaccard係数の使い所

自然言語処理とかでは、文字列の距離や文章の距離を測るために用いられます。先にも述べたとおり、単語の文字一つ一つや、文章の単語一つ一つを集合の要素とみなし(もちろん重複は削除した上で)、2つの集合における積集合が和集合においてどのくらいの割合を示すかを見ることで、単語などの類似度を見ようというのに使われます。

自然言語処理のこういった類似度の計算方法は様々ありますが、Jaccard係数は最も簡単なのではないかと。ただ、文書などの順番の依存関係はJaccard係数だと破棄されるので、注意が必要です。

以下の資料がわかりやすかったです。

www.slideshare.net

Pythonでの実装

scratch

標準ライブラリ以外を使わずにで書くと、以下のようになります。x, yはリストを想定しています。

def jaccard_similarity(x, y):
    intersection = len(set.intersection(*[set(x), set(y)]))
    union = len(set.union(*[set(x), set(y)]))
    return intersection / float(union)

scikit-learn

一応ありますが、これはどうもベクトルのサイズが同じものでなければ比較ができないらしいので、自然言語処理などで使う際には微妙だと思います。

from sklearn.metrics import jaccard_similarity_score
jaccard_similarity_score(x, y)

nltk

自然言語処理の処理を行うときに何かとお世話になるnltkでは、以下のように処理を書くことができます。

また、入力はset型なのと、距離なので値が大きいほうが似ていないとなります。

from nltk.metrics import jaccard_distance
jaccard_distance(x, y)