言語処理100本ノック 2015の99本目「t-SNEによる可視化」の記録です。
t-SNE(t-distributed Stochastic Neighbor Embedding)で2次元に削減をして単語ベクトルを下図のように可視化します。2次元や3次元なら人間が見てわかりますね。
参考リンク
リンク | 備考 |
---|---|
099.t-SNEによる可視化.ipynb | 回答プログラムのGitHubリンク |
素人の言語処理100本ノック:99 | 言語処理100本ノックで常にお世話になっています |
早く知っておきたかったmatplotlibの基礎知識、あるいは見た目の調整が捗るArtistの話 | 今更ながらにMatplotlibの基本を少し覚えました |
color example code: colormaps_reference.py | MatplotlibのColor Map |
環境
種類 | バージョン | 内容 |
---|---|---|
OS | Ubuntu18.04.01 LTS | 仮想で動かしています |
pyenv | 1.2.15 | 複数Python環境を使うことがあるのでpyenv使っています |
Python | 3.6.9 | pyenv上でpython3.6.9を使っています 3.7や3.8系を使っていないことに深い理由はありません パッケージはvenvを使って管理しています |
上記環境で、以下のPython追加パッケージを使っています。通常のpipでインストールするだけです。
種類 | バージョン |
---|---|
matplotlib | 3.1.1 |
pandas | 0.25.3 |
scikit-learn | 0.21.3 |
課題
第10章: ベクトル空間法 (II)
第10章では,前章に引き続き単語ベクトルの学習に取り組む.
99. t-SNEによる可視化
96の単語ベクトルに対して,ベクトル空間をt-SNEで可視化せよ.
課題補足(t-SNE)
t-SNE(t-distributed Stochastic Neighbor Embedding)は次元を2または3に削減します。次元削減という意味では、PCA(主成分分析)と同じです。ただ、PCAでできない非線形構造をもつデータにも対応可能です。偉そうに書いていますが、数式を理解しておらず記事「t-SNEによるイケてる次元圧縮&可視化」の受け売りです。
回答
回答プログラム 099.t-SNEによる可視化.ipynb
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.manifold import TSNE
from sklearn.cluster import KMeans
country_vec = pd.read_pickle('./096.country_vector.zip')
print(country_vec.info())
# t-SNE
t_sne = TSNE().fit_transform(country_vec)
print('t_sne shape:', t_sne.shape)
# KMeansクラスタリング
clustered = KMeans(n_clusters=5).fit_predict(country_vec)
fig, ax = plt.subplots(figsize=(22, 22))
# Set Color map
cmap = plt.get_cmap('Dark2')
for i in range(t_sne.shape[0]):
cval = cmap(clustered[i] / 4)
ax.scatter(t_sne[i][0], t_sne[i][1], marker='.', color=cval)
ax.annotate(country_vec.index[i], xy=(t_sne[i][0], t_sne[i][1]), color=cval)
plt.show()
回答解説
全体の8割近くは記事「素人の言語処理100本ノック:99」のコピペです。
ここが、今回のメインのコードです。scikt-learnのTSNEはいくつかパラメータがあるのですが、デフォルトのままで実行しました。scikt-learnのTSNEはあまりよくないと言及しているブログもありましたが、とりあえず気にせず行きます。
t_sne = TSNE().fit_transform(country_vec)
あと、散布図で表示する色としてK-Meanで非階層クラスタリングをしています。
clustered = KMeans(n_clusters=5).fit_predict(country_vec)
最後にmatplotlib
で散布図表示です。plt.get_cmap
を使って表示色定義をしていて、どんな色かはcolor example code: colormaps_reference.pyに情報があります。
scatter
で点を表示し、annotate
でラベル(国名)を表示しています。
※今更恥ずかしながらmatplotlib
の基本を、少しだけ記事「早く知っておきたかったmatplotlibの基礎知識、あるいは見た目の調整が捗るArtistの話」で理解しました。
fig, ax = plt.subplots(figsize=(22, 22))
# Set Color map
cmap = plt.get_cmap('Dark2')
for i in range(t_sne.shape[0]):
cval = cmap(clustered[i] / 4)
ax.scatter(t_sne[i][0], t_sne[i][1], marker='.', color=cval)
ax.annotate(country_vec.index[i], xy=(t_sne[i][0], t_sne[i][1]), color=cval)
plt.show()