LoginSignup
2
2

More than 5 years have passed since last update.

素人の言語処理100本ノック:88

Last updated at Posted at 2017-04-01

言語処理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を用いよ.

88. 類似度の高い単語10件

85で得た単語の意味ベクトルを読み込み,"England"とコサイン類似度が高い10語と,その類似度を出力せよ.

出来上がったコード:

main.py
# 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']

# 'England'とのコサイン類似度算出
vec_England = matrix_x300[dict_index_t['England']]
distances = [cos_sim(vec_England, matrix_x300[i])
        for i in range(0, len(dict_index_t))]

# 上位10件を表示
index_sorted = np.argsort(distances)
keys = list(dict_index_t.keys())
for index in index_sorted[-2:-12:-1]:       # トップに来る自分自身は除く
    print('{}\t{}'.format(keys[index], distances[index]))

実行結果:

実行結果
Scotland    0.6780631362432838
Australia   0.6439496692044923
Wales   0.6352223096061712
Italy   0.5993389833593241
Spain   0.5810143958505265
France  0.5711030646029182
Japan   0.5709618229888032
Germany 0.5377148103064543
Ireland 0.5374312543293124
Europe  0.4868884673753479

実行結果について

結果を見ると国名が並んでいるので、「England」が国であることは特徴として捉えているようです。また、「Scotland」や「Wales」や「Ireland」といったイギリスの国がTop10に入ってきたのも驚きです。
文章を構文解析したり同義語辞書を使ったりしている訳でもなく、単純にその単語の周辺で使われる文脈語をベクトル化しただけで、ここまでヒトの感覚に似た単語を提示できるのは、いろいろな可能性を感じさせてくれて面白いですね。

 
89本目のノックは以上です。誤りなどありましたら、ご指摘いただけますと幸いです。


実行結果には、100本ノックで用いるコーパス・データで配布されているデータの一部が含まれます。この第9章で用いているデータのライセンスはクリエイティブ・コモンズ 表示-継承 3.0 非移植日本語訳)です。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2