言語処理100本ノック-93(pandas使用):アナロジータスクの正解率の計算

[言語処理100本ノック 2015](http://www.cl.ecei.tohoku.ac.jp/nlp100/)の93本目「アナロジータスクの正解率の計算」の記録です。
前のノック結果に対して正解率を計算するだけで楽勝です。自作プログラムでの結果は約25%、Gensim使用時の結果は58%と大きく水をあけられています(正解率の計算方法がこれでいいのか、という疑問も少しあり)。

# 参考リンク

|リンク|備考|
|:--|:--|
|[093.アナロジータスクの正解率の計算.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)/093.%E3%82%A2%E3%83%8A%E3%83%AD%E3%82%B8%E3%83%BC%E3%82%BF%E3%82%B9%E3%82%AF%E3%81%AE%E6%AD%A3%E8%A7%A3%E7%8E%87%E3%81%AE%E8%A8%88%E7%AE%97.ipynb)|回答プログラムのGitHubリンク|
|[素人の言語処理100本ノック:93](https://qiita.com/segavvy/items/f1939cabfc9f71e5aaa0)|言語処理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でインストールするだけです。

|種類|バージョン|
|:--|:--|
|pandas|0.25.3|

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

### 93. アナロジータスクの正解率の計算
> 92で作ったデータを用い，各モデルのアナロジータスクの正解率を求めよ．

# 回答
## 回答プログラム [093.アナロジータスクの正解率の計算.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)/093.%E3%82%A2%E3%83%8A%E3%83%AD%E3%82%B8%E3%83%BC%E3%82%BF%E3%82%B9%E3%82%AF%E3%81%AE%E6%AD%A3%E8%A7%A3%E7%8E%87%E3%81%AE%E8%A8%88%E7%AE%97.ipynb)

```python
import pandas as pd

def calc_accuracy(file):
    df = pd.read_table(file, header=None, usecols=[3, 4, 5], names=['word4', 'result', 'similarity'])
    print(df.info())
    print('Total records:', len(df))
    print('Available records:', (df['similarity'] != -1).sum())
    print('Correct records:', (df['word4'] == df['result']).sum())
    print('Accuracy', (df['word4'] == df['result']).sum() / (df['similarity'] != -1).sum())

calc_accuracy('092.analogy_word2vec_1.txt')

calc_accuracy('092.analogy_word2vec_2.txt')
```

## 回答解説
もっとスマートな書き方あると思いますが、時間優先であまり突き詰めていません。
ファイルを読み込んで、正解率を計算しています。
分母をどうするか判断に迷ったのですが、コーパスに単語が見つからなかった場合は分母から除外しています。

```python
df = pd.read_table(file, header=None, usecols=[3, 4, 5], names=['word4', 'result', 'similarity'])
print(df.info())
print('Total records:', len(df))
print('Available records:', (df['similarity'] != -1).sum())
print('Correct records:', (df['word4'] == df['result']).sum())
print('Accuracy', (df['word4'] == df['result']).sum() / (df['similarity'] != -1).sum())
```

自作プログラムでの結果です。

```bash
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 506 entries, 0 to 505
Data columns (total 3 columns):
word4         506 non-null object
result        462 non-null object
similarity    504 non-null float64
dtypes: float64(1), object(2)
memory usage: 12.0+ KB
None
Total records: 506
Available records: 462
Correct records: 114
Accuracy 0.24675324675324675
```

Gensim使った場合の結果です。"Available records"が減っているのが気になります。確かGensimは頻度が少ない場合はWord2Vecで対象としないロジックがあったような・・・

```bash
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 506 entries, 0 to 505
Data columns (total 3 columns):
word4         506 non-null object
result        400 non-null object
similarity    506 non-null float64
dtypes: float64(1), object(2)
memory usage: 12.0+ KB
None
Total records: 506
Available records: 400
Correct records: 231
Accuracy 0.5775
```