言語処理100本ノック-94(Gensim使用):WordSimilarity-353での類似度計算

[言語処理100本ノック 2015](http://www.cl.ecei.tohoku.ac.jp/nlp100/)の94本目「WordSimilarity-353での類似度計算」の記録です。
ファイル上の単語間の類似度を計算します。技術的には今までやったことに対して、コーディングを少し変えるだけといった感じです。

# 参考リンク

|リンク|備考|
|:--|:--|
|[094.WordSimilarity-353での類似度計算_1.ipynb](https://github.com/YoheiFukuhara/nlp100/blob/master/10.%E3%83%99%E3%82%AF%E3%83%88%E3%83%AB%E7%A9%BA%E9%96%93%E6%B3%95%20(II)/094.WordSimilarity-353%E3%81%A7%E3%81%AE%E9%A1%9E%E4%BC%BC%E5%BA%A6%E8%A8%88%E7%AE%97_1.ipynb)|回答プログラムのGitHubリンク|
|[094.WordSimilarity-353での類似度計算_2.ipynb](https://github.com/YoheiFukuhara/nlp100/blob/master/10.%E3%83%99%E3%82%AF%E3%83%88%E3%83%AB%E7%A9%BA%E9%96%93%E6%B3%95%20(II)/094.WordSimilarity-353%E3%81%A7%E3%81%AE%E9%A1%9E%E4%BC%BC%E5%BA%A6%E8%A8%88%E7%AE%97_2.ipynb)|Gensim版回答プログラムのGitHubリンク|
|[素人の言語処理100本ノック:94](https://qiita.com/segavvy/items/4c3295bf2c0321bea5e2)|言語処理100本ノックで常にお世話になっています|

# 環境

|種類|バージョン|内容|
|:--|:--|:--|
|OS|Ubuntu18.04.01 LTS|仮想で動かしています|
|pyenv|1.2.15|複数Python環境を使うことがあるのでpyenv使っています|
|Python|3.6.9|pyenv上でpython3.6.9を使っています<br>3.7や3.8系を使っていないことに深い理由はありません<br>パッケージはvenvを使って管理しています|

上記環境で、以下のPython追加パッケージを使っています。通常のpipでインストールするだけです。

|種類|バージョン|
|:--|:--|
|gensim|3.8.1|
|numpy|1.17.4|
|pandas|0.25.3|


# 課題
## [第10章: ベクトル空間法 (II)](http://www.cl.ecei.tohoku.ac.jp/nlp100/#ch10)
> 第10章では，前章に引き続き単語ベクトルの学習に取り組む．

### 94. WordSimilarity-353での類似度計算
> [The WordSimilarity-353 Test Collection](http://www.cs.technion.ac.il/~gabr/resources/data/wordsim353/)の評価データを入力とし，1列目と2列目の単語の類似度を計算し，各行の末尾に類似度の値を追加するプログラムを作成せよ．このプログラムを85で作成した単語ベクトル，90で作成した単語ベクトルに対して適用せよ．

#### 課題補足
ZIPファイルをダウンロードするといくつかファイルがあって、その中の`combined.tab`を使いました。
1行目がヘッダ行で、最初2列に単語が2つあり、その類似度を人間が判定した数値が3列目に来るようです(10点満点の類似度)。これをコサイン類似度では、どの程度の類似度かを計算して4列目に設定します。

```text:combined.tab
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](https://github.com/YoheiFukuhara/nlp100/blob/master/10.%E3%83%99%E3%82%AF%E3%83%88%E3%83%AB%E7%A9%BA%E9%96%93%E6%B3%95%20(II)/094.WordSimilarity-353%E3%81%A7%E3%81%AE%E9%A1%9E%E4%BC%BC%E5%BA%A6%E8%A8%88%E7%AE%97_1.ipynb)

```python
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秒もかからず終わります。

```text:094.combine_1.txt
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](https://github.com/YoheiFukuhara/nlp100/blob/master/10.%E3%83%99%E3%82%AF%E3%83%88%E3%83%AB%E7%A9%BA%E9%96%93%E6%B3%95%20(II)/094.WordSimilarity-353%E3%81%A7%E3%81%AE%E9%A1%9E%E4%BC%BC%E5%BA%A6%E8%A8%88%E7%AE%97_2.ipynb)

```python
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版の方がずっと結果がいいですね。

```text:094.combine_2.txt
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
後略
```