円の方程式/人工データ作成/スペクトラムクラスタリング

よくある例題データみたいなのを使ってscikit-learn(sklearn)を使ってスペクトラムクラスタリングを(英語版Wikipedia)を試そうと思っていろいろやっていたのをメモしておく.

円の方程式

凄い当たり前だけど,半径rの円上の点を生成するには三角関数(cos/sin)を使えばいい.媒介変数とし角度θ(0≦θ≦2π)として,θの基準となる軸からθだけ回転した点の(x,y)座標は (r \cos(\theta), r \sin(\theta))

人工データの作成

適当に小さい円(r=1.5)と大きい円(r=3.0)に関して人工データを作成する.どうやって二次元ベクトルを作るかよく分からなかったのでnumpy.r_[X,Y]というベクトルをくっつけてくれるっぽい感じのメソッドをそのまま使った.媒介変数θは0から2πの間を適当に分割して作った.こういう昨日はMatlabと一緒でnumpy.linspaceがやってくれる.2つ作った店の集合(small/large)を縦にくっつけるのにnumpy.r_とは反対でnumpy.c_を使った.ついでに(標準)正規分布の乱数を適当に付けた(numpy.random.randn)
import numpy as np
import scipy as sp
import matplotlib.pyplot as plt
np.random.seed(0)

N = 500
theta = np.linspace(0, 2 * np.pi, N / 2)
r1, r2 = 1.5, 3.0
small = np.c_[r1 * np.cos(theta), r1 * np.sin(theta)]
large = np.c_[r2 * np.cos(theta), r2 * np.sin(theta)]
dataX = np.r_[small, large] + np.random.randn(N, 2) * 0.25

# plot
plt.figure()
plt.plot(dataX[:,0], dataX[:,1], 'bo')
plt.savefig("sample.png")

プロットするとよくある図みたいにこうなる.
sample

スペクトラムクラスタリング

スペクトラムクラスタリングに関してはリンク先が解説してくれている(スペクトラルクラスタリングの話 – おいしいお米の話).numpy/scipyだけではなく,ここからはscikit-learnを使う.スペクトラムクラスタリングに相当する機能はsklearn.clusterに納められているクラスタリング関係のパッケージ群の中に

  • SpectralClustering (クラス)
  • spectral_clustering (関数)
の2つが何故か用意されていて,関数で直接計算する場合とクラスにいろいろとパラメータを設定してfit→predictするという,いつものsklearn方式が使える,と思いきやfit_predictという関数に統合されているという謎な感じになっている.スペクトラムクラスタリングに必要な行列W(affinity matrix)をどう計算するかという問題があるけど,データをnumpy.ndarrayの形(例えば人工データのdataX)で入れると,クラスSpectralClustering自体が計算してくれる.パラメータを設定すると,事前に自分が計算した行列を使うことも可能.以下のように使う.

# spectral clustering by scikit-learn
from sklearn.cluster import SpectralClustering, spectral_clustering
sc = SpectralClustering(n_clusters = 2, eigen_solver='arpack', affinity = 'rbf', gamma = 10.0)
assigned_labels = sc.fit_predict(dataX)

assigned_labels(SpectralClustering#fit_predictの返り値)にはfitしたデータ(dataX)の各データ点がどのクラスタ番号に割り振られたか,というラベル情報が返ってくるので,それとnumpy.whereを使ってデータを分けることが可能.

plt.figure()
c1 = dataX[np.where(assigned_labels == 1)]
c0 = dataX[np.where(assigned_labels == 0)]
plt.plot(c1[:,0], c1[:,1], 'bo')
plt.plot(c0[:,0], c0[:,1], 'rx')
plt.savefig("clustered.png")

プロットするとよくある感じの結果が得られた.

clustered

2件のコメント

  1. 本ブログで、Scikit-learnのSpectralClusteringにはクラスと関数の二種類存在することに気づくことができ、非常に助かりました。今までは、関数であるspectral_clusteringに対して一生懸命パラメータを設定しようとしてうまくいっていませんでした。
    誠にありがとうございます。

返信を残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です