Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

k-means

アルゴリズム

DD次元ユークリッド空間上の確率変数XXのNN個の観測点で構成されるデータ集合{x1,...,xN}\{x_1, ..., x_N\}があるとする。

このデータをKK個のクラスターに分割したい。(簡単のため、まずKKは既知とする。)

クラスターとは、クラスター内のデータ点同士の距離がクラスター外の点との距離よりも小さいグループであると想定する。

プロトタイプと呼ばれるKK個のDD次元ベクトルμk(k=1,…,K)\boldsymbol{\mu}_k (k = 1,\dots, K)を導入し、これがkk番目のクラスターの中心を表すとする。

目的関数LLは 歪み尺度 (distortion measure) と呼ばれる、各データ点とμk\boldsymbol{\mu}_kの二乗距離の総和で、

L=∑i=1N∑k=1Krik∥xi−μk∥2L = \sum^N_{i=1} \sum^K_{k=1} r_{ik} \| \boldsymbol{x}_i - \boldsymbol{\mu}_k \|^2

となる。ここでrik∈{0,1}r_{ik}\in \{0, 1\}は、ii番目の観測点ベクトルxi\boldsymbol{x}_iがkkに属するかどうかを示す変数。

k-meansの推定はrikr_{ik}の推定とμk\boldsymbol{\mu}_kの推定を交互に繰り返すことで求める(EMアルゴリズムのように行う)。

rikr_{ik}の推定

kkに属するのはxi\boldsymbol{x}_iとμj(j=1,…,K)\boldsymbol{\mu}_j (j=1,\dots, K)の距離が他のクラスより短いときなので、

rik={1k=arg⁡min⁡j∥xi−μj∥20それ以外r_{ik} = \begin{cases} 1 & k = \arg \min_j \| \boldsymbol{x}_i - \boldsymbol{\mu}_j \|^2\\ 0 & それ以外 \end{cases}

となる。

μk\boldsymbol{\mu}_kの推定

rikr_{ik}を固定した下でのμk\boldsymbol{\mu}_kの最適化を考える。目的関数LLはμk\boldsymbol{\mu}_kの二次関数であり、μk\boldsymbol{\mu}_kに関する偏微分を0とおくことで最適化できる。

2∑i=1Nrik(xi−μk)=02 \sum^N_{i=1} r_{ik} (\boldsymbol{x}_i - \boldsymbol{\mu}_k) = 0

これをμk\boldsymbol{\mu}_kについて解くと、

μk=∑i=1Nrikxi∑i=1Nrik\boldsymbol{\mu}_k = \frac{\sum^N_{i=1} r_{ik} \boldsymbol{x}_i}{\sum^N_{i=1} r_{ik}}

分母はkk番目のクラスタに選ばれたサンプル数に等しいので、上の式は単純に算術平均の形になっている。

この「rikr_{ik}の推定」と「μk\boldsymbol{\mu}_kの推定」の2ステップを、データ点のクラスターへの再割り当てがおこらなくなるまで、あるいはあらかじめ決めておいた反復数に達するまで繰り返してクラスタリングを行う。

実装

データセットの用意

irisデータを使う

Loading...
<Figure size 640x480 with 1 Axes>

1. rrの推定

乱数で適当なμ\muの初期値を作る

array([[0.5488135 , 0.71518937, 0.60276338], [0.54488318, 0.4236548 , 0.64589411]])
rik={1k=arg⁡min⁡j∥xi−μj∥20それ以外r_{ik} = \begin{cases} 1 & k = \arg \min_j \| \boldsymbol{x}_i - \boldsymbol{\mu}_j \|^2\\ 0 & それ以外 \end{cases}

なので

2. μ\muの推定

μk=∑i=1Nrikxi∑i=1Nrik\boldsymbol{\mu}_k = \frac{\sum^N_{i=1} r_{ik} \boldsymbol{x}_i}{\sum^N_{i=1} r_{ik}}

なので、そのクラスに属するサンプルで平均をとる

反復的に推定


--- iteration 0 ---
r[:5, ]=array([[1., 0., 0.],
       [1., 0., 0.],
       [1., 0., 0.],
       [1., 0., 0.],
       [1., 0., 0.]])
mu=array([[-0.86241763,  0.65672986, -0.00538524],
       [ 0.16687246, -0.54940295,  1.76074949]])


--- iteration 1 ---
r[:5, ]=array([[1., 0., 0.],
       [1., 0., 0.],
       [1., 0., 0.],
       [1., 0., 0.],
       [1., 0., 0.]])
mu=array([[-1.03447069,  0.60948424, -0.01615572],
       [ 0.17494954, -0.51096196,  1.67506514]])


--- iteration 2 ---
r[:5, ]=array([[1., 0., 0.],
       [1., 0., 0.],
       [1., 0., 0.],
       [1., 0., 0.],
       [1., 0., 0.]])
mu=array([[-1.09454976,  0.58326887, -0.01615572],
       [ 0.19541148, -0.49758611,  1.67506514]])

分類としての評価

array([0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 2, 2, 2, 0, 2, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 2, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1])
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 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])
<Figure size 640x480 with 2 Axes>

分類精度でみるといまいちだが、もともとデータ点にオーバーラップが多いため特徴選びが問題

Centroidの位置

人間の感覚とも概ね合致したクラスターの中心点が取れているのではないか

<Figure size 640x480 with 1 Axes>