文系AIエンジニアが作る自然言語処理プログラム〜単語予測編〜

こんにちは。TabiOです。
私は文系出身で、プログラムを全く書かないSEを経て、1年ほど前からゼロからAIのdeep learningや機械学習という分野を勉強しています。
数学は高2からやってないので、数式やプログラムを見るだけでスリープモードに入るのですが、今回は初心者なりに頑張ってプログラムを作ってみました。


テーマは自然言語処理でよく使われるword2vecとwikipediaのデータを活用した単語予測をやります。
自然言語処理やword2vecの概要についてはこちらの記事をご覧ください

やろうとしていること

数字の足し算、引き算は小学校で習うので、多くの人はできると思うのですが、単語の足し算引き算ってやったことありますでしょうか?
僕はやったことはないのですが、なんとなく問題をみるとイメージがわくと思います。
例えば下記式はどんな答えになるのでしょうか?

王様 + 女 – 男 = ?

女王とかお姫様とかそんな単語がなんとなく頭の中には答えが浮かんでくるのではないでしょうか。
人間は今までの経験でイメージできますが、PCはこのニュアンスはわからないので、具体的に処理をさせる必要があります。
そこで、wikipediaのデータを使って学習モデルを作成し、モデルを使って日本語(単語)を数値化してより類似度が高い単語を推測するということをプログラムを交えながら説明します。

実行環境

mac book pro(2017モデル)
macOS High Sierra 10.13.4
メモリ 8GB
CPU 3.1GHzデュアルコアIntel Core i5
python 3.5.4
mecab 0.996

※mecab:オープンソースの形態素解析エンジン

対象

  • 自然言語処理を初めたての方
  • 機械学習をやってみたいけどどうしたら良いのかわからない方
  • 自然言語に興味はあるが何から始めたらよいかわからない方
  • Wikipediaのコーパスをテキスト化するやり方がわからない方

など、pythonも機械学習も余裕という方は簡単な内容なので、おさらい程度に見るのは良いと思います。

今回の学習の流れ

  • 前処理
  • モデル作成
  • 単語予測

それでは前処理からやっていきましょう!

WikipediaのデータをWord2Vecで使える形式に変換

wikipediaのデータを取得

まずはターミナルを立ち上げて、下記プログラムを実行するとwikipediaからデータを取得することができます。
※実行するディレクトリは任意のディレクトリで大丈夫です。

Terminal.
curl https://dumps.wikimedia.org/jawiki/latest/jawiki-latest-pages-articles.xml.bz2 -o jawiki-latest-pages-articles.xml.bz2

ダウンロードしたデータはまだテキストデータとして扱えるようになっていないので,変換する必要があります。

gitから「WikiExtractor.py」をcloneする

こちらも任意のフォルダで、wikiextractorというデータをclone(ダウンロード)します。

Terminal.
git clone https://github.com/attardi/wikiextractor

変換処理を実行

ダウンロードが完了したら、wikiextractorフォルダ内にあるWikiExtractor.pyを実行します。

Terminal.
python3 wikiextractor/WikiExtractor.py jawiki-latest-pages-articles.xml.bz2

※実行には数時間かかることもあります。

上記が終了するとtextディレクトリが作成されており、そのディレクトリ内にはWikipediaの各ページのテキストが保存されています。

1つのファイルに纏まっていないので、それらを一つにまとめるために、以下の処理を行います。

Terminal.
cat text/*/* > jawiki.txt

catコマンドで各テキストファイルを出力し、統合するファイルに書き込んでいます。
これで、jawiki.txtというファイルにまとまりました。

word2vecに読み込ませる前に分かち書きをして単語ごとに分割しておく必要があります。

Terminal.
mecab -Owakati jawiki.txt -o data.txt

このままだとdata.txtに単語と単語の間にスペースなどの余計な文字が混じってしまいます。また、日本語の文字を処理しやすいように文字コードを統一しておく必要があります。
このため、nkfコマンドを使ってuft-8に揃えます。
※nkfのインストールは こちら (http://codenote.net/mac/homebrew/1747.html)

Terminal.
nkf -w --overwrite data.txt

ここまでが前処理です。

今回の学習の流れ

  • 前処理←ここまで完了
  • モデル作成
  • 単語予測

これから、前処理したdata.txt
ファイルを使ってモデルを作成します。

モデル作成

ここからはpythonを使って進めます。
loggingライブラリを使えば、モデル作成の進捗状況が標準出力に表示されます。

create_wikimodel.py
from gensim.models import word2vec
import logging

logging.basicConfig(format=’%(asctime)s : %(levelname)s : %(message)s’, level=logging.INFO)
sentences = word2vec.Text8Corpus(‘./data.txt’)

model = word2vec.Word2Vec(sentences, size=200, min_count=20, window=15)
model.save(“./wiki.model”)

5epoch(5周分)くらい学習すると終了します。
wiki.modelが作成したモデルとなります。

今回の学習の流れ

  • 前処理
  • モデル作成←ここまで完了
  • 単語予測

コーパスを活用して単語の類似度を出力

先ほど学習したモデルを使って、単語を予測したいと思います。

wiki_model_test.py
from gensim.models import word2vec

コーパスを読み込む
model = word2vec.Word2Vec.load(‘./wiki.model’)
sim = model.most_similar(positive=[‘王様’, ‘女’], negative=(‘男’))

類似度が高い上位5つの内容を表示
for i in range(0, int(5)):
print(sim[i])

上記で実行していることは、王様 + 女 -男をするとどんな単語が類推させるのかという処理をしています。
その結果が下記です。
左が類推されるキーワードで、右の数字が左の単語が合っていると思われる確率です。(1に近づくほど精度が高い)

結果

('お姫様', 0.6108419299125671)
('王女', 0.5821991562843323)
('女王', 0.5519042611122131)

「お姫様」が最も高い結果になりました。
かなり実際のイメージと近い概念になっていますね。
他のパターンでも試してみました。

ITから残業を引くとどうなるのか。。。
sim = model.most_similar(positive=['IT’], negative=('残業'))

結果

('アウトソーシング', 0.6222032308578491)
('マネジメント', 0.5457292795181274)
('マーケティング', 0.5399150848388672)

なんとなくわかる!笑
アウトソーシングすると自分の作業量は減りますしね!

もう一つ試してみました。
sim = model.most_similar(positive=['旦那'], negative=('給料'))
旦那から給料を引くとどうなるか。

('何やら', 0.41971057653427124)
('子分', 0.4069960415363312)
('親分', 0.405059814453125)

上位2つが悲しすぎる・・・笑

ですが、なかなか空気の読めるモデルが出来上がりました。

まとめ

今回は、wikipediaの公開データを活用して、単語を推測するモデルを作りました。
単語の予測精度が上がると文章の生成もできるようになってくるため、これをベースに色々試してみると面白そうです。

未来技術推進協会では、アイデアソンだけでなく、今後は実装や評価も含めたハッカソンも企画しているため、是非ご興味ある方は参加してみてはいかがでしょうか。(イベントは決定次第随時HPやSNSで公開します)

以上、TabiOでした。

参考URL