2018年05月11日

Bayesian Gaussian mixture model(BGMM)を使ってクラスタリング数を求める

エモトです.みなさま某IWはご覧になりましたでしょうか.私は原作を知らなかったのでこんな展開になるのかよ!と驚きました.しかし幸いなことに,直前に某アニメの王位争奪戦を見直していたので,心のダメージは最小に抑えられました.アタルありがとう.フェイスフラッシュで無事解決したように,来年公開の4を待ちましょう.

前回,混合ガウスモデル(Gaussian mixture model, GMM)を使用して,クラスタリングを行いました.クラスタリングで問題になるのは,やはり最適なクラスタリング数は何かです.

前回はBIC(ベイズ情報量規準)から最適なクラスタリング数を求めました.ここで,潜在的ディリクレ配分法(Latent Dirichlet Allocation, LDA)に階層ディリクレ過程(Hierechical Dirichlet Process, HDP)があるように,GMMにもクラスタリング数を自動推定する Bayesian Gaussian mixture model(BGMM)があります.今回は,そのBGMMを簡単に説明します.

なお,同様な手法として Dirichlet Process Gaussian Mixture Model (DPGMM) があるのですが,今回使用するライブラリ scikit-learn では deprecated になっていました(これらの経緯は勉強不足です,すみません).

今回は簡単な例を示した後に,複雑なデータを与えたときの結果を紹介します.なお,前半のコード例は こちら で公開しています.

BayesianGaussianMixtureの使い方

まず,検証用のデータを生成します.今回は2クラスに分類されそうなデータを作成しました.
from numpy.random import rand
vec_list = []
for base in [[10, 10], [0, 0]]:
  for _ in range(100):
    temp = [base[0] + rand(), base[1] + rand()]
    vec_list.append(temp)
1F1BC2E6D3FAEFA026E5FE9BEF6FC562.png


BGMMの学習を行います.前述通り,scikit-learn を使用しています.ここでは,BGMMの推定クラスターの最大候補数 n_components を10に,学習回数 max_iter を1000にしています.この例では学習回数はデフォルトの100のままでも大丈夫ですが,実際に複雑なデータでは100より大きい数値に設定しておくと良いと思います.
import numpy as np
nvec = np.array(vec_list)

from sklearn.mixture import BayesianGaussianMixture
gmm = BayesianGaussianMixture(n_components=10, verbose=1, max_iter=1000)
gmm.fit(nvec)
分類結果を見ると,今回はクラスター番号2と5のクラスターに分かれました.クラスターごとに色付けた散布図をみると,綺麗に2クラスに分かれたことがわかります.
clusters = gmm.predict(nvec)
print("clusters:", clusters)

'''
clusters: [5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 2 2 2 2 2 2 2 2 2 2 2
 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2]
'''
5A5F4268F47E0D856FBF4F181D9BEBF0.png


また,分類結果のクラスター番号を集合(set)に変換すると,クラスター数がわかりやすくなると思います.
clusters_set = set(clusters)
print("clusters_set:", clusters_set)
print("len(clusters_set):", len(clusters_set))
'''
clusters_set: {2, 5}
len(clusters_set): 2
'''
次に,BGMMで学習した各クラスター番号の重みを確認します.クラスタリング番号2と5に重みが集中して,他がほとんど0になっています.この重みからも2クラスターになったのが判断できます.
weights = gmm.weights_
components = gmm.n_components
x_clusters = np.arange(components)
plt.bar(x_clusters, weights, tick_label=x_clusters)
plt.show
1197D336BADA29F45CCB19C8EF080875.png


より複雑なデータはどうなるか?

上記の例ではきれいに分かれましたが.実際のデータ(より複雑なデータ)ではそう簡単にはいきません.下図は,あるデータに対してBGMMを行ったときの各カテゴリーごとの重みの計算結果です.
94C04508A40C2F2A81EA26BF037F7DAE.png


グラフを比べてわかるように,後者の図からクラスター数をポンっと決めるのは難しいです.しかしながら,いくつか0に近い重みのクラスターがあるので,それら考慮して取捨選択していけば,ある程度の目星はつきそうです.クラスター数の候補を絞って,GMMを行い,結果を比較すれば,最適なクラスター数を絞り込めそうです.
posted by Seesaa京都スタッフ at 12:00| Comment(0) | 機械学習 | このブログの読者になる | 更新情報をチェックする

2018年04月24日

Topic Model で学習したデータをGMMでクラスタリングする

エモトです.GWは某VR,吹奏楽,ヒーロー大集合,オリジンの映画と映画館に連日通いつめそうです.さすがGW.あ,サッカーも見に行くよ.

以前 Topic Model を使って,文章の解析を行いました.そこでも問題になったのは,最適なトピック数は何か?です.今回は別のクラスタリング手法を加えて,最適なクラスタリング数を探してみます.

クラスタリングの有名な手法だとk-meansがありますが,今回は混合ガウスモデル(Gaussian mixture model, GMM)を選択しました.調べていると,単一のドキュメントが幾つかの異なるトピックに属すためLDAと相性が良い,とのことで採用しました.

Topic Modelの計算結果から,コーパスデータを特徴量に変換します.可変長のコーパスデータが,LDAで指定したトピック数だけの次元の特徴量に変換されます.
corpus_vec_list = []
for corpus in corpus_data:
  temp_vec = [0 for i in range(topic_count)]
  for tp in lda.get_document_topics(corpus):
    temp_vec[tp[0]] = tp[1]
  corpus_vec_list.append(temp_vec)
GMMは scikit-learn を使用しました.
def calc_gmm(vec_list, component):
	from sklearn.mixture import GaussianMixture
	gmm = GaussianMixture(n_components=component, covariance_type='full')
	
	import numpy as np
	nvec = np.array(vec_list)
	
	gmm.fit(nvec)
	clusters = gmm.predict(nvec)
	proba = gmm.predict_proba(nvec)
	bic = gmm.bic(nvec)
	return clusters, proba, bic
候補のクラスタリング数だけ,GMMを計算します.BIC(ベイズ情報量規準)から最適なクラスタリング数を求めます.単純に大小の比較を行いましたが,最適化計算からの乱数によるブレが生じるので,候補それぞれでの数値や複数回処理するなどを加味すると良いと思われます.
import sys
min_bic = sys.float_info.max
best_component = 0
        
for component in range(20, 30):
	clusters, proba, bic = calc_gmm(corpus_vec_list, component)
	if bic < min_bic:
		min_bic = bic
		best_component = component
今回は.文章が持つトピック数を求めるために使用したTopic Modelを,トピック特徴空間への写像方法として使用して,その特徴空間でGMMを使ってクラスタリングを行いました.これで,文章の最適なトピック数・クラスタリング数が絞れれば良いのですが,逆に候補が増えて混乱になったりも.自然言語の扱いは難しいですね.
posted by Seesaa京都スタッフ at 13:00| Comment(0) | 機械学習 | このブログの読者になる | 更新情報をチェックする

2018年03月22日

TensorFlowのハンズオンをしました

エモトです.先日,某作品のOVA・劇場版・最終章の三連続マサラ上映に参加しました.発生可能な応援上映に加えて,クラッカーや紙吹雪も大丈夫な上映形態,楽しくないわけがない.約3時間半ほど,クラッカーを発砲やイベントシーンのタイミングに合わせて鳴らしてました.次はあのシーンだなと右手で数個のクラッカーを持ち,左手でタイミングよく順々に鳴らしたときの達成感はなんともすごい.少しセーブしたものの,持ち込んだ200個のクラッカーでは足りなかった.劇場の音響の力に,クラッカーの音と火薬の匂いが混じり,とても楽しい時間でした.静かに映画を見るのも良いですが,わいわい見れる映画館も本当に良いですね.

運営協力している Kyoto.LT にて TensorFlow ハンズオンを行いました.

周りに機械学習する人・興味ある人が増えたらいいなと入門的なハンズオンをしたいと思っていましたが,環境構築で時間が終わりそうなので断念していました.そうしていたところ,Google Colab で GPU が利用できるようになったと聞き,これはやらねばということで,開催しました(実際は簡単なコードしか取り扱わなかったので CPU 計算で十分ですが).

ハンズオン資料はこちらで 公開 しています.各自の環境で ipynb ファイルを展開してもらえば,動くと思います.理論も紹介したいし,肝心のコードもやらないといけないと,時間が足りず中途半端な感じになっていますが,雰囲気を体験してもらえば幸いです.


posted by Seesaa京都スタッフ at 13:00| Comment(0) | 機械学習 | このブログの読者になる | 更新情報をチェックする