デジタル・デザイン・ラボラトリーな日々

アラフィフプログラマーが数学と物理と英語を基礎からやり直す。https://qiita.com/yaju

TensorFlowコトハジメ Word2Vecで「君の名は。」と戯れてみた

はじめに

前回、Word2Vecを初めて試してみて面白いと思ったので、日本語に挑戦することにした。 yaju3d.hatenablog.jp

日本語に挑戦するにあたり、どうせなら旬なネタがいいなと思って、今のお気に入りは火曜ドラマ「逃げるは恥だが役に立つ」で「みくに - 平匡」の結果がどうなるか見てみたいと思ったわけですが、元となるデータ(2chデータやTVの感想)を収集するのが面倒くさいのと、まだドラマが中盤なので後回しにしました。
その代わりとして思いついたのが新海誠さんの「君の名は。」です。小説が出ているので小説をそのまま取り込めば、ノイズが入らないのでいい結果が得られると思ったからです。ただデータ量としては少ないのが懸念です。

小説のテキスト化

小説 君の名は。 (角川文庫) Kindle版を購入しました。

下記の手順に従って、「君の名は。」をテキスト化しました。個人でデータマイニングする上で問題ないので。
【追記 2017/02/10 参照サイトが削除されていたため、手順を記述しました。】
Kindleで購入した電子書籍には DRM(デジタル著作権管理)プロテクトが掛かっているので解除が必要です。DRM解除機能は「 Calible + DeDRM 」の合わせ技で実現できます。
参照:完全無料!Amazonで購入したKindleの縦書き電子書籍をPDFに変換する方法

Step1:Kindle for PCをインストールします。
Step2:Calibreをインストールします。
Step3:DeDRM(tools_v6.2.1.zip)をダウンロードし、解凍するとDeDRM_calibre_pluginフォルダ内に「DeDRM_plugin.zip」が見つかります。
Step4:Kindle for PCに対象の本をダウンロードします。
Step5:Calibreを起動し、マイドキュメントの「My Kindle Content」フォルダにある対象の本「.azw」ファイルをCalibreにドラッグ&ドロップしてください。
Step6:Calibreで「設定」→「プラグイン」→「ファイルからプラグインを読み込む」で「DeDRM_plugin.zip」を選択します。 その際にセキュリティリスクの警告が表示されますが、そのまま「はい」→「OK」とクリックしていきます。プラグインを有効にするために、Calibreを再起動します。
Step7:Calibreで対象の本を選択し、「本を変換」の変換画面で出力フォーマットを「TXT」にして「OK」をクリックすると変換が開始されます。
Step8:変換されたTXTファイルは、マイドキュメントの「Calibre Library」フォルダに保存されています。

形態素解析

テキスト化された「君の名は。」ですが、Word2Vecで使用するには「分かち書き」にする必要があります。
分かち書きとは、ある単位ごとに区切って、その間に空白を置くことです。
形態素解析として、「MeCab」より「JUMAN++」の方が、表記揺れや話し言葉に強いということで、「JUMAN++」を使用することにしました。 qiita.com

JUMAN++のインストール

最初はいつも通りにDocker上のTensorFlowでターミナルを使用としたのですが、「boostlib」のインストールが出来ないため断念、Dockerを使う前に作成したVirtualBoxにUbuntu(64bit)とPython数値計算環境「Anaconda」の環境があったため、こちらを久しぶりに使用しました。OSはUbuntu 14.04.2 LTSからアップグレードして、Ubuntu 16.04 LTSにしています。

yaju3d.hatenablog.jp

JUMAN++のインストールには下記サイトを参考にしました。 foolean.net
ただ、「sudo python setup.py install」としても「from pyknp import Jumanpp」で「ImportError: No module named pyknp」となるため、ネットで検索して「pip install ./pyknp-0.3」としたりして何とか使えるようになりました。ここらへんの仕組みがまだ理解出来てないですね。

JUMAN++は、VirtualBox上から使用しているから余計なんですが遅いなと思って、今見たらVirtualBox上のメモリが1GByteのままでした、JUMAN++の推奨はメモリ4GByteです。

JUMAN++による分かち書き

JUMAN++による分かち書きは、下記サイトのプログラムを使用させて頂きました。 foolean.net

最初にオプションを付けないまま、分かち書きをしてWord2Vecを使ったのですが、思ったような結果が得られないとTwitter上で呟いたところ、@K_Ryuichirouさんから、ストップワードを省いてみたらとのアドバイスを頂いて、ストップワードを省いて再挑戦しました。
ストップワードとは、一般的すぎる語や低頻度すぎる語などで、助詞や助動詞などの機能語(日本語ならば「は」「の」「です」「ます」など)のことです。

python3 main.py input.txt -t 名詞 動詞 形容詞 副詞

メモリが少ないこともあって、テキストデータを4つに分割してから、結果を結合しています。あと、事前にあとがき以降と空行を削除しています。

Gensim版Word2Vecのインストール

前回、Gensimを使わない「pip install word2vec」でインストールしたのですが、テキストファイルを読む「word2vec.Text8Corpus」メソッドが無いことに気がつきました。テキストファイルを読む処理などを作り込めばいいのですが、面倒なので素直にGensim版Word2Vecのインストールすることにしました。

今度は、前回と同じ環境であるDocker上のTensorFlowで構築した環境を使用します。
※別にそのままVirtualBox上の環境でも構いません。

$ easy_install -U gensim
Installed /usr/local/lib/python2.7/dist-packages/boto-2.43.0-py2.7.egg                                                                                        
Finished processing dependencies for gensim
$ pip install cython

Cythonを入れるのは、word2vecをスピードアップ(70倍違うとか)させるためです。

Word2Vecと戯れる

先にJupyter notebook上で分かち書きした「yourname.txt」をUploadしておきます。
※yourname.txtは、2000行で176KByteです。

「三葉」と「瀧」のそれぞれの結果で、「俺」と「私」が出てくるのは物語通りですね。

from gensim.models import word2vec
data = word2vec.Text8Corpus('yourname.txt')
model = word2vec.Word2Vec(data, size=200)

out=model.most_similar(positive=[u'三葉'])
for x in out:
    print x[0],x[1]

#結果0.999974846840.999966681004
する 0.9999563694
して 0.9999560117720.999956011772
こと 0.9999519586560.9999514818190.999950230122
先輩 0.999950110912
自分 0.999948740005
from gensim.models import word2vec
data = word2vec.Text8Corpus('yourname.txt')
model = word2vec.Word2Vec(data, size=200)

out=model.most_similar(positive=[u'瀧'])
for x in out:
    print x[0],x[1]

#結果0.9999613165860.999957501888
三葉 0.999945700169
して 0.999944329262
した 0.99993789196
先輩 0.999935507774
もう 0.9999344348910.9999333024020.9999322891240.999930977821

「俺 + 私 - 三葉」の結果が「瀧」ですね。

from gensim.models import word2vec
data = word2vec.Text8Corpus('yourname.txt')
model = word2vec.Word2Vec(data, size=200)

out=model.most_similar(positive=[u'俺',u'私'],negative=[u'三葉'])
for x in out:
    print x[0],x[1]

#結果0.99993789196
して 0.999936521053
こと 0.999934196472
した 0.999931871891
テッシー 0.9999276399610.999927401543
言う 0.999924242496
もう 0.9999235272410.9999231100080.999921619892

同様に「俺 + 私 - 瀧」の結果が「三葉」ですね。

from gensim.models import word2vec
data = word2vec.Text8Corpus('yourname.txt')
model = word2vec.Word2Vec(data, size=200)

out=model.most_similar(positive=[u'俺',u'私'],negative=[u'瀧'])
for x in out:
    print x[0],x[1]

#結果
三葉 0.999938130379
こと 0.9999338388440.999928653240.999924600124
テッシー 0.999921619892
して 0.999921500683
彗星 0.99992030859
する 0.9999191761020.9999167323110.999916255474

「三葉 - 瀧」の結果が「愛」なんてイキですね。

from gensim.models import word2vec
data = word2vec.Text8Corpus('yourname.txt')
model = word2vec.Word2Vec(data, size=200)

out=model.most_similar(positive=[u'三葉'],negative=[u'瀧'])
for x in out:
    print x[0],x[1]

#結果0.0158168040216
トンビ 0.0155568365008
地点 0.0151626057923
置いた 0.0145640941337
情報 0.0137448376045
金色 0.0131560843438
光って 0.0130646442994
古い 0.0127832395956
おばちゃん 0.0127398446202
地面 0.0123804248869

※この「愛」は「愛(いと)おしい」と思われます。

最後に

実際にやってみて、そこそこの結果が得られて良かったです。
データ量が少ないのか「WARNING:gensim.models.word2vec:under 10 jobs per worker: consider setting a smaller `batch_words' for smoother alpha decay」と警告が出ていますので、調整が必要なんだと思います。

Kindleなどの電子小説ならテキスト化できるので、自分の好きな小説を試してみるのも楽しいと思います。

参照

スポンサーリンク