Shingoの数学ノート

プログラミングと機械学習のメモ

Pythonで文章の近さを計算しよう3(cos類似度)

日付:    カテゴリ: 自然言語処理


Pythonで文章の近さを計算しよう2の続き。今回はベクトル化された文章の類似度を測る。


文章の類似度を計算する

通常、2次元ベクトルや3次元ベクトルの距離や近さを測るには、ユークリッド距離等が使われる。しかし、文章のベクトルの次元は単語数なので、多い文章になると次元が10000を超えることもしばしばある。また、文章のベクトルは0が非常に多い。(スパースなデータという。)このようなデータは、ユークリッド距離で計算するには向いていない。そこで、次元が多く、スパースなデータにとっておきのcos類似度の計算方法を紹介する。

cos類似度

$n$を次元数とすると、$u=(u_1,\cdots,u_n)$、$v=(v_1,\cdots,v_n)$のcos類似度は次で表される。 \[ cossim(u,v)=\frac{u \cdot v}{|u||v|}=\frac{u_1v_1+\cdots+u_nv_n}{\sqrt{u_1^2+ \cdots + u_n^2 }\sqrt{v_1^2+ \cdots + v_n^2 }} \]

式で書くと難しそうに思えるので、実際に計算して文章AとBのcos類似度を求めてみる。

文章 リンゴ 食べる バナナ 買う 長さ
A. 私はリンゴを食べる。 1 1 1 0 0 $\sqrt{3}$
B. 私はバナナを食べる。 1 0 1 1 0 $\sqrt{3}$
文章A × 文章B 1 0 1 0 0

cos類似度は、文章A×文章Bの和をとって、長さで割ることで算出できる。

\[ 文章Aと文章Bのcos類似度=\frac{1+0+1+0+0}{\sqrt{3} \times \sqrt{3}}=\frac{2}{3} \]

これと同じように、3つの文章のbag-of-wordsからcos類似度を計算してみる。


文章1 文章2 cos類似度
私はリンゴを食べる。 私はバナナを食べる。 0.66
私はリンゴを食べる。 私はリンゴを買う。 0.66
私はバナナを食べる。 私はリンゴを買う。 0.33

bag-of-wordsでベクトル化した後のcos類似度は、共起している度合いを計算しているイメージである。共通している単語が多ければ、cos類似度が上がり、似ていると判断される。

Pythonでの実装

bag-of-wordsでベクトル化さえできていれば、cos類似度の計算は簡単だ。vector_bowは前回の記事で作成したものを使用する。


import numpy as np
def cos_sim(v1,v2):
    return np.dot(v1,v2)/np.linalg.norm(v1)/np.linalg.norm(v2)
v1,v2,v3=vector_bow
print("v1={},v2={},v3={}".format(v1,v2,v3))
print("v1とv2のcos類似度:{:.03f}".format(cos_sim(v1,v2)))
print("v1とv3のcos類似度:{:.03f}".format(cos_sim(v1,v3)))
print("v2とv3のcos類似度:{:.03f}".format(cos_sim(v2,v3)))
実行結果
v1=[1. 1. 1. 0. 0.],v2=[0. 1. 1. 1. 0.],v3=[1. 1. 0. 0. 1.]
v1とv2のcos類似度:0.667
v1とv3のcos類似度:0.667
v2とv3のcos類似度:0.333

まとめと今後の課題

いったんテキストから類似度の算出までを記載した。シンプルではあるが、そこそこ直感と合っていて、理解もしやすい。

類似度を算出できれば、次のことができる。

  • 単語が似た文章の検索
  • 文章のクラスタリング

ここら辺はできると思うので、ぜひ試していただきたい。


しかし、bag-of-wordsを使用したcos類似度は以下の欠点も存在する。

  • 次元数が多いため、計算量が膨大。
  • 表記揺れで、同じ意味の単語でも別の単語として区別する。(「楽しい」、「たのしい」等)
  • 別の単語を同じ単語として認識する。(「うまい(美味い、上手い)等」)
  • 文章の並び順を考慮していない。
  •   
  • 「〜ない」等の否定語の考慮(否定しているのに類似度が高いと出てしまう。)

上3つはSVD、LDAなどの次元削減によって解決できる。筆者の余裕があれば今後ブログを書いていく予定。

下2つは並び順を考慮しなければならないので、構文解析や、ディープラーニング等をして解決する。こちらもできれば書いていきたい。


Comment Box is loading comments...