yamaMomoによる分散表現の評価実験

ワークス徳島人工知能 NLP 研究所が公開している[yamaMomo](https://github.com/WorksApplications/yamaMomo)では[Sudachi同義語辞書](https://github.com/WorksApplications/SudachiDict/blob/develop/docs/synonyms.md)を基に表記ゆれの情報から単語分散表現の評価を行うことができます。
yamaMomo, Sudachi同義語辞書の詳細やデータは公式ドキュメントや論文をご参照ください。

今回はこちらを使って分散表現の比較を実際に行ってみました。

# yamaMomoの概要
yamaMomoでは分散表現の評価データをSudachi同義語辞書から自動生成します。
例えば、以下の例では**インフルエンザ**と**influenza**は翻字の関係にあり、**インフルエンザ**と**インフル**は略称の関係にあります。
このような関係がフラグによって管理されているため、その情報を基に各同義関係ごとの同義語ペアを抽出できます。

また、(医療)のように同義語グループにはカテゴリー情報が付与されたものもあるため分野ごとに単語を集めることもできます。
```
000127,1,0,1,0,0,0,(医療),インフルエンザ,,
000127,1,0,1,0,0,1,(医療),influenza,,
000127,1,0,1,0,2,0,(医療),インフル,,
000127,1,0,2,0,0,0,(医療),流行性感冒,,
000127,1,0,2,0,2,0,(医療),流感,,
```

yamaMomoではこれらの情報を使って同義関係の評価、分野間の評価を行うことができます。

評価方法について軽く説明すると、同義関係の評価はOutlier Word Detection、分野間の評価はConcept Categorizationのタスクをベースに行われています。
Outlier Word Detectionでは同義語ペアに外れ値となるような単語を追加して実際にその単語が同義語ペアよりも遠い位置にいるのかを確認しています。
Concept Categorizationでは2つの分野から持ってきた単語の集合をクラスタリングしたときに正しく分野ごとに分類できているかを見ます。

それでは実際に分散表現の評価を行ってみます。

# 分散表現の評価

まず、事前準備としてyamaMomoをクローンします。
```
git clone https://github.com/WorksApplications/yamaMomo.git
cd yamaMomo
pip install -r requirements.txt
```
次に、以下のように評価に使うモデルを適当なディレクトリにまとめます。

今回は[朝日新聞単語ベクトル](https://cl.asahi.com/api_data/wordembedding.html)を評価しました。
Skip-gram、CBOW、GloVeとそれらにRetrofittingを行ってfine-tuningした計6モデルを使って比較を行っています。
今回は`embs`というディレクトリを作成し、その中に分散表現のモデルを入れています。
```
mkdir embs
ls embs/
cbow-retrofitting.txt  cbow.txt  glove-retrofitting.txt  glove.txt  skipgram-retrofitting.txt  skipgram.txt
```

## 表記ゆれの評価
最初は表記ゆれ（略称・翻字・異表記）による同義関係について評価します。
```
cd outlier
python create_outlier_dataset.py -m "../embs/*" && python evaluate_outlier_detection.py
```
上記のコマンドを実行すると最終的に以下のような出力が得られます。
```
abbj
loading... ['../embs/cbow-retrofitting.txt', '../embs/cbow.txt', '../embs/glove-retrofitting.txt', '../embs/glove.txt', '../embs/skipgram-retrofitting.txt', '../embs/skipgram.txt']
cbow-retrofitting 7018 0.873972602739726 578 0.7198007471980075
cbow 6925 0.8623910336239103 563 0.701120797011208
glove-retrofitting 6472 0.8059775840597758 468 0.5828144458281445
glove 6322 0.7872976338729764 433 0.539227895392279
skipgram-retrofitting 7248 0.9026151930261519 608 0.7571606475716065
skipgram 7214 0.8983810709838107 599 0.7459526774595268
je
reuse... ['../embs/cbow-retrofitting.txt', '../embs/cbow.txt', '../embs/glove-retrofitting.txt', '../embs/glove.txt', '../embs/skipgram-retrofitting.txt', '../embs/skipgram.txt']
cbow-retrofitting 19222 0.5874694376528118 766 0.2341075794621027
cbow 18690 0.5712102689486552 724 0.22127139364303178
glove-retrofitting 5729 0.1750916870415648 77 0.023533007334963326
glove 6219 0.19006723716381418 81 0.024755501222493887
skipgram-retrofitting 16311 0.4985024449877751 363 0.11094132029339854
skipgram 15937 0.4870721271393643 321 0.09810513447432763
jj
reuse... ['../embs/cbow-retrofitting.txt', '../embs/cbow.txt', '../embs/glove-retrofitting.txt', '../embs/glove.txt', '../embs/skipgram-retrofitting.txt', '../embs/skipgram.txt']
cbow-retrofitting 25800 0.9361393323657474 2279 0.8269230769230769
cbow 25061 0.9093251088534108 2081 0.7550798258345428
glove-retrofitting 23345 0.8470609579100146 1839 0.6672714078374455
glove 20628 0.7484760522496372 1354 0.49129172714078373
skipgram-retrofitting 26204 0.9507982583454282 2340 0.8490566037735849
skipgram 25784 0.9355587808417997 2174 0.7888243831640058
```

見づらいので、表にまとめると以下のような結果が得られています。
### abbj: 略称
|モデル名              |outlierごとの正解数|正解率|同義語ペアごとの正解数|正解率|
| -----               | ---:| ----: |---:| ----: |
|cbow-retrofitting    | 7018| 0.8740| 578| 0.7198|
|cbow                 | 6925| 0.8624| 563| 0.7011|
|glove-retrofitting   | 6472| 0.8060| 468| 0.5828|
|glove                | 6322| 0.7873| 433| 0.5392|
|skipgram-retrofitting| 7248| 0.9026| 608| 0.7572|
|skipgram             | 7214| 0.8984| 599| 0.7460|

### je: 翻字
|モデル名              |outlierごとの正解数|正解率|同義語ペアごとの正解数|正解率|
| -----               | ---:| ----: |---:| ----: |
|cbow-retrofitting    | 19222 | 0.5875 | 766 | 0.2341|
|cbow                 | 18690 | 0.5712 | 724 | 0.2213|
|glove-retrofitting   | 5729  | 0.1751 | 77  | 0.0235|
|glove                | 6219  | 0.1901 | 81  | 0.0248|
|skipgram-retrofitting| 16311 | 0.4985 | 363 | 0.1109|
|skipgram             | 15937 | 0.4871 | 321 | 0.0981|

### jj: 異表記
|モデル名              |outlierごとの正解数|正解率|同義語ペアごとの正解数|正解率|
| -----               | ---:| ----: |---:| ----: |
|cbow-retrofitting    | 25800 | 0.9361 | 2279 | 0.8269|
|cbow                 | 25061 | 0.9093 | 2081 | 0.7551|
|glove-retrofitting   | 23345 | 0.8471 | 1839 | 0.6673|
|glove                | 20628 | 0.7485 | 1354 | 0.4913|
|skipgram-retrofitting| 26204 | 0.9508 | 2340 | 0.8491|
|skipgram             | 25784 | 0.9356 | 2174 | 0.7888|

同じ朝日新聞コーパスから学習されているはずですが、結果から学習モデルによって精度に差があることが分かります。
略称・異表記ではskipgramが一番良く、翻字では全体的に精度が低いですがcbowが一番高い精度です。
また、retrofittingによって同義語ペアが近づいていることで正解率が改善していることが分かります。

abbj, je, jjはそれぞれ表記ゆれ中のより詳細な同義関係を表しているものです。
abbjは略称に限定した同義語ペアで評価をしており、実際に評価に使われたデータは`data_eval/abbj.json`で確認できます。je(翻字), jj(異表記)も同様に確認できます。
例えば、今回のデータでは以下のようなものがあり**アニメーション**と**アニメ**がランダムに選ばれた**outliers**よりも近い位置にいることが望まれます。
「outlierごとの正解数」はこのoutliersの単語1つずつで正解数をカウントしています。そして、「同義語ペアごとの正解数」はこの10個のoutliersの単語がすべて正解できている同義語ペアの数です。
```
        {
            "synos": [
                "アニメーション",
                "アニメ"
            ],
            "outliers": [
                "タリーズ",
                "フジオフードシステム",
                "キャパ",
                "モチベーション",
                "アサヒ",
                "登山",
                "フォークソング",
                "アフロヘアー",
                "ヤマト",
                "traditional"
            ]
        },
```


## 分野情報の評価
次に、分野情報を使った評価を行います。
```
cd ../concept/
python create_concept_dataset.py -m "../embs/*" && python evaluate_concept_categorization_dataset.py
```
上記のコマンドを実行すると最終的に以下のような出力が得られます。
```
cbow-retrofitting
100%|███████████████████████████████████████████████████████████████████████| 2025540/2025540 [09:17<00:00, 3632.39it/s]
cbow-retrofitting: 1014468/2025540 = 0.5008382949731923
cbow
100%|███████████████████████████████████████████████████████████████████████| 2025540/2025540 [08:35<00:00, 3929.02it/s]
cbow: 971047/2025540 = 0.4794015423047681
glove-retrofitting
100%|███████████████████████████████████████████████████████████████████████| 2025540/2025540 [09:48<00:00, 3439.96it/s]
glove-retrofitting: 604086/2025540 = 0.2982345448621108
glove
100%|███████████████████████████████████████████████████████████████████████| 2025540/2025540 [08:36<00:00, 3921.62it/s]
glove: 565558/2025540 = 0.27921344431608364
skipgram-retrofitting
100%|███████████████████████████████████████████████████████████████████████| 2025540/2025540 [08:39<00:00, 3902.24it/s]
skipgram-retrofitting: 1033176/2025540 = 0.5100743505435588
skipgram
100%|███████████████████████████████████████████████████████████████████████| 2025540/2025540 [08:29<00:00, 3974.74it/s]
skipgram: 1009937/2025540 = 0.498601360624821
```
|モデル名              | 正解率|
| -----               | ----: |
|cbow-retrofitting    | 0.5008|
|cbow                 | 0.4794|
|glove-retrofitting   | 0.2982|
|glove                | 0.2792|
|skipgram-retrofitting| 0.5101|
|skipgram             | 0.4986|

分野情報ではskipgram-retrofittingが一番良いという結果になりました。
先ほどの実験でも似たような傾向が得られていますが、skipgramやcbowが強そうな印象です。
なぜ、gloveの結果が極端に低いのか？などが調べられると面白そうに感じました。

# おわり
ということで、今回はyamaMomoを使った分散表現の評価を行いました。
翻字関係があまり学習できていないということやモデル間での精度差があるなどやってみるといろいろと気付く部分で出てきて面白いなと思います。
分散表現の評価の一つとして使ってみてはどうでしょうか。