今日も窓辺でプログラム

外資系企業勤めのエンジニアが勉強した内容をまとめておくブログ

Wikipediaでword2vecの学習してEmbedding Projectorで可視化してみる

はじめに

前回の記事で、Wikipediaの全行に対してループを回せるような環境を用意しました。
www.madopro.net

そのコードを利用して、今回はWikipediaの全記事をもとに

  • gensimを使ってword2vecモデルを学習して、
  • その結果をEmbedding Projectorを使って可視化

してみたいと思います。

word2vecモデルの学習

前回の記事でWikipediaの全記事が分かち書きされたようなファイルを用意しました。
実はあの形式は、gensimでword2vecを学習させるときの入力としてそのまま使用できます。
models.word2vec.Word2Vecクラスを使用すると簡単に学習させることができます。

前回の分かち書きのファイルのパスが filename に入っているとすると、なんとたったのこれだけでモデルの学習・保存が完了します。

from gensim.models import word2vec

corpus = word2vec.LineSentence(filename)
self.model = word2vec.Word2Vec(corpus, size=200, min_count=5, workers=6)
self.model.save(model_filename)

Word2Vecに渡す引数はひとまずよく見かけた200次元のベクトルを学習、Wikipedia全体での出現回数が5回以上の単語のみを扱う、という設定にしてみました。
最後のworkersは学習に使うワーカーの数です。環境に合わせて適宜変更してください。

学習時間は環境によると思うのですが、数十分から数時間くらいでしょうか。
学習した単語数は498928語と、かなりの量でした。

単語ベクトルで足し算引き算のような演算をしたり、類似度を計算して似ている単語を探したり、なんてこともコードを書けばできますが、もっとこう、学習結果を目で確認したい!と思い探してみたらEmbedding Projectorというのが使えそうでした。

Embedding Projector

以前 TensorFlow の記事でTensorBoardのEmbedding Visualization機能を試してみたことがありましたが、現在はEmbedding Projectorなどと呼ばれ、簡単に試すことのできるWebサイトも用意されているようです。

上記サイトをクリックしてみると、既にWord2Vecのサンプルデータが表示されています。左のDATAというメニューからサンプルのデータセットを変更すると、英語のWord2Vecの学習結果やMNISTの学習結果などの可視化のサンプルを見ることができます。

Load dataというボタンをクリックすると、なんと任意のデータをアップロードして試すことができるようになっています。
ここに先ほど学習したモデルをアップロードしてあげれば、学習結果をEmbedding Projectorで可視化できそうです。

Embedding Projector に渡すファイルの用意

モデルの学習自体はすでに終えているので、あとは結果をEmbedding Projector用に整形してあげればよいだけです。
必要なファイルは2つです。

  1. 1行にベクトルが1つ並んだTSV
  2. 1行にメタデータ(ベクトルのラベルなど)が並んだTSV

メタデータは1列目がラベルとして表示されるようなので、ベクトルファイルと同じ順番で1行に1単語を並べたものを用意すればよいでしょう。メタデータのTSVのみヘッダが必要なので注意です。

これも実装は簡単で、self.modelに学習済みモデルが入っているとすると、たったのこれだけのコードでOKです。

def save_embedding_projector_files(self, vector_file, metadata_file):
    with open(vector_file, 'w', encoding='utf-8') as f, \
         open(metadata_file, 'w', encoding='utf-8') as g:

        # metadata file needs header
        g.write('Word\n')

        for word in self.model.wv.vocab.keys():
            embedding = self.model.wv[word]

            # Save vector TSV file
            f.write('\t'.join([('%f' % x) for x in embedding]) + '\n')

            # Save metadata TSV file
            g.write(word + '\n')

このメソッドを実装してあるクラス全体はWordEmbedding.pyという名前でGitHubにあげてあります。

さっそく可視化してみる

出力された2つのファイルを、早速 Embedding Projector に入力してみます。

ベクトルの分布

学習したベクトルの分布はこのようになりました。点の数がものすごい量ですが、空間上に散らばって存在している様子がわかります。
f:id:kanohk:20171127124704p:plain

ベクトル空間上で近くに存在している単語

データ量が多いので少し動きがもたついたのですが、この点をクリックしたり単語ラベルを検索したりすると、200次元のベクトル空間上で近くにあるほかの単語を確認することができます。いくつか確認してみましょう。

まずは「ブログ」という単語の近くに存在している単語を調べてみました。
f:id:kanohk:20171127124820p:plain

近くの単語を見てみると、

ツイッター, Twitter, twitter, オフィシャルブログ, Instagram, インスタグラム, オフィシャルサイト, アメーバブログ, facebook, Facebook, …

とSNSやブログに関連した単語がたくさん並んでいます。
なんの正規化処理もしないでそのままデータを使用したので、TwitterやFacebookが大文字と小文字のものが2つ登場してしまっています。今後の課題ですね。

次は「Google」を見てみました。
f:id:kanohk:20171127124945p:plain

Apps, Gmail, AOL, Facebook, 岩出, Chrome, Dropbox, ウェブブラウザ, Skype, Amazon, Mozilla, Safari, Maps, ...

Googleのサービスや、ライバル企業・サービスの名前が並んでいるようです。…岩出ってなんだ?


最後にYouTuberの「HIKAKIN」も見てみました。
f:id:kanohk:20171127125858p:plain

Spontania, ティアーズ, ヒットメーカー, YouTuber, 福居, ブラザーズ, メロコア, チャットモンチー, AOR, 東京スカイパラダイスオーケストラ, サザンオールスターズ, ...

ミュージシャンの名前が目立つでしょうか。ボイスパーカッションで有名になっているので、他のミュージシャンと同じような文脈で使われているのかもしれないですね。
ブラザーズは、スーパーマリオブラザーズの一部のようです。HIKAKINさんの有名な動画の一つがマリオのBGMをボイスパーカッションで再現したものです 。


コード

今回のコードは下記GitHubにおいてあります。
github.com

データと環境さえご自分で用意していただければ、WikiNLPというレポジトリをクローンして

python WordEmbedding.py

と打ってしばらく待つとモデルの学習からEmbedding Projectorへの入力ファイルの用意が終わるんじゃないかと思います。

関連記事

前回記事
www.madopro.net

少し前の記事ですが、TensorFlowでEmbedding Projectorを試した時の記事です。
www.madopro.net