テキストマイニングで文字の類似ベクトルとN-gramベクトル、コサイン類似度について学びました。
自力で書いたコードを載せておきます。
文字の頻度ベクトル、N-gramベクトル
文字の類似ベクトルはtextに含まれる文字の種類毎の個数を要素としたベクトル
N-gramベクトルはtextに含まれる連続したN文字の種類毎の個数を要素としたベクトル
とのこと。
N-gramベクトルにおいてN=1なら文字の類似ベクトルと同じですね。
def text_frequency(text):
dic_vec={}
for i in text:
if i in dic_vec.keys():
dic_vec[i]+=1
else:
dic_vec[i]=1
return dic_vec
def N_gram(N,text):
N_gram_vec={}
for i in range(len(text)-N+1):
if text[i:N+i] in N_gram_vec.keys():
N_gram_vec[text[i:N+i]]+=1
else:
N_gram_vec[text[i:N+i]]=1
return N_gram_vec
コサイン類似度
コサイン類似度は二つのベクトルがどれだけ似ているかをcosで数値化してみよう、といったものです。
先ほどの文字の頻度ベクトルとN-gramベクトルを用いることで、比較したい文をベクトル化し、このコサイン類似度の考え方で類似度を数値化できるわけですね。
二つのベクトルが似ているほどこの値は1に近くなります。
逆に似ていない場合は0に近くなります。
cosを考えていますが出現頻度は負の値を取らないので-1にはなりませんね。
最初勘違いしていました。
下の関数は2つの辞書を受け取りコサイン類似度を返します。
アルファベット(五十音)の順番が近いほど良いと考えsortedではkeyの順序で並び替えました。
でもkeyの並び順が近いからと言って文が似ていることになるのでしょうか?
valueの順序を並び替えるべきなのかもしれない?
次回の講義で聞けたらいいな……
※追記(2019/06/11)
コサイン類似度では要素が完全に一致しなければなりません
したがって片方の辞書にしかないkeyに関して、もう片方の辞書のkeyのvakueは0とした新しい辞書なりリストなりを生成しなくてはいけませんね
def cos_similarlity(dic1,dic2):
sorted(dic1.items(), key=lambda pair: pair[0])
sorted(dic2.items(), key=lambda pair: pair[0])
arr1 = np.array([i[1]
for i in sorted(dic1.items(), key=lambda pair: pair[0])])
arr2 = np.array([i[1]
for i in sorted(dic2.items(), key=lambda pair: pair[0])])
if arr1.shape==arr2.shape:
return np.dot(arr1,arr2.transpose())/(np.linalg.norm(arr1)*np.linalg.norm(arr2))
else:
return -1