
こんにちは。コンサルティングサービス本部、芳賀です。
最終回の今回は、モデルの作成とJupyterを使っての実際のモデルとのインタラクションの様子をお伝えします。
コーパス内の単語の出現位置や頻度だけを頼りに、ここまで単語間の関係が学習できることに驚くと思います。
今回、モデルの作成も含め、すべての作業は Jupyter notebook 上で実施しています。
掲載している notebook は、弊社のカンファレンスで使用したものもとにを一部改変したものです。
モデルを構築します¶
環境によりますが、数時間要します。待ちましょう。
モデル作成手順の詳細な解説(モデルを調整するパラメータなど)は、gensimのドキュメントを参照してください。
今回はデフォルトの設定でモデルを作成しています。
from gensim.models import word2vec
jawiki_sentences = word2vec.Text8Corpus('data/jawiki.wakati.txt')
jawiki_model = word2vec.Word2Vec(jawiki_sentences,workers=4)
jawiki_model.save('data/jawki_model')
今回はブログ用に特別にモデルの変数名を日本語にしています。
したがって、これ以降登場する「ウィキペディア」と「商品マスタ」は、文字列ではなく、変数名です。
ウィキペディア=jawiki_model
また、比較用に、書籍を説明する文章のカラムを社内の商品マスターから抽出し、モデルにします。(事前作成したものをロードします)
なお、こちらのモデルは読者の方は用意できません。ご容赦ください。モデル作成手順はwikipedia日本語版をコーパスとする場合と同様です。ご自身で青空文庫から文章を適当にダウンロードしてコーパスとしたり、ご自身のSNSから文章を抽出してコーパスにしたりすると新しい発見があるかもしれません。
商品マスタ=word2vec.Word2Vec.load('data/naiyo_joho_model_20160715')
準備ができました。さっそく触ってみましょう。¶
単語が200次元ベクトルに変換された様子をみてみます。
ウィキペディア['東京']
「東京」という単語が200次元ベクトルになり numpy の配列に格納されていることがわかります。
単なる数値の羅列を眺めても理解はできないので、各種メソッドを試してみます。
ウィキペディア.most_similar('東京')
「東京」が登場する文脈で、それを適当な区の名前に置き換えても自然ということでしょうか。うーむ。
地名以外もやってみましょう。
ウィキペディア.most_similar('ハンバーガー')
それっぽいラインナップ
ウィキペディア.most_similar('カレーライス')
これも、それっぽいですね。 しかし、「福神漬」を差し置いて9位に「梅干し」がランクイン。
福神漬はどこへ行ったのでしょう。
ウィキペディア.most_similar('福神漬')
ウィキペディアでは、「カレーライス」と「福神漬」は全然違う文脈の世界に存在するようです。
書籍の商品マスタ由来のモデルでも試してみます。
商品マスタ.most_similar('東京')
同じ「東京」でもウィキペディアモデルとは違うリストが返ってきます。
どうやらこちらのモデルは、旅行ガイドや地図を紹介する文章の影響を強く受けているようです。
「パリ」も試してみます。
商品マスタ.most_similar('パリ')
これは、思わず旅に出たくなるラインナップ。
シリーズ物の旅行ガイドブックのタイトル「○○○○○○ パリ」「○○○○○○ ロンドン」などがSkip-gramにはまるんでしょう。
「ドイツ」を試します。
商品マスタ.most_similar('ドイツ')
いきなり、語学のテキストになってしまいました。国名だからでしょうか?
「フランス」もみてみましょう。
商品マスタ.most_similar('フランス')
ドイツほどの語学臭はないようです。
形容詞も試します¶
ウィキペディア.most_similar('高い')
「高い」の対義語「低い」がトップ。関連性が高く、「高い」と置換してもほとんどの場合意味のある文章になります。
今回はword2vecに入力する前に、原形に変換したりはしていないのですが、「高い」と「高く」の関連性に Word2Vecは気付きました。
ウィキペディア.most_similar('恥ずかしい')
どうなんでしょう。
動詞もみてみましょう¶
ウィキペディア.most_similar('食べる')
いい線いってます。
ウィキペディア.most_similar(positive=['ロンドン','フランス'], negative=['パリ'])
商品マスタ.most_similar(positive=['ロンドン','フランス'],negative=['パリ'])
どちらのモデルも良好な結果を返しています。
こんなのもいけますよ。
女 → スカート
男 → ?
コーパス内の単語の位置関係だけを頼りにここまで意味を汲み取れます。辞書無しで。
ウィキペディア.most_similar(positive=['スカート','男'],negative=['女'])
ウィキペディア.most_similar(positive=['イタリア','パリ'],negative=['フランス'])
商品マスタ.most_similar(positive=['イタリア','パリ'],negative=['フランス'])
ミラノやロンドンがトップに来てしまいます¶
その訳は?
ウィキペディア.most_similar('ローマ')
仲間はずれ探し ( doesnt_match メソッド )¶
引数に与えたリストに含まれる単語の中から、それらの平均からもっとも遠い単語を返します。
ウィキペディア.doesnt_match(['ローマ','パリ','ロンドン','ニューヨーク'])
やはり、ローマが仲間はずれでした。
ローマは他の首都とは使われる文脈が異なるように、実は、日本の都道府県では東京が特別であることがわかります。
みてみましょう。
ウィキペディア.doesnt_match(['東京','神奈川','千葉','埼玉'])
やはり、「東京」が仲間はずれでした。
東京のかわりに茨城をいれてみると?
ウィキペディア.doesnt_match(['茨城','神奈川','千葉','埼玉'])
現実は時に非情です。
ウィキペディア.doesnt_match(['東京','神奈川','千葉','埼玉','カレーライス'])
都道府県の中ではもっとも個性的な東京も、他県との隔たりはカレーライスほどではないようです。
関東6県の「東京」との類似度¶
実際、東京と一番遠いのは何県かみてみましょう
for pref in ['東京','神奈川','千葉','埼玉','茨城','栃木','群馬']:
print(pref,'\t',ウィキペディア.similarity('東京',pref))
群馬でした。 茨城ごめんなさい・・・。
ここに大阪も参加させてみます。
for pref in ['東京','神奈川','千葉','埼玉','茨城','栃木','群馬','大阪']:
print(pref,'\t',ウィキペディア.similarity('東京',pref))
地理的には距離がある大阪ですが、文脈上の距離は関東6県よりも東京に近いようです。
カレーライスも参戦させます。
for pref in ['東京','神奈川','千葉','埼玉','茨城','栃木','群馬','大阪','カレーライス']:
print(pref,'\t',ウィキペディア.similarity('東京',pref))
カレーライスの類似度は一桁落ちます。
東京>群馬>>>>>>>>>>カレーライス
くらいの距離感??
ウィキペディア.most_similar(positive=['芥川','漱石'],negative=['夏目'])
商品マスタ.most_similar(positive=['芥川','漱石'],negative=['夏目'])
餅は餅屋といったところでしょうか。
書名や著者に関連する情報の場合、精度が高い傾向にあります。
さいごに¶
今回は、EC2上でWord2Vecをためしてみました。
モデルの作成には多少時間がかかりますがそれでも、この実験にかかるAWSの料金はほんの数百円です。(うまくスポットを使うと百円以下かも)
作業用のデータをEphemeralに置くためにm4ではなくm3を使い、インスタンス停止時は作業用のディレクトリ以下をs3に保管しています。
思い立ったらすぐに試せるのがクラウドの良さです。
みなさんも、さまざまな文章をWord2Vecに食べさせて面白い結果を得てください!
次回は、また違うライブラリを試したいと思います。