sklearn.cluster.KMeans をつかってみたいときとかあると思います。iris データにつかうと以下のようになります。
# -*- coding: utf-8 -*- import pandas from sklearn import datasets from sklearn.cluster import KMeans from sklearn.metrics import confusion_matrix if __name__ == "__main__": iris = datasets.load_iris() predict = KMeans(n_clusters=3).fit(iris.data) mat = pandas.DataFrame(confusion_matrix(iris.target, predict.labels_)) mat.index = iris.target_names print(mat)
0 1 2 setosa 0 50 0 versicolor 48 0 2 virginica 14 0 36
setosa はすべてクラスタ1に分類され(かつ、クラスタ1に他の品種は混ざっていない)、一方、virginica はクラスタ0とクラスタ2に分裂してしまったことがわかります。各品種が分類された最大クラスタが対角線上に並んでいないと見にくいという人は、以下のように列を入れ替えてください。
mat = mat.loc[:,mat.idxmax(axis=1)] mat.columns = range(iris.target_names.shape[0]) print(mat)
0 1 2 setosa 50 0 0 versicolor 0 48 2 virginica 0 14 36
クラスタリングした結果、各クラスタの重心はどこになったかも確認できます(以下)。
print(predict.cluster_centers_)
[[ 6.85 3.07368421 5.74210526 2.07105263] [ 5.006 3.418 1.464 0.244 ] [ 5.9016129 2.7483871 4.39354839 1.43387097]]
初期クラスタ重心を与えることもできます。
以下のようにすれば元データの 0 番目、50 番目、100 番目を初期クラスタ重心にできます。
# -*- coding: utf-8 -*- import numpy import pandas from sklearn import datasets from sklearn.cluster import KMeans from sklearn.metrics import confusion_matrix if __name__ == "__main__": iris = datasets.load_iris() initial_centers = numpy.array([iris.data[0], iris.data[50], iris.data[100]]) predict = KMeans(n_clusters=3, init=initial_centers).fit(iris.data) mat = pandas.DataFrame(confusion_matrix(iris.target, predict.labels_)) mat.index = iris.target_names print(mat) print(predict.n_iter_)
ただし、これを実行すると以下のように警告文が出てきます。これの意味は、KMeans はクラスタ初期化方法が k-means++(デフォルト)や random の場合はデフォルトで n_init=10 通りの初期値からのクラスタリングを試み、最もよいクラスタリング結果を出力します(モーメントがよく更新され続けた回をもっともよいクラスタリング結果とする)。しかし、初期クラスタ重心が明示的に与えられたときにはその他の初期化を試みるのはおかしいので、デフォルトの n_init=10 は無視して1回しかクラスタリングを試みませんよという意味です。その代わりにというか、クラスタリングのイテレーション回数 n_iter_ が返却されます。クラスタ重心は3回更新されるのみだったようです。
/usr/local/lib/python2.7/site-packages/sklearn/cluster/k_means_.py:889: RuntimeWarning: Explicit initial center position passed: performing only one init in k-means instead of n_init=10 return_n_iter=True) 0 1 2 setosa 50 0 0 versicolor 0 48 2 virginica 0 14 36 3