word2vecで得られたベクトルを主成分分析してみる

概要

前回の記事(以下のリンク)で、word2vecを利用して、単語をベクトルへ変換しました。
その時は、とりあえず、200次元のベクトルとして学習させましたが、どんな感じに学習されているのか(次元数が多すぎたりしないのかなど)興味がわいたので、
主成分分析を行って調べて見ることにします。

marmarossa.hatenablog.com

準備

  • 主成分分析用途
    • pip install sklearn
  • グラフ作成用途
    • pip install pandas
    • pip install matplotlib

主成分分析って何?

元のベクトルが持つ情報をなるべく欠損することなく縮約する手法です。
何が嬉しいかと言うと、例えば10次元のベクトルが2次元や3次元で済めば、保存容量も少なくて済みますし、可視化も簡単です。
詳しい解説は、以下のリンクを参照してください。
http://www.statistics.co.jp/reference/software_R/statR_9_principal.pdf

手順

手順と言うほどの長さではないので、コードを直接読んで頂いた方が早いと思います(コメントもつけてます)。
私は、元のword2vecの次元を200で作成しているので、主成分分析した後の次元も200で揃え、 累積の寄与率を計算しています。
累積の寄与度が1に近くほど元のベクトルから情報の欠損がないことを示しています。

#!/usr/bin/env python
# coding: utf-8

from sklearn.decomposition import PCA
from gensim.models import Word2Vec
import matplotlib
import matplotlib.pyplot as plt
import pandas as pd

# word2vecのモデルを読み込みます。
model_file_name = "jawiki_wl_all.zip_200_1.model"
model = Word2Vec.load_word2vec_format(model_file_name, binary=True)

# 元が200次元あるので、変換先のベクトルも200次元にしておきます。
pca = PCA(n_components = 200);

# word2vecのモデルから取り出した全部の単語ベクトルの配列を引数として、主成分分析を行います。
pca.fit_transform(map(lambda k : model[k], model.vocab.keys()));

ccr = 0.0; #累積寄与率 (0で初期化)

#(1行目) 最終的に得る結果 (idxは添え字(グラフ描画のために1始まり))
#(2行目) 各ratioに対して
#(3行目) ccrへratioを加算して行く
graph_input = [[idx+1,ccr] \
 for idx,ratio in enumerate(pca.explained_variance_ratio_) \
 for ccr in [(lambda x,y:x+y)(ccr,ratio)]]

# pandasとmatplotlibによるグラフ描画
df = pd.DataFrame(graph_input, columns=list('nr'))
df.plot(x=['n'],y=['r'],kind='scatter')
plt.title(u'cumulative contribution ratio', size=16)
plt.show();

結果

結果は、以下の通りです。縦軸が累積寄与率、横軸が主成分(寄与率の高い順)です。
グラフの立ち上がりが急であればあるほど、より少ない次元で表現可能であることを示し、グラフが直線になるほど、情報は均等に分散していることを示します。
25次元くらいまでは、ぐっと立ち上がりますが、その後ゆるやかな増加になっています。
特定の主成分に偏りすぎることなく綺麗に分布しているように思えます。
f:id:marmarossa:20170309105535p:plain