word2vecで単語計算を遊んでみた

## Word2Vecとは

>Word2vecでは、2層のニューラルネットワーク構造を用いて大量のテキストデータのコーパスに対し単語の分散表現を生成して各単語の特徴を数百次元のベクトル空間で表現する。このベクトル空間ではコーパスにおける共通のコンテキストを共有している単語を類似しているとして、ベクトル空間上で近い位置になるよう各単語にベクトルの割り当てを行う。

簡単にまとめると

- 単語を特徴量でベクトル化
- 意味を踏まえたベクトル表現


## 単語のone-hot表現と分散表現

### one-hot表現
単語に対して(1,0,0,....,0),(0,1,0,0,...,0)のように一つが1で他が0のベクトルとして表現する方法。
→単語数が増えると次元がそれだけ増える
→コサイン類似度が使用できない

### 分散表現
単語をそれぞれ複数の要素の組み合わせで表現する方法。例えば、攻撃力、体力、防御力、みたいな。実際の特徴は人間は理解できないものがほとんど。
→単語数が増えても次元が大きくならない

## とりあえずw2vで遊ぶ

### App
(無料プラン終了に伴い停止しました...)

### インポート

```python:インポート
from gensim.models.word2vec import Word2Vec
from pprint import pprint  # 表示用
```


### モデルをダウンロード
ネットで探してきてw2vモデルをダウンロードする。
なんかいろんな形式があるから、そのモデルに合った読み込みをしないとうまくいかないけどその阪大委が難しかった。判断の仕方は良く分からない。



```python:読み込み
model_path = "./model/word2vec.gensim.model"
model = Word2Vec.load(model_path)
```

いろんなモデルで試して、その時にいろいろ使った読み込みが以下のものだが、使い分けは正直覚えてないしわからない。他のモデルを読み込むときにうまくいかなかったら参考になるかも？

```python
model = Word2Vec.load_word2vec_format(model_path, binary=True)
model = gensim.models.KeyedVectors.load_word2vec_format(model_path, binary=True)
model = KeyedVectors.load_word2vec_format(model_path, binary=True)
```

### 似ている単語を表示してみる

```python
pprint(model.wv.most_similar("日本"))
```

```:結果
[('韓国', 0.7088127136230469),
 ('台湾', 0.6461570262908936),
 ('日本国内', 0.640389084815979),
 ('欧米', 0.6350582838058472),
 ('日本国外', 0.6200590133666992),
 ('台湾出身', 0.6174062490463257),
 ('中華圏', 0.6128153204917908),
 ('日本の経済', 0.6088820099830627),
 ('日本の歴史', 0.6070738434791565),
 ('韓国国内', 0.6054152250289917)]
```

```python
 pprint(model.wv.most_similar("Python"))
```

```:結果
[('Perl', 0.9588817954063416),
 ('JavaScript', 0.9520395994186401),
 ('Java', 0.9506087303161621),
 ('スクリプト言語', 0.9481661915779114),
 ('Ruby', 0.9438326954841614),
 ('C言語', 0.9374942779541016),
 ('Pascal', 0.929658830165863),
 ('C#', 0.9238971471786499),
 ('C++', 0.9227113723754883),
 ('XML', 0.9211979508399963)]
```

### 単語の類似度を表示してみる

```python
print(model.wv.similarity("日本", "アメリカ"))
```

```:結果
0.50296694
```

```python
print(model.wv.similarity("晴","雨"))
```

```:結果
0.08299452
```

### 単語計算

```
pprint(model.most_similar(positive=["東京","アメリカ"], negative=["日本"]))
```

```:結果
[('ニューヨーク', 0.7787366509437561),
 ('シカゴ', 0.7644962668418884),
 ('ロサンゼルス', 0.7558329105377197),
 ('サンフランシスコ', 0.7409358024597168),
 ('ロンドン', 0.7222370505332947),
 ('シドニー', 0.7194989919662476),
 ('ロスアンゼルス', 0.7077062129974365),
 ('カリフォルニア', 0.7073572874069214),
 ('ロサンジェルス', 0.7020710706710815),
 ('ボストン', 0.6936832070350647)]
```

Appの中で実際に行われているw2vの処理はこの程度。ほとんどをモデルとgensimライブラリに頼っているのでめっちゃシンプル。


## Flaskで構成する

ここまでに触った内容をほとんどそのままFlaskで作成した。だいたいの構成はメインページでどのモードにするかを選択し、各モードではPOSTで受け取った単語を変数でw2vのメソッドに入れて実行しHTMLに返す、という本当に普通の基本的な使い方のところ。
入力漏れとかでエラーが出まくるので例外処理が結構大変だったかも。

[github](https://github.com/tatsuki1119/w2v)
~~Heroku~~ (無料プラン終了に伴い停止しました...)


## 参考リンク


[Word2Vecの学習済み日本語モデルを読み込んで使う](https://qiita.com/omuram/items/6570973c090c6f0cb060)

[学習済み日本語word2vecとその評価について](https://blog.hoxo-m.com/entry/2020/02/20/090000)

[Python+Word2Vecで似た意味を持つ単語を調べる](https://analysis-navi.com/?p=2258)

[【Python】Word2Vecの使い方](https://qiita.com/kenta1984/items/93b64768494f971edf86)

[15分でできる日本語Word2Vec](https://qiita.com/makaishi2/items/63b7986f6da93dc55edd)