BlazingTextを使って単語ベクトルを手に入れる


CPUしか積んでいないPCで単語ベクトルを得るためにfastTextを使い感動していた私です。
ですが、もともとの文書ファイルが数Gになってきたので、ローカルで取り扱うのめんどくさいなーと思ってました。

より高速に、数G~のファイルを扱うには・・・

昨年のre:Invent2017で発表された激アツなAWSのサービスである **SageMaker** を使って、Build in algorithmのひとつ **BlazingText** を使うしかないですね！

BlazingTextのリリースノートは[こちら](https://aws.amazon.com/jp/blogs/news/amazon-sagemaker-blazingtext-parallelizing-word2vec-on-multiple-cpus-or-gpus/)

個人的にリリースノートにかかれているところで大事だと感じたところは

* *Amazon SageMaker BlazingText は、GPU を使用して Word2Vec を高速化するための効率的な並列処理手法を提供します*
* *CBOW および skip-gram を使用したシングル CPU インスタンスでは BlazingText のパフォーマンスが fastText のものと互角であるため、ここではこれらの数値を報告しません*
* *BlazingText は複数の GPU と、複数の CPU インスタンス全体での分散計算を活用できるため、fastText よりも数倍速くなります。しかし、最良のインスタンス構成を選択するには、埋め込みの品質 (精度)、スループット、およびコスト間のバランスを取らなければなりません。*

なるほど、ローカルで単語ベクトルを作る時代は終わったということですね :+1: 


準備
---

* 半角スペースで分かち書きされたファイル

利用するAWSサービス
---

* SageMaker
* S3
* IAM


### S3に関して

まず、SageMakerが使えるリージョンは現在、アイルランド・バージニア北部・オハイオ・オレゴンの４つとなっています。（2018/02/22現在）
準備で用意した分かち書き済みファイルを用意するS3の場所は、SageMakerを立ち上げるリージョンと同じところでないとダメなので気をつけてください。


### IAMに関して

SageMakerはS3から学習ファイルを読み込み、今回の成果物である単語とベクトルがマッピングされたファイルは指定されたS3に吐き出されます。
IAMにS3の読み書きアクセス権がないと、 `ClientError: Data download failed:403 Forbidden (403): Forbidden` といったエラーに遭遇するので注意してください。


SageMakerのセットアップ
---

まず、ジョブをセットアップしましょう。

![スクリーンショット 2018-02-22 17.01.01.png](https://qiita-image-store.s3.amazonaws.com/0/18331/17311e34-0dbe-088b-4ecc-097575fb91b4.png "スクリーンショット 2018-02-22 17.01.01.png")

「トレーニングジョブの作成」を選びます。

#### IAM, アルゴリズムの選択


![スクリーンショット 2018-02-22 17.02.22.png](https://qiita-image-store.s3.amazonaws.com/0/18331/a7a5d669-c4b3-1803-50e8-ba37ab9bf337.png "スクリーンショット 2018-02-22 17.02.22.png")

ジョブ名に関しては、適当にいれてください。
IAMロールに関しては以下のポリシーがアタッチされてるものを用意してください

* AmazonSageMakerFullAccess
* AmazonS3FullAccess（めんどくさいので）

#### リソース設定

![スクリーンショット 2018-02-22 17.18.49.png](https://qiita-image-store.s3.amazonaws.com/0/18331/18c5eda4-ee98-4026-54f5-53c769f8a91d.png "スクリーンショット 2018-02-22 17.18.49.png")

インスタンスのボリュームサイズについては余裕を持って設定したほうがいいかもしれません。

`No space left on device` に遭遇して数時間の苦労が水の泡になるかもしれないので。


#### トレーニングデータの指定

ここは結構重要です。
BlazingTextは学習に利用する **ファイル** を指定してください。




![スクリーンショット 2018-02-27 14.04.27.png](https://qiita-image-store.s3.amazonaws.com/0/18331/c1aa1eca-eb7e-3ea4-b308-3583ac635b42.png "スクリーンショット 2018-02-27 14.04.27.png")





S3の場所を `s3://hogehoge/fugafuga/` とすると、そのパス以下のファイルを１つだけ適当に（たぶん名前順？）読み込んでくれます。

そのパス以下をすべて読み取り、学習につかってくれるかというと
<font color="FireBrick">読み取ってくれません。うまくやってほしいものですね。（要望）</font>
 

あとは成果物の出力パスを設定して「トレーニングジョブの作成」で学習が始まります。
	
学習
---

* 用意したデータ
	* 627M words
	* vocab size: 526366





### ml.p2.xlargeで学習させた場合（インスタンス数1台）

* 5エポック
* skip-gram


![スクリーンショット 2018-02-27 16.59.05.png](https://qiita-image-store.s3.amazonaws.com/0/18331/d2e50f9d-1371-0736-4ea1-703e76fc6992.png "スクリーンショット 2018-02-27 16.59.05.png")


### ml.c4.2xlarge、インスタンス数2台で学習させた場合

* 5エポック
* batch_skipgram

![スクリーンショット 2018-02-27 17.01.40.png](https://qiita-image-store.s3.amazonaws.com/0/18331/361365b9-a531-69d4-6594-f49fdc33ca4f.png "スクリーンショット 2018-02-27 17.01.40.png")

### ml.c4.2xlarge、インスタンス数8台で学習させた場合

* 5エポック
* batch_skipgram

![スクリーンショット 2018-02-27 17.07.45.png](https://qiita-image-store.s3.amazonaws.com/0/18331/4a877dab-d298-fa45-414c-8d4e5b066b33.png "スクリーンショット 2018-02-27 17.07.45.png")


### ml.c4.8xlarge、インスタンス数2台で学習させた場合

* 5エポック
* batch_skipgram


![スクリーンショット 2018-02-27 19.21.07.png](https://qiita-image-store.s3.amazonaws.com/0/18331/e6d46b50-2142-9d8c-aef4-584fd8c3d607.png "スクリーンショット 2018-02-27 19.21.07.png")




比較
---


| type | インスタンス数 | words/sec |
| --- | --- | --- |
| ml.p2.xlarge | 1 | 0.1 |
| ml.c4.2xlarge | 2 | 0.2 |
| ml.c4.2xlarge | 8 | 0.48~0.5 |
| ml.c4.8xlarge | 2 | 0.9~0.92 |


CPU分散はやすぎる...


確認
---

アウトプットの指定をしたS3のパスに結果が出力されます。
出力されるファイルを解凍すると `vectors.txt` が得られます。

```py
import os
import sys
sys.path.append(os.getcwd())

from gensim.models import KeyedVectors

word_vectors = KeyedVectors.load_word2vec_format('./vectors.txt', binary=False, encoding='utf-8', unicode_errors='ignore')

word_vectors.get_vector(u'あ')
```


おまけ
---

自分は訳あってS3にjson形式で分かち書きの文書を保存していたので、
Athenaで抜いて整形する必要がありました。
[Athenaの結果をSedコマンドでBlazingText用に整形する - Qiita](https://qiita.com/RyujiKawazoe/items/f55d511fba66c2f72d9a)