ナード戦隊データマン

機械学習, 自然言語処理, データサイエンスについてのブログ

単語Embeddingを2次元上にプロットする

前回 ( https://datanerd.hateblo.jp/entry/2019/12/14/134234 ) は、単語の共起グラフから単語Embeddingを作りました。今回は、このEmbeddingをプロットします。なお、ここでの手順は一般的なword2vecにも適用可能です。

github.com

コード

In[1]:

%matplotlib inline
from gensim.models import KeyedVectors
from sklearn.decomposition import PCA
import re
import matplotlib
import numpy as np
from matplotlib.font_manager import FontProperties
import matplotlib.pyplot as plt

font_path = '/usr/share/fonts/truetype/takao-gothic/TakaoPGothic.ttf'
font_prop = FontProperties(fname=font_path)
matplotlib.rcParams['font.family'] = font_prop.get_name()

model = KeyedVectors.load("emb.kv", mmap="r")

def pca_plot(model, words):    
    data = [(model[word], word) for word in words]
    
    pca_model = PCA()
    values = pca_model.fit_transform([x[0] for x in data])[:,:2]
        
    plt.figure(figsize=(8, 8)) 
    for i, (d, v) in enumerate(zip(data, values)):
        plt.scatter(v[0],v[1])
        plt.annotate(
            d[1], 
            xy=(v[0], v[1]), xytext=(5, 2),
            textcoords='offset points', ha='right', va='bottom')
    plt.show()

In[2]:

words = [
    "野球","イチロー","大谷","二刀流","投手","ダルビッシュ","打者","松井","大リーグ",
    "浅田真央","羽生","スケート","サルコー","4回転","トリプルアクセル",
    "石川","ゴルフ","ボギー","ホールインワン","パター"]

pca_plot(model, words)

出力

f:id:mathgeekjp:20191216104111p:plain

考察

単語の共起グラフから生成した単語Embeddingに対し、いくつかの単語ベクトルを取得してPCAで次元圧縮してからプロットしてみると、「ゴルフ勢」「スケート勢」「野球勢」が見事にグループ化されていることがわかります。つまり、共起しやすい語が空間的に近くなっています。

このEmbeddingは、ある親語に対して、共起する語とその頻度によって親語のベクトルを更新しています。つまり、共起する語そのものを用いて親語を定義しています。この手法では、ある語に類似する語の類似度は極端に高い値が出やすいため、共起しやすい語のベクトル同士が極めて近い空間に位置するようになっています。これにより、グループ化されているといえます。これはGraph Embeddingと呼ばれる手法に近いです。

この共起語のGraph Embeddingの手法はニューラルネット的な仕組みを用いていませんが、「共起」という単なる統計的な情報によって生成されています。このようなEmbeddingであっても「スポーツの種類が同じ選手は空間的に近い」というような性質を見ることが可能だとわかります。

ただし、ベクトル同士の演算はできません。

参考

  1. Gensim word vector visualization
  2. Visualizing Word Vectors with t-SNE | Kaggle