言語処理100本ノック 2015の94本目「WordSimilarity-353での類似度計算」の記録です。
ファイル上の単語間の類似度を計算します。技術的には今までやったことに対して、コーディングを少し変えるだけといった感じです。
参考リンク
リンク | 備考 |
---|---|
094.WordSimilarity-353での類似度計算_1.ipynb | 回答プログラムのGitHubリンク |
094.WordSimilarity-353での類似度計算_2.ipynb | Gensim版回答プログラムのGitHubリンク |
素人の言語処理100本ノック:94 | 言語処理100本ノックで常にお世話になっています |
環境
種類 | バージョン | 内容 |
---|---|---|
OS | Ubuntu18.04.01 LTS | 仮想で動かしています |
pyenv | 1.2.15 | 複数Python環境を使うことがあるのでpyenv使っています |
Python | 3.6.9 | pyenv上でpython3.6.9を使っています 3.7や3.8系を使っていないことに深い理由はありません パッケージはvenvを使って管理しています |
上記環境で、以下のPython追加パッケージを使っています。通常のpipでインストールするだけです。
種類 | バージョン |
---|---|
gensim | 3.8.1 |
numpy | 1.17.4 |
pandas | 0.25.3 |
課題
第10章: ベクトル空間法 (II)
第10章では,前章に引き続き単語ベクトルの学習に取り組む.
94. WordSimilarity-353での類似度計算
The WordSimilarity-353 Test Collectionの評価データを入力とし,1列目と2列目の単語の類似度を計算し,各行の末尾に類似度の値を追加するプログラムを作成せよ.このプログラムを85で作成した単語ベクトル,90で作成した単語ベクトルに対して適用せよ.
課題補足
ZIPファイルをダウンロードするといくつかファイルがあって、その中のcombined.tab
を使いました。
1行目がヘッダ行で、最初2列に単語が2つあり、その類似度を人間が判定した数値が3列目に来るようです(10点満点の類似度)。これをコサイン類似度では、どの程度の類似度かを計算して4列目に設定します。
Word 1 Word 2 Human (mean)
love sex 6.77
tiger cat 7.35
tiger tiger 10.00
book paper 7.46
computer keyboard 7.62
computer internet 7.58
plane car 5.77
train car 6.31
telephone communication 7.50
後略
回答
自作回答プログラム 094.WordSimilarity-353での類似度計算_1.ipynb
import csv
import numpy as np
import pandas as pd
# 保存時に引数を指定しなかったので'arr_0'に格納されている
matrix_x300 = np.load('./../09.ベクトル空間法 (I)/085.matrix_x300.npz')['arr_0']
print('matrix_x300 Shape:', matrix_x300.shape)
group_t = pd.read_pickle('./../09.ベクトル空間法 (I)/083_group_t.zip')
# コサイン類似度計算
def get_cos_similarity(line):
try:
v1 = matrix_x300[group_t.index.get_loc(line[0])]
v2 = matrix_x300[group_t.index.get_loc(line[1])]
# ベクトルが全てゼロの場合は-1を返す
if np.count_nonzero(v1) == 0 \
or np.count_nonzero(v2) == 0:
line.extend([-1])
else:
line.extend([np.dot(v1, v2) / (np.linalg.norm(v1) * np.linalg.norm(v2))])
except:
line.extend([-1])
return line
# 評価データ読み込み
with open('./combined.tab') as file_in:
reader = csv.reader(file_in, delimiter='\t')
header = next(reader)
result = [get_cos_similarity(line) for line in reader]
with open('094.combine_1.txt', 'w') as file_out:
writer = csv.writer(file_out, delimiter='\t', lineterminator='\n')
writer.writerows(result)
回答解説
今までの内容を組み合わせただけなので、技術的には特に解説することがないです。
結果はヘッダ行なしのタブ区切りテキストファイルで出力しています。当然なのかもしれませんが、人間が設定した類似度とだいぶ違いますね。
これは類似単語を抽出するわけではないので、1秒もかからず終わります。
love sex 6.77 0.28564147035983395
tiger cat 7.35 0.848285056343736
tiger tiger 10.00 1.0000000000000002
book paper 7.46 0.4900762715360672
computer keyboard 7.62 0.09513773584009234
computer internet 7.58 0.2659421289876719
plane car 5.77 0.48590778050802136
train car 6.31 0.2976902017313069
telephone communication 7.50 0.1848868997304664
television radio 6.77 0.7724947668094843
後略
Gensim版回答プログラム 094.WordSimilarity-353での類似度計算_2.ipynb
import csv
import numpy as np
from gensim.models import Word2Vec
model = Word2Vec.load('./090.word2vec.model')
print(model)
# コサイン類似度計算
def get_cos_similarity(line):
try:
v1 = model.wv[line[0]]
v2 = model.wv[line[1]]
# ベクトルが全てゼロの場合は-1を返す
if np.count_nonzero(v1) == 0 \
or np.count_nonzero(v2) == 0:
line.extend([-1])
else:
line.extend([np.dot(v1, v2) / (np.linalg.norm(v1) * np.linalg.norm(v2))])
except KeyError:
line.extend([-1])
return line
# 評価データ読み込み
with open('./combined.tab') as file_in:
reader = csv.reader(file_in, delimiter='\t')
header = next(reader)
result = [get_cos_similarity(line) for line in reader]
with open('094.combine_2.txt', 'w') as file_out:
writer = csv.writer(file_out, delimiter='\t', lineterminator='\n')
writer.writerows(result)
回答解説
自作プログラムと大差ないです。
結果は、自作プログラムよりGensim版の方がずっと結果がいいですね。
love sex 6.77 0.5481953
tiger cat 7.35 0.7811356
tiger tiger 10.00 1.0
book paper 7.46 0.5549785
computer keyboard 7.62 0.6746693
computer internet 7.58 0.6775914
plane car 5.77 0.5873176
train car 6.31 0.6229327
telephone communication 7.50 0.52026355
television radio 6.77 0.7744317
後略