読者です 読者をやめる 読者になる 読者になる

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

アラフィフプログラマーが数学と物理を基礎からやり直す

TensorFlowコトハジメ Word2Vecによる自然言語処理を試す

はじめに

以前、ベイジアンフィルタを実装して自然言語処理に興味を持ち始めたので、とりあえず「king - man + woman = queen」で有名になった「Word2Vec」を動かしてみたいと思った次第です。
yaju3d.hatenablog.jp

Word2Vecとは

Word2Vecは米グーグルの研究者であるトマス・ミコロフ氏らが提案した機械学習の分野で使われる、ニューラルネットというモデルを使ったツール/ライブラリです。名前の通り、word(単語)をvector(ベクトル)に変換します。
この技術をベースに、「単語」だけではなく「文書」にも意味を持たせてベクトルとして捉えて利用できる技術「Doc2Vec」も作成されました。

ベクトルは1行m列やn行1列のこと、または「大きさと向き」を持つ量のことです。単語を文字列としているだけでは分類することは出来ないので何かしら意味のある数値にするわけです。こうすることでベクトル同士の足し算・引き算・コサイン類似度などを計算できるようになり、有名になった「king(王様) - man(男) + woman(女性) = queen(女王)」ということが可能になるわけです。
他にも「東京 - 日本 + フランス = パリ」となるという例もあり、これは「首都」であるという関連情報が上位にあるからです。

単語をベクトル表現する方法は「word2vec」以前にもあったのですが、類似度の特徴を満たしていたものの足したり引いたりといった操作までは出来ませんでした。なので、「word2vec」が発表された時は一般には衝撃的だったのです。

enakai00.hatenablog.com

ベクトル空間モデル

word2vec以外で基本的なベクトル空間モデルを2点を列挙します。

BoW(Bag of Words)モデル

テキストデータを単語ごとの出現回数だけで表す方法です。ちなみに、bagは多重集合(multiset)の別名とのこと。
単語の出現順は考慮しないため。「彼女と僕」と「僕と彼女」は同じベクトルになる。

N-gramモデル

テキストデータをN文字単位で文字列を分解して表す方法です。
「彼女と僕」→ 彼女、彼女と、と僕、僕
「僕と彼女」→ 僕、僕と、と彼女、彼女

N-gramモデルでは、隣り合った文字列または単語の組み合わせを「共起関係」と呼びます。
また、「共起関係」がどの程度現れるかを集計した結果を「共起頻度」と呼びます。

実装環境

Pythonは、Docker上のTensorFlowで構築した環境を使用しています。
参照:WindowsユーザーがTensorFlowをインストールしてみた(Docker版) - デジタル・デザイン・ラボラトリーな日々

環境

  • Docker
  • Jupyter
  • Python 2.7
  • Word2Vec 0.9.1
  • CPython 0.25.1

Word2Vecのインストール

Word2Vecをインストールしたら「ImportError: No module named Cython.Build」とエラーになりましたので、先に「Cython」をインストールします。
※Word2Vecは、Pythonから扱える自然言語処理ライブラリ(Gensim)に含まれているのですが、今回はGensimを使わない方法にしました。
※pipはアップグレードしておいただけです。

# pip install --upgrade pip
 ︙
Successfully installed pip-9.0.1  
# pip install Cython
 ︙
Successfully installed Cython-0.25.1
# pip install word2vec
 ︙
Successfully installed word2vec-0.9.1

Word2Vecを試す

下記のword2vecのexamplesサイトを試しに動かしてみます。 http://nbviewer.jupyter.org/github/danielfrg/word2vec/blob/master/examples/word2vec.ipynb

text8.zipのダウンロードと解凍

Word2Vecのデモ用としてtext8という100MB程のコーパスのデータが用意されていますので、ダウンロードして解凍します。
wgetコマンドが無かったので、curlコマンドを使用します。

# curl http://mattmahoney.net/dc/text8.zip > text8.gz                                                                                                         
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current                                                                               
                                 Dload  Upload   Total   Spent    Left  Speed                                                                                 
100 29.8M  100 29.8M    0     0   497k      0  0:01:01  0:01:01 --:--:--  396k                                                                                
# gzip -d text8.gz -f                                                                                                                                         

Jupyter Notebook

Inの番号が飛んでいるのはミスしたからで意味はありません。 examplesサイトではtext8の格納フォルダ「/Users/drodriguez/Downloads/」になっていますが、自分はカレントフォルダに格納したのでフォルダは付けていません。

「king - man + woman」の部分

indexes, metrics = model.analogy(pos=['king', 'woman'], neg=['man'], n=10)
indexes, metrics
model.generate_response(indexes, metrics).tolist()

結果として、「queen」が先頭になっています。

[(u'queen', 0.2905402467729655),
 (u'empress', 0.2734506828577926),
 (u'prince', 0.2709167973829251),
 (u'wife', 0.2679356346054478),
 (u'monarch', 0.26728773557223445),
 (u'son', 0.2666904115522106),
 (u'throne', 0.2657155461401751),
 (u'regent', 0.26416170868397304),
 (u'pope', 0.2637096213206423),
 (u'pharaoh', 0.2619265026976325)]

最後に

Word2Vecをインストールして英語用のデモを試して雰囲気を楽しんだだけでしたが、次回は日本語を使っていろいろ試してみたいと思います。
今回初めて、GitHub Gistを使ってブログにJupyter Notebookを表示してみました。これ結構いけますね。

参照