Mecab については以下を参考。
コマンドで word2vec
導入
Macでの導入方法。
$ git clone https://github.com/svn2github/word2vec.git
$ cd word2vec/
$ make
gcc word2vec.c -o word2vec -lm -pthread -O3 -march=native -Wall -funroll-loops -Wno-unused-result
gcc word2phrase.c -o word2phrase -lm -pthread -O3 -march=native -Wall -funroll-loops -Wno-unused-result
gcc distance.c -o distance -lm -pthread -O3 -march=native -Wall -funroll-loops -Wno-unused-result
distance.c:18:10: fatal error: 'malloc.h' file not found
#include <malloc.h>
^~~~~~~~~~
1 error generated.
make: *** [distance] Error 1
Mac では上記の通りエラーが発生する。
Mac では <malloc.h>
ではなく <stdlib.h>
を使用するので以下を実行してから make する。
$ sed -ie 's/#include <malloc.h>/#include <stdlib.h>/g' *.c
なお、コンパイルして作成した word2vec
などのコマンドは make
を実行したカレントに作成されており、パスは通っていない。
実行
動作確認用の ./demo-word.sh
を実行する。
$ brew install wget
$ brew install gzip
$ ./demo-word.sh
$ ./distance vectors.bin
Enter word or sentence (EXIT to break): dog
Word: dog Position in vocabulary: 1902
Word Cosine distance
------------------------------------------------------------------------
dogs 0.637071
spaniel 0.604613
borzoi 0.582073
hound 0.579149
mastiff 0.573205
terrier 0.563618
hund 0.552174
...
Enter word or sentence (EXIT to break):
上記が成功したら英語コーパス(text8)による学習は完了しているので、次回以降は ./distance vectors.bin
で実行できる。
また word2vec
コマンドの学習インプットとなるテキストは 分かち書き である必要がある。
上記のデモは英語をコーパスとして使用しているため、もともと分かち書きである。
日本語コーパスをインプットとする場合は分かち書きした状態にする必要がある。
word2vec の機能
- distance
- 入力した単語の類義語や同義語を返す
- analogy
- 単語の足し算、引き算ができる
日本語学習済みモデル
$ wget http://www.cl.ecei.tohoku.ac.jp/~m-suzuki/jawiki_vector/data/20170201.tar.bz2
$ tar xf 20170201.tar.bz2
$ ./distance 20170201
日本語のコーパス
青空文庫
$ brew install nkf
$ wget http://www.aozora.gr.jp/cards/001847/files/57347_ruby_57225.zip
$ unzip 57347_ruby_57225.zip
$ nkf -g rojinto_umi.txt
Shift_JIS
$ nkf -w --overwrite rojinto_umi.txt
$ nkf -g rojinto_umi.txt
UTF-8
$ cat rojinto_umi.txt | mecab -Owakati > rojinto_umi_wakati.txt
$ time ./word2vec -train rojinto_umi_wakati.txt -output rojinto_umi_wakati.model -size 200 -window 5 -sample 1e-3 -negative 5 -hs 0 -binary 1
$ ./distance rojinto_umi_wakati.model
Enter word or sentence (EXIT to break): 老人
Word: 老人 Position in vocabulary: 22
Word Cosine distance
------------------------------------------------------------------------
0.913845
分かっ 0.904279
無かっ 0.865596
コーパスの収集して学習・実行する
コーパスとして Wikipedia のデータを使用する。
word2vec へのインプットとして上記のコーパスが分かち書きされた 1つのテキストデータを作成する必要がある。
$ nohup wget https://dumps.wikimedia.org/jawiki/latest/jawiki-latest-pages-articles.xml.bz2 &
$ less nohup.out
Redirecting output to ‘wget-log’.
$ tail -f wget-log
上記で取得したデータは XMLファイルなので、テキストファイルに整形する必要がある。
wp2txt
という Ruby 系のツールを使用する。
インストールは以下。
$ gem install wp2txt
実行。
$ mkdir jawiki-latest-pages-articles
$ cd jawiki-latest-pages-articles
$ wp2txt --input-file ../jawiki-latest-pages-articles.xml.bz2
出力されたファイルを結合して分かち書きファイルを作成する。
$ cd ..
$ cat jawiki-latest-pages-articles/*.txt | mecab -Owakati > jawiki-latest-pages-articles-wakati-ipadic.txt
コーパスを使って学習する。
$ time ./word2vec -train jawiki-latest-pages-articles-wakati-ipadic.txt -output jawiki-latest-pages-articles-wakati-ipadic.bin -size 200 -window 5 -sample 1e-3 -negative 5 -hs 0 -binary 1
オプションは以下。( $ ./word2vec
コマンドで表示される)
- -train
- 学習に使用するファイル。分かち書きが必要。
- -output
- 学習結果を出力するファイル名
- -size
- ベクトルの次元数
- -window
- 指定した数値の分だけ、単語の前後にある単語を文脈として判断させる
- -sample
- 単語を無視する頻度の閾値。1e-3は「頻出度が高め」 の意味。
- あまりに高い頻度で出現する単語は意味のない単語である可能性が高いので、無視する。
- -hs
- 学習に階層化ソフトマックスを使用するかどうか
- -negative
- ネガティブサンプリングに用いる単語数、ランダムに間違った解答として判断させる
- -threads
- 学習に使用するスレッド数
- -iter
- トレーニング反復回数
- -min-count
- n回未満登場する単語を破棄
- -alpha
- 学習率
- 高いほど収束が速いですが、高すぎると発散します。低いほど精度が高いですが、収束が遅くなります。
- -classes
- ベクトルよりもワードクラスを優先させる
- -debug
- デバッグモード
- -binary
- バイナリ形式で出力するかどうか
-binary 0
で出力ファイルを見ると各単語のベクトルが見れる
- -save-vocab
- 語彙をファイル保存
- -read-vocab
- 語彙をファイルから使用
- -cbow
- 学習モデル CBOW を使うか、Skip-gram を使うか
以下で学習データを使って実行。
$ ./distance jawiki-latest-pages-articles-wakati-ipadic.bin
Enter word or sentence (EXIT to break):
Pythonで word2vec
$ pip install gensim
学習の実装は以下。
# -*- coding: utf-8 -*-
from gensim.models import word2vec
import logging
logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
sentences = word2vec.Text8Corpus('jawiki_wakati.txt')
model = word2vec.Word2Vec(sentences, size=200, min_count=20, window=15)
model.save("jawiki_wakati.model")
2単語の類似度を出力する実装は以下。
(どうやら Cos 類似度の模様)
# -*- coding: utf-8 -*-
from gensim.models import word2vec
import logging
import sys
logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
model = word2vec.Word2Vec.load("jawiki_wakati.model")
argvs = sys.argv
print model.similarity(argvs[1], argvs[2])
$ python similarity.py 日本 フィリピン
単語のベクトルを出力する実装は以下。
# -*- coding: utf-8 -*-
from gensim.models import word2vec
import logging
import sys
logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
model = word2vec.Word2Vec.load("jawiki_wakati.model")
argvs = sys.argv
print model[argvs[1]]
おすすめ書籍
リンク