Python3 – KMeansClustering

概要

k平均法(k-means clustering)はクラスタリングの手法の1つで、与えられたデータ群の特徴と初期値に基づいて、データを並列(非階層)のクラスターに分類する。

アルゴリズムはシンプルで、以下の手順。

  1. クラスターの数だけクラスターの代表点の初期値を設定する
  2. 代表点の位置が収束するまで以下を繰り返す
    1. データの各点から最も近い代表点を選ぶ
    2. 同じ代表点の点群から重心を算出し、新しい代表点の位置とする

このクラスは、特徴量が2つのデータ群と代表点の初期値を与えて、k平均法でクラスタリングを行うテストクラス。

2つの特徴量x_datay_dataを与えてオブジェクトを生成し、代表点の初期値x_meansy_meansを与えてメソッドを実行して結果を得る。

全コード

KMeansClusteringクラスの全コードは以下の通り。

利用方法

クラスタリングを行うインスタンスの生成

初期データを与え、KMeansClusteringクラスのインスタンスを生成する。

コンストラクターに与える引数は以下の通り。

x_data, y_data
クラスタリングを行うデータの特徴量x、yの配列(1次元のndarray)。

クラスタリングの実行

生成したインスタンスに対して、クラスタリングを行うメソッドを実行して結果を得る。

メソッドに与える引数は以下の通り。

x_means, y_means
k個のクラスターの代表点の初期値(1次元のndarray)。

結果は以下のタプルで与えられる。

x_means, y_means
クラスターの代表点のx、yの配列。収束までの各計算段階の値を記録しており、2次元のndarrayの各行が各計算ステップに相当。
groups
各データが属するクラスター(代表点)番号のndarray

実行例

以下のコードでKMeansClusteringクラスをテスト。内容は以下の通り。

  1. 2つの円状に散らばるランダムな点群を発生させ、1つのデータとしてまとめる
    • random_scatter_dataは指定した中心・半径の円内に指定した数のランダムな点を発生させるモジュールで、別途作成(最後の方にコードを掲載)
  2. クラスターの代表点の数と位置、散布図を描画するパラメーターを設定する
    • プロットする図の数は2行3列で固定し、初期状態を除いた5つの図を表示させる
    • 予め実行させてコンソールで収束回数を確認し、33行目で表示させる計算ステップを指定している
  3. 初期状態の散布図をプロット
  4. クラスタリングを行うKMeansClustringオブジェクトを生成し、結果を得るためのメソッドを実行(53-54行目)
  5. 結果をプロット

このコードの実行結果はコンソールで以下のように表示される。

この結果から1、2、3、5、7回目の計算結果を図示するよう上のコードでセットした表示結果は以下の通り。

グループが比較的明確なので、早い段階で代表点の位置が定まっている。

クラス説明

__init__()~インスタンス生成

クラスタリングを行うデータの特徴量x_datay_datandarrayで与えてインスタンスを生成。

プライベート・メンバーは以下の通り。

_x, _y
クラスタリングを行うデータの2つの特徴量の配列。計算過程で変更されない。
_x_means, _y_means
代表点の計算結果を保存していく配列。分析実行時に初期値が与えられるため、初期値はNone。
_num_data
データの個数。
_num_means
代表点(クラスターの個数)。代表点が分析実行時に与えられるため、初期値は0。
_groups
各データの属するクラスターを保存していく配列。

get_result()~分析の実行

k個の代表点のx、yを引数として渡し、結果を得る。

引数

_x_means, _y_means
k個の代表点の初期値x、yを、それぞれ1次元のndarrayで与える。引数で与えた配列は変更されない。

戻り値

x_means, y_means
代表点の計算結果が保存された配列。各行は計算ステップに相当。
groups
各計算ステップにおける、各点のクラスターが保存された配列。各行は計算ステップに相当。

処理内容

  1. 代表点の初期値をプライベート・メンバーにコピーし、代表点の個数をセット
  2. 全ての代表点の位置が収束するまで、以下を繰り返す
    1. 各データについて、最も近い代表点をセット
    2. 共通の代表点を持つデータから、新しい代表点の位置を計算
    3. 代表点の前回最後の計算値と今回の計算値が収束したならループ終了、でなければ計算結果を追加してループ継続
  3. 計算結果を戻り値として終了

プライベートメソッド

_distance()~2点間の距離

2つの点の距離を与える。ここではユークリッド距離の2乗。

_point_converged()~収束判定

2つの点の座標から、点の位置が収束したかどうかを判定。

本来、各座標値はfloatなので'=='による判定は危険だが、ここでは収束の速さと確実性を信じて簡易に設定。

_all_points_converged()~全ての点の収束判定

配列で与えた2組の点がすべて収束条件を満たしているか判定。

_set_nearest_mean_point()~各点に最も近い代表点

処理内容

  1. 各データについて、それぞれから最も近い距離にある代表点を探し、その番号を1次元の配列groupsに記録
  2. _groups配列に、今回の分類結果を行として追加

_revise_mean_points()~代表点の更新

同じ代表点に属するデータからそれらの重心を計算し、新しい代表点として返す。

random_scatter_data.py

今回整理のためにつくったモジュールで、内容は以下の通り。

 

3件のコメント

  1. random_scatter_data モジュールが見つからないんですが、残念ですね。

    1. まに合わせの自作モジュールだったので「別途作成」とだけしていましたが、この記事の最後にコードを掲載しました。
      ご示唆ありがとうございました。

  2. 傑作、大変勉強できました。
    これからも期待満々です。

コメントを残す

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