paiza開発日誌

IT/Webエンジニア向け総合求人・学習サービス「paiza」(https://paiza.jp ギノ株式会社)の開発者が開発の事、プログラミングネタ、ITエンジニアの転職などについて書いています。

機械学習初心者向け、Pythonを使ってK-meansでクラスタリングしてみた

f:id:paiza:20170613144753j:plain
Photo by Rene Barrios
秋山です。

機械学習と一言で言っても、そのアルゴリズムにはたくさんの種類があり、「どれがどんな場合に適しているのか」というのは、なかなかわかりづらいと思います。

そこで今回は、初心者向けに「K-means」(k平均法)という手法について説明します。

K-meansがどんなデータに適しているか、どうやってデータが分離されるのか…といったことは、文章だけ読んでも分かりづらいと思いますので、実際にPythonでコードを書いて実行したり、図を出したりして、過程を見ながら説明していきます。

既に機械学習の経験がある人にとっては今さらなことばかりかと思いますが、「機械学習の勉強を始めたい」という人の参考になればと思います。

■K-meansとは

簡単に説明しますと、

  1. まず、各点に対してランダムにどのクラスタに属するかを決定します。
  2. 次に、各クラスタの中心点Vが決定されます。(ランダムに決まったクラスタの中心です)
  3. Vと各点における距離を求め、各点はそれぞれ一番近いクラスタに割り当て直されます。このとき、すべての点が同じクラスタに割り当て直されたら処理は終了し、そうでなければ2に戻ります。

……っというのがK-meansのアルゴリズムです。(※k平均法 - Wikipedia

3.の手順の終了条件は、一般的にはクラスタの割り当て直す数が設定した閾値以下であれば終了…となるように設定することが多いかと思います。

……と、文字だけで説明されても何だかよくわからないかと思いますので、実際にランダムで作ったテストデータのクラスタ割り当てを見て確認してみましょう。

K-meansは、scikit-learnというライブラリで簡単に使うことができます。

インストールは↓これだけでできます。

pip install scikit-learn

また、ライブラリはnumpy,pandas,matplotlibも使います。インストール方法などは、過去に書いたjupyterの記事を参考にしてください。
paiza.hatenablog.com


下記のPythonコードは、 n_samples がサンプル数、 centers がクラスタの個数です。 cluster_std はばらつきを調整しています。 random_state=3 は、ランダムジェネレートのシード値で省略すると毎回違う結果となるので、それを固定しています。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
data,cluster=make_blobs(n_samples=1000,centers=2,cluster_std=2.3, random_state=3)
plt.scatter(data[:,0],data[:,1],c='black',marker='.',s=50)
plt.grid()
plt.show()

上記コードをjupyterで実行すると、このような図が作られます。
f:id:paiza:20170613140852p:plain

cluster には、実際に2クラスタに分かれたデータが入っています。それを表示させるためには以下のようなコードを実行します。

plt.scatter(data[cluster==0,0],data[cluster==0,1],s=50,c='red',marker='.',label='1')
plt.scatter(data[cluster==1,0],data[cluster==1,1],s=50,c='black',marker='.',label='2')
plt.legend()
plt.grid()
plt.show()


上記コードをjupyterで実行すると、このような図が出ます。何となく、右上と左下に集まったデータ群…になっているのがわかりますよね。
f:id:paiza:20170613141106p:plain


それでは、K-meansを使ってクラスタが不明な状態からクラスタ分けを実行してみましょう。

from sklearn.cluster import KMeans
def t(n):
    km = KMeans(n_clusters=2,init='random',n_init=1,max_iter=n,random_state=1)
    cluster = km.fit_predict(X)
    plt.scatter(data[cluster==0,0],data[cluster==0,1],c='red',marker='.',label='1')
    plt.scatter(data[cluster==1,0],data[cluster==1,1],c='black',marker='.',label='2')
    plt.scatter(km.cluster_centers_[:,0],km.cluster_centers_[:,1],marker='X',c='red',label='centroids')
    plt.legend()
    plt.grid()
    plt.show()

KMeans(n_clusters=2,init='random',n_init=1,max_iter=n,random_state=1) というのが、K-meansを行う関数です。

上記の def t(n) では、 max_iter を n として受け取っています。こうすることで、最初に説明した手順の2.と3.の繰り返し回数を指定できます。

また、 random_state=1 では、データを作ったときと同様に、ランダムのシード値を固定しています。


1〜5回それぞれの回数を繰り返した図と、10回繰り返させた図を順に並べると……

t(1)
t(2)
t(3)
t(4)
t(5)
t(10)

回数が多いほど、少~しずついい感じにデータが分離されていってるのがわかるかと思います。


1回
f:id:paiza:20170613143001p:plain


2回
f:id:paiza:20170613143036p:plain


3回
f:id:paiza:20170613143116p:plain


4回
f:id:paiza:20170613143152p:plain


5回
f:id:paiza:20170613143253p:plain


10回
f:id:paiza:20170613143334p:plain

■まとめ

K-meansに限らず、他のアルゴリズムでも似たような感じでコードを書いて実行して結果を見ることで、機械学習への理解が深まるかと思います。

過去に「Word2Vec」「Doc2Vec」を使ってディープラーニングをやってみた記事も書いていますので、「ディープラーニングのほうが興味ある~」という方はこちらもぜひ見てみてください。
paiza.hatenablog.com

Pythonの講座も公開中!プログラミングが動画で学べるレッスン


paizaは、プログラミング未経験者・初心者向け学習サービス「paizaラーニングを、新サービスとして独立オープンいたしました。

今回記事の中で使用しているPythonの入門講座も好評公開中です。ぜひごらんください!

↓詳しくはこちら
paiza.jp

そして、paizaでは、Webサービス開発企業などで求められるコーディング力や、テストケースを想定する力などが問われるプログラミングスキルチェック問題も提供しています。
paiza.jp
スキルチェックに挑戦した人は、その結果によってS・A・B・C・D・Eの6段階のランクを取得できます。必要なスキルランクを取得すれば、書類選考なしで企業の求人に応募することも可能です。「自分のプログラミングスキルを客観的に知りたい」「スキルを使って転職したい」という方は、ぜひチャレンジしてみてください。

ITプログラマ・エンジニア向け転職・就活・学習サービスのpaiza


プログラミング入門講座|paizaラーニング

PHP入門編Ruby入門編Python入門編Java入門編JavaScript入門編C言語入門編C#入門編アルゴリズム入門編