筋トレ大学生によるアウトプット雑記

筋トレや読書のことをはじめとして、プログラミングその他日常生活における様々なことについて書いていきます。

Output Blog

主に筋トレ・プログラミングについて書きます

文章間の距離を求める3つの手法【自然言語処理】

スポンサーリンク

f:id:daimori1005:20191124103252j:plain
自然言語処理では現在、単語間距離や文章間の距離を素性に取ることが多くあります。
文章間の距離、類似度を求める方法はいくつかあります。
本記事では、メジャーかつ汎用性の高い3つの手法をpythonでの実装方法とともに紹介します。
プログラミングに興味がある方必見です。
是非ご覧ください。

文章間の距離を求める手法

文章間の距離を求める手法は以下の3つが代表的なものです。

  1. ユークリッド距離
  2. コサイン類似度
  3. Jaccard係数

効いたことがある方もない方もいると思います。

前提として、文章をベクトル化する必要があります。
ベクトル化には、tfidfやWord Embeddingなどの手法が代表されています。
こちらは後日紹介します。

それでは紹介していきます。

ユークリッド距離

ユークリッド距離は最も知られている距離の測り方です。
従来、2点間距離をピタゴラスの定理で求める方法として使われてきました。
f:id:daimori1005:20191122230128p:plain
この画像の青線の部分がユークリッド距離です。
ユークリッド距離=\sqrt{{(c-a)}^2+{(d-b)}^2}
と表すことができます。

次元数が上がった場合でも、この式の末尾に増えた次元の計算を増やしていくだけです。
理解もしやすい手法の1つですね。


類似度というよりは、単純な距離ということで文章にはコサイン類似度ほどは向いていません。
が、使われることもあります。

実際にpythonで実装する際は、こんな面倒な式を書く必要はありません。
Numpyを使うことで、一瞬で実装できます。

import numpy as np
np.linalg.norm(a-b)

これだけです。
入力はベクトルを代入した変数です。

コサイン類似度

コサイン類似度はとりわけ分散表現同士の比較に使われることが多い類似度計算手法です。
分散表現だけでなく、自然言語処理全般にも広く使われています。
コサイン類似度は、高次かつスパースなデータに向いています。

f:id:daimori1005:20191122232124p:plain
このθがコサイン類似度になります。

{\cos( \vec{q}, \vec{d} ) = \frac{ \vec{q} \cdot \vec{d}}{  |\vec{q}| |\vec{d}|}}
式はこんな感じになります。

コサイン類似度は、-1から1までの値を取ります。
類似度は-1に近いほど低く、1に近ければその逆です。


実装方法は簡単です。

import numpy as np
def cos_simil(x, y):
    return np.dot(x, y) / (np.linalg.norm(x) * np.linalg.norm(y))

簡単ですね~。

Jaccard係数

Jaccard係数は、元々集合の類似度を測る手法として使われていました。

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

集合中の共通要素に着目し、それが占める割合を表しています。
0から1の値を取り、値が大きいほど類似度は高くなります。

def jaccard(x,y):
    intersection = len(set.intersection(set(x), set(y)))    
    union = len(set.union(set(x), set(y)))            
    return Fraction(intersection , union)

入力には、文章中の単語リストを取ります。

どの手法を使うべきか

類似度計算手法は他にもたくさんあります。
どれを使えばいいかわからない方も多くいますよね。

文章を処理する場合には、基本的にコサイン類似度を使っておけば問題ないです。

精度などを高くしたい場合には、色々な手法を試してみることが一番です。
内容によって、適切な類似度手法は異なってきます。
なので、とりあえず試すことも大事です。

まとめ

いかがでしたか?
本記事では、類似度計算手法を3つまとめました。
自然言語処理では必須の技術ですので、覚えておくと良いですね。
こちらの記事もおすすめです。

スポンサーリンク