言語処理100本ノック 2015の挑戦記録です。環境はUbuntu 16.04 LTS + Python 3.5.2 :: Anaconda 4.1.1 (64-bit)です。過去のノックの一覧はこちらからどうぞ。
第9章: ベクトル空間法 (I)
enwiki-20150112-400-r10-105752.txt.bz2は,2015年1月12日時点の英語のWikipedia記事のうち,約400語以上で構成される記事の中から,ランダムに1/10サンプリングした105,752記事のテキストをbzip2形式で圧縮したものである.このテキストをコーパスとして,単語の意味を表すベクトル(分散表現)を学習したい.第9章の前半では,コーパスから作成した単語文脈共起行列に主成分分析を適用し,単語ベクトルを学習する過程を,いくつかの処理に分けて実装する.第9章の後半では,学習で得られた単語ベクトル(300次元)を用い,単語の類似度計算やアナロジー(類推)を行う.
なお,問題83を素直に実装すると,大量(約7GB)の主記憶が必要になる. メモリが不足する場合は,処理を工夫するか,1/100サンプリングのコーパスenwiki-20150112-400-r100-10576.txt.bz2を用いよ.
###87. 単語の類似度
85で得た単語の意味ベクトルを読み込み,"United States"と"U.S."のコサイン類似度を計算せよ.ただし,"U.S."は内部的に"U.S"と表現されていることに注意せよ.
####出来上がったコード:
# coding: utf-8
import pickle
from collections import OrderedDict
from scipy import io
import numpy as np
fname_dict_index_t = 'dict_index_t'
fname_matrix_x300 = 'matrix_x300'
def cos_sim(vec_a, vec_b):
'''コサイン類似度の計算
ベクトルvec_a、vec_bのコサイン類似度を求める
戻り値:
コサイン類似度
'''
norm_ab = np.linalg.norm(vec_a) * np.linalg.norm(vec_b)
if norm_ab != 0:
return np.dot(vec_a, vec_b) / norm_ab
else:
# ベクトルのノルムが0だと似ているかどうかの判断すらできないので最低値
return -1
# 辞書読み込み
with open(fname_dict_index_t, 'rb') as data_file:
dict_index_t = pickle.load(data_file)
# 行列読み込み
matrix_x300 = io.loadmat(fname_matrix_x300)['matrix_x300']
# 'United States'と'U.S'のコサイン類似度表示
vec_a = matrix_x300[dict_index_t['United_States']]
vec_b = matrix_x300[dict_index_t['U.S']]
print(cos_sim(vec_a, vec_b))
####実行結果:
0.832760703627
###コサイン類似度
コサイン類似度は、2つのベクトルがどれくらい同じ向きを向いているのかを表す指標です。単語のままだと似ているかどうかの判定ができませんが、単語をベクトル化したおかげで、コサイン類似度を調べれば似ているかどうかが判定できるようになりました。
ベクトル$ \boldsymbol{A} $、$ \boldsymbol{B} $のコサイン類似度は次の式で計算できます。
$$ \frac{\boldsymbol{A}\cdot\boldsymbol{B}}{|\boldsymbol{A}|,|\boldsymbol{B}|} $$
ちなみに$ |\boldsymbol{A}| $はベクトル$ \boldsymbol{A} $の長さ(ノルム)で、numpy.linalg.norm()
で求められます。
コサイン類似度は最大が1で、値が大きい方が似ていることを示します。今回の実行結果は0.83くらいでしたので、「United States」と「U.S.」はかなり近い言葉だと推測したことになります。Wikipediaの記事を食わせただけで「United States」と「U.S.」が近い言葉だと推測するのは結構すごいことですね。
コサイン類似度の詳細は、「コサイン類似度」などでググってみてください。
88本目のノックは以上です。誤りなどありましたら、ご指摘いただけますと幸いです。
実行結果には、100本ノックで用いるコーパス・データで配布されているデータの一部が含まれます。この第9章で用いているデータのライセンスはクリエイティブ・コモンズ 表示-継承 3.0 非移植(日本語訳)です。