【pythonで自然言語処理】word2vecで分散表現した単語を2次元に可視化する

  • 2020年3月20日
  • 2021年10月16日
  • Python
  • 3283view

 

概要

 

意味的に近い単語の分布を知りたい。そんなときは、2次元の分布図を作成するのが有効です。

kaggleで特徴量を調査するときにも役立つツールになります。

この記事では、word2vecによる分散表現、PCA(主成分分析)による次元圧縮(N次元から2次元へ)、単語を2次元の図にプロットする方法を解説します。

 

なお、word2vecによる分散表現についてはUdemyの自然言語処理の講座が参考になります。

この記事のword2vecの部分は、Udemyの自然言語処理の講座を参考にしています。

Udemy 「自然言語処理とチャットボット: AIによる文章生成と会話エンジン開発」はこちらから

 

 

実装例をもとに分散表現から2次元にプロットまで解説

処理の流れ

 

処理の流れは以下の通りになります。

  1. 分布図の作成に必要な文章が入ったファイルを読み込む
  2. 文章ごとに単語を空白で分割する(日本語の場合は形態素分析して分割する)
  3. gensimのword2vecを使って分散表現(N次元の配列)にする
  4. 分散表現により、意味的に近い単語がわかるようになる
  5. PCA(主成分分析)を用いてN次元の分散表現を2次元に圧縮する
  6. 圧縮した分散表現を使って2次元のグラフにプロットする

 

ここからは、ここの項目について解説します。

全体的なコードは、記事の後半に記載しています。

 

単語の分布図の作成に必要な文章が入ったファイルを読み込む

 

単語の分布図の元になる文章をファイルから読み込みます。

#  テキストファイルの読み込み(なお、前処理は考慮していない)
#  この例では、kaggleにある英語のデータで試しています。
with open("kaggle_dis.txt", mode="r", encoding="utf-8") as f:  
    wagahai = f.read()

 

文章は、kaggleのコンペの英文をtxtファイルに入れています。

 

 

文章ごとに単語を空白で分割する

 

文章の区切りを指定するセパレーターを定義します。

今回は英文のため、セパレーターは改行コードにしています。

日本語の場合は、「。」をセパレータに設定することが多いです。

seperator = "\n"  # このサンプルは、改行で文章を区切っているのでセパレータを改行コードにした。日本語だと「。」にすることが多い
wagahai_list = wagahai.split(seperator)  # セパレーターを使って文章をリストに分割する

wagahai_words = []
for sentence in wagahai_list:
    data = sentence.split() #英語のため空白で分割する。日本語の場合は、形態素の分けます。
    wagahai_words.append(data)   # 文章ごとに単語に分割し、リストに格納
    #wagahai_words.append(t.tokenize(sentence, wakati=True))  日本語の場合はコチラ
    

 

gensimのword2vecを使って分散表現(N次元の配列)にする

word2vecを使って分散表現することにより、意味的に近い単語がわかるようになる。

分散表現はN次元の配列の実数値になります。

 

# size : 中間層のニューロン数・数値に応じて配列の大きさが変わる。数値が多いほど精度が良くなりやすいが、処理が重くなる。
# min_count : この値以下の出現回数の単語を無視
# window : 対象単語を中心とした前後の単語数
# iter : epochs数
# sg : skip-gramを使うかどうか 0:CBOW 1:skip-gram
model = word2vec.Word2Vec(wagahai_words,
                          size=200,
                          min_count=5,
                          window=5,
                          iter=20,
                          sg = 0)

#学習結果を確認します
print(model.wv.vectors.shape)  # 分散表現の形状 Word2Vecのsizeの設定が反映されているのがわかります
print(model.wv.vectors)  #実際の分散表現、size次元の配列になっていることがわかるかと思います。

#類似している(ベクトルの距離的に近い)単語を出力してみる
#以下の例では単語「earthquake」に近い単語を出力することができます。
print(model.most_similar(positive=['earthquake'], topn=20))


 

PCA(主成分分析)を用いてN次元の分散表現を2次元に圧縮する

 

現時点では、N次元(今回の例では200次元)の配列データになっているため、2次元の図にプロットするためには、2次元まで圧縮する必要があります。

圧縮する方法の一つが主成分分析です。

 


#プロットしたい単語を設定する
#以下の例は、fire,earthquakeなどを設定しています。
words = []
words.append(["fire","r"])
words.append(["earthquake","r"])
words.append(["accident","r"])
length = len(words)
data = []
 
j = 0
while j < length:
    data.append(model[words[j][0]])
    j += 1
    

#主成分分析により2次元に圧縮する
pca = PCA(n_components=2)
pca.fit(data)
data_pca= pca.transform(data)

 

圧縮した分散表現を使って2次元のグラフにプロットする

 

主成分分析により2次元まで次元を圧縮しました。2次元になったところで、

matplotlibで表にプロットします。

 

fig=plt.figure(figsize=(20,12),facecolor='w')

plt.rcParams["font.size"] = 10
i = 0
while i < length_data:
    #点プロット
    plt.plot(data_pca[i][0], data_pca[i][1], ms=5.0, zorder=2, marker="x", color=words[i][1])
 
    #文字プロット
    plt.annotate(words[i][0], (data_pca[i][0], data_pca[i][1]), size=12)
 
    i += 1

plt.show()

 

実際にプロットすると以下のような2次元の分布図が作成されます。

 

その結果、「was」「or」「a」「is」などのSTOP WORDに設定されやすい単語、「Fire」「accident」などの災害を連想させる単語が集結しているように見えます。

 

 

 

全体的なコード

これまで実装方法を部分的なコードで解説しましたが、全体的なコードを掲載します。

 

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

# # word2vecによる分散表現と2次元グラフに単語のプロットする
# 
# ・word2vecによる分散表現に変換する
# ・分散表現をした単語をPCAを使って2次元に圧縮する
# ・圧縮した分散表現を2次元の図にプロットする
# ・参考にした参考動画(Udemy自然言語処理とチャットボット: AIによる文章生成と会話エンジン開発講座より「word2vecによる分散表現」)
# https://www.udemy.com/course/ai-nlp-bot/?deal_code=JPA8DEAL2PERCENTAGE&aEightID=s00000016735001
# 

# ## コーパスの前処理
# ・ファイルから文章データを取り出す
# ・文章ごとに単語に分割する

# In[1]:


import re
import pickle
from janome.tokenizer import Tokenizer
import warnings
warnings.simplefilter('ignore')

#  テキストファイルの読み込み(なお、前処理は考慮していない)
#  この例では、kaggleにある英語のデータで試しています。
with open("kaggle_dis.txt", mode="r", encoding="utf-8") as f:  
    wagahai = f.read()


seperator = "\n"  # このサンプルは、改行で文章を区切っているのでセパレータを改行コードにした。日本語だと「。」にすることが多い
wagahai_list = wagahai.split(seperator)  # セパレーターを使って文章をリストに分割する
#wagahai_list.pop() # 最後の要素は空の文字列になるので、削除
#wagahai_list = [x+seperator for x in wagahai_list]  # 文章の最後に。を追加
        
t = Tokenizer()


wagahai_words = []
for sentence in wagahai_list:
    data = sentence.split() #英語のため空白で分割する。日本語の場合は、形態素の分けます。
    wagahai_words.append(data)   # 文章ごとに単語に分割し、リストに格納
    #wagahai_words.append(t.tokenize(sentence, wakati=True))  日本語の場合はコチラ
    
#ここで、pickleに保存します。
with open('wagahai_words.pickle', mode='wb') as f:  # pickleに保存
    pickle.dump(wagahai_words, f)


# ## gensimのword2vecを用いた学習をする
# 今回はword2vecのためにライブラリgensimを使います。  
# 
# gensimについては、以下を参照 
# https://radimrehurek.com/gensim/
# 
# 以下では、word2vecを用いてコーパスの学習を行い、学習済みのモデルを作成します。

# In[2]:


from gensim.models import word2vec

with open('wagahai_words.pickle', mode='rb') as f:
    wagahai_words = pickle.load(f)
    
    
# size : 中間層のニューロン数・数値に応じて配列の大きさが変わる。数値が多いほど精度が良くなりやすいが、処理が重くなる。
# min_count : この値以下の出現回数の単語を無視
# window : 対象単語を中心とした前後の単語数
# iter : epochs数
# sg : skip-gramを使うかどうか 0:CBOW 1:skip-gram
model = word2vec.Word2Vec(wagahai_words,
                          size=200,
                          min_count=5,
                          window=5,
                          iter=20,
                          sg = 0)


# In[3]:


#学習結果を確認します
print(model.wv.vectors.shape)  # 分散表現の形状 Word2Vecのsizeの設定が反映されているのがわかります
print(model.wv.vectors)  #実際の分散表現、size次元の配列になっていることがわかるかと思います。


# In[4]:


print(len(model.wv.index2word))  # 語彙の数
print(model.wv.index2word[:10])  # 最初の10単語を表示します。頻出単語の順番で出力されるようです。


# In[5]:


#print(model.wv.vectors[0])  # 最初のベクトル
#print(model.wv.__getitem__("maskhttp"))  # 最初の単語「の」のベクトル


# In[6]:


#類似している(ベクトルの距離的に近い)単語を出力してみる
model.most_similar(positive=['earthquake'], topn=20)


# ## 単語を2次元の図にプロットします
# ・PCAを用いてN次元の分散表現を2次元に圧縮する
# ・2次元に圧縮した分散表現を2次元の図にプロットします

# In[8]:


import matplotlib.pyplot as plt
from sklearn.decomposition import PCA

#プロットしたい単語を設定する
#FIreなどの災害の意味で使われそうなものを設定
words = []
words.append(["fire","r"])
words.append(["earthquake","r"])
words.append(["accident","r"])
words.append(["involving","r"])
words.append(["Hawaii","r"])
words.append(["Africa","c"])
words.append(["San","c"])
words.append(["Francisco","c"])
words.append(["maskusername","c"])

#頻出単語もセットする
print(model.wv.index2word[:50])
for s in model.wv.index2word[:50]:
    words.append([s,"b"])


length = len(words)
data = []
 
j = 0
while j < length:
    data.append(model[words[j][0]])
    j += 1
    

#主成分分析により2次元に圧縮する
pca = PCA(n_components=2)
pca.fit(data)
data_pca= pca.transform(data)
 
length_data = len(data_pca)

#プロットの設定
#fig=plt.figure(figsize=(10,6),facecolor='w')
fig=plt.figure(figsize=(20,12),facecolor='w')

plt.rcParams["font.size"] = 10
i = 0
while i < length_data:
    #点プロット
    plt.plot(data_pca[i][0], data_pca[i][1], ms=5.0, zorder=2, marker="x", color=words[i][1])
 
    #文字プロット
    plt.annotate(words[i][0], (data_pca[i][0], data_pca[i][1]), size=12)
 
    i += 1

plt.show()


# ## プロットの結果
# プロットの結果、なんとなく近い単語が集まっている。
# 例えば、「was」「or」「a」「is」などのstopwordに設定されやすい単語が集まっているのがわかるかと思います。

 

独学で挫折した人向け・AI(機械学習)を短期間で学ぶ方法

独学で挫折してしまった
本買ったり、YoutubeでAIを勉強していたんだけど、結局から何を勉強してよいかわからず挫折してしまったんだ。どうしたら解消できる?

 

PythonをAI(機械学習)について、短期間で効率的に学ぶ方法を紹介します。

それは、以下のようなサービス、プログラミングスクールを利用することです。

プログラミングスキルを習得している人でも機械学習の習得は、難しいため、独学で迷うよりは、プロに教えてもらったほうが遥かに最短経路で身につけることができます。

 

スクール名 受講形式 サポート体制 値段の安さ こんな人にオススメ!
.Pro(ドットプロ) 教室 ★★★★★ ★★ ・AIだけでなくWEB開発技術も対面授業を通して直接講師に教えてもらいたい
・教室で仲間と一緒に学びたい!
Aidemy Premium Plan オンライン ★★★★ ★★ ・画像認識・自然言語処理・AIアプリ開発・AIとWEBを組み合わせたシステムなど広範囲の知識を身に着けたい!
・教育訓練給付制度を活用して最大70%引きで学びたい!
AIジョブカレ 教室
オンライン
★★★★ ★★★★★ ・授業形式でAI実務家から直接AIの実務について教えてもらいたい!
・10万円台と低価格で教えてもらいたい!
・ゆっくりペースで学びたい!
テックアカデミー オンライン ★★★★ ★★★★ ・最短8週間!短期間で学び終えるほど料金が安い!
・講座数が多いためAI以外のスキルも学びたい!
ヒューマンアカデミー オンライン ★★★ ★★★★ ・比較的リーズナブルな値段でPython基礎から学びたい
・就職内定率90.7% 提携企業115社以上という就職実績があるスクールで学びたい
Udemy オンライン ★★ ★★★★★ ・一度購入した講座は、Udemyがつぶれない限りずっと見ることができる
・1講座あたり2000円台(セール期間中)で購入して学びたい!

 

まとめ

自然言語のkaggleのコンペや、ユーザーの動向を調査するのに可視化は大事ですね。

可視化にword2vecによる分散表現を取り入れてみてはいかがでしょうか?

 

 

 

最新情報をチェックしよう!
>プログラミングスクール検索・比較表サイト

プログラミングスクール検索・比較表サイト

ワンクリック、さらに詳細に条件を指定してプログラミングスクールの検索ができます。さらに比較表により特徴を細かく比較できる!

CTR IMG