広告の限界を超える|セールス
広告の限界を超える|セールス
2018.06.08

Pythonでクラスタ分析(K-means法)をやってみた

Jack

こんにちは、マネージャーのジャックです。
本日も、プログラミングネタで記事を執筆していこうと思います。

最近、というかかなり前からですが、AIやらビックデータ分析やらが流行っていますよね。「◯◯という手法を使ってクラスタリングしてみた!」とか「分析してみた!」などの話題は、様々なメディアで見かけることが多くなりました。

本日は、完全なる個人的な趣味で「クラスタ分析」について書いていきたいと思います。

さて、クラスタ分析とは何でしょうか? 以前、このような記事を見かけました。

クラスター分析は、ビッグデータの分析、その中でもOne to Oneマーケティングに用いる分析手法としては、最も重要な地位を占めており、最もよく使われる手法の1つだ。
(引用元:最も重要で、最もよく使われ、最も難しい分析手法の一つ「クラスター分析」

なるほど、すごそうです。
そして、引用した記事はクラスタ分析について非常にわかりやすく説明されています。
(この記事の意味……というのは置いておいて……)

クラスタ分析とは?

クラスタ分析について簡単に説明させていただきます。
クラスタ分析とはデータ解析手法のひとつで、異なるものが混ざりあっている集団の中から互いに似たものを集めてクラスタを作る分類手法です。
「教師なし学習」という機械学習の手法の一種です。

そして、クラスタ分析には「階層クラスタ分析」と「非階層クラスタ分析」があります。

階層クラスタ分析

階層クラスタ分析は、最も類似度が高い(似ている)組み合わせからまとめていく手法になります。
事前にクラスタ数を決める必要がなく、最終的にはツリー状のデンドログラム(樹形図)を書くことができます。

非階層クラスタ分析

非階層クラスタ分析とは、事前に何個のクラスタに分けるかを決め、その決めたクラスタ数になるようにまとめていく手法の事です。
代表的な手法に「K平均法(K-means法)」があります。
今回は、K-means法に関して書いていきたいと思います。

K-means法とは?

K-means法とは、先ほども説明させていただいたとおり、非階層のクラスタ分析手法です。
クラスタ平均を用い、与えられたクラスー数をk個に分類することからこの名称が付けられました。
K個のクラスタに平均を用いてまとめていく手法です。

PythonでK-means法を実装してみる

せっかくなので、PythonでK-means法を実装してみたいと思います。
百聞は一見に如かずというやつですね。とりあえず、コードを書いて肌でK-means法を感じてみましょう。

今回は、scikit-learnを用いて実装してみます。scikit-learnとは、Pythonのオープンソース機械学習ライブラリです。
K-means法以外に、SVM(サポートベクターマシン)、ランダムフォレストなどの様々なアルゴリズムを一瞬で実装できます。便利ですよね。

使用するデータ

今回、使用するデータは、UCバークレー大学の UCI Machine Leaning Repository にて公開されている、「Iris」データを利用します。機械学習のテストでは、よく利用されるデータセットですので一度は見たことがある方もいるもしれません。

下記リンクからダウンロードすることができます。
Iris Data Set

このデータセットは、あやめのデータであり、「setosa」、「versicolor」、「virginic」の種類が存在します。

そして、このあやめデータは、がく片の長さ、 がく片の幅、花びらの長さ、花びらの幅の計4種類の特徴データを保持しています。

実際にPythonインタプリタで動かしてみる

必要ライブラリを読み込む

まず、Pythonインタプリタを起動し、必要なライブラリを読み込みます。scikit-learn以外にも、pandasライブラリを利用します。

% python
import pandas as pd
import numpy as np
from sklearn.cluster import KMeans

データセットを読み込む

次に利用するデータを読み込んでみましょう。今回を利用するiris.dataにはヘッダーが付与されていないので、read_csvメソッドの第2引数にheader=Noneを指定してください。

cust_df = pd.read_csv("iris.data", header=None)
cust_df
0 1 2 3 4
0 5.1 3.5 1.4 0.2 Iris-setosa
1 4.9 3.0 1.4 0.2 Iris-setosa
2 4.7 3.2 1.3 0.2 Iris-setosa
3 4.6 3.1 1.5 0.2 Iris-setosa
4 5.0 3.6 1.4 0.2 Iris-setosa
5 5.4 3.9 1.7 0.4 Iris-setosa
6 4.6 3.4 1.4 0.3 Iris-setosa
7 5.0 3.4 1.5 0.2 Iris-setosa
8 4.4 2.9 1.4 0.2 Iris-setosa
9 4.9 3.1 1.5 0.1 Iris-setosa
10 5.4 3.7 1.5 0.2 Iris-setosa
11 4.8 3.4 1.6 0.2 Iris-setosa
12 4.8 3.0 1.4 0.1 Iris-setosa
13 4.3 3.0 1.1 0.1 Iris-setosa
14 5.8 4.0 1.2 0.2 Iris-setosa
15 5.7 4.4 1.5 0.4 Iris-setosa
〜中略〜
136 6.3 3.4 5.6 2.4 Iris-virginica
137 6.4 3.1 5.5 1.8 Iris-virginica
138 6.0 3.0 4.8 1.8 Iris-virginica
139 6.9 3.1 5.4 2.1 Iris-virginica
140 6.7 3.1 5.6 2.4 Iris-virginica
141 6.9 3.1 5.1 2.3 Iris-virginica
142 5.8 2.7 5.1 1.9 Iris-virginica
143 6.8 3.2 5.9 2.3 Iris-virginica
144 6.7 3.3 5.7 2.5 Iris-virginica
145 6.7 3.0 5.2 2.3 Iris-virginica
146 6.3 2.5 5.0 1.9 Iris-virginica
147 6.5 3.0 5.2 2.0 Iris-virginica
148 6.2 3.4 5.4 2.3 Iris-virginica
149 5.9 3.0 5.1 1.8 Iris-virginica

[150 rows x 5 columns]

不要なカラムを削除する

K-meansにかける際に、setosaなどのラベル名情報などの不要カラムは削除していきます。削除するには、下記コマンドを実行してみましょう。

del(cust_df[4])
cust_df
0 1 2 3
0 5.1 3.5 1.4 0.2
1 4.9 3.0 1.4 0.2
2 4.7 3.2 1.3 0.2
3 4.6 3.1 1.5 0.2
4 5.0 3.6 1.4 0.2
5 5.4 3.9 1.7 0.4
6 4.6 3.4 1.4 0.3
7 5.0 3.4 1.5 0.2
8 4.4 2.9 1.4 0.2
9 4.9 3.1 1.5 0.1
10 5.4 3.7 1.5 0.2
11 4.8 3.4 1.6 0.2
12 4.8 3.0 1.4 0.1
13 4.3 3.0 1.1 0.1
14 5.8 4.0 1.2 0.2
15 5.7 4.4 1.5 0.4
〜中略〜
136 6.3 3.4 5.6 2.4
137 6.4 3.1 5.5 1.8
138 6.0 3.0 4.8 1.8
139 6.9 3.1 5.4 2.1
140 6.7 3.1 5.6 2.4
141 6.9 3.1 5.1 2.3
142 5.8 2.7 5.1 1.9
143 6.8 3.2 5.9 2.3
144 6.7 3.3 5.7 2.5
145 6.7 3.0 5.2 2.3
146 6.3 2.5 5.0 1.9
147 6.5 3.0 5.2 2.0
148 6.2 3.4 5.4 2.3
149 5.9 3.0 5.1 1.8

[150 rows x 4 columns]

不要カラムを削除することができましたね。

PandasのデータフレームからNumPyの行列に変換する

そして、PandasのデータフレームからNumPyの行列に変換し、データの事前準備が完了します。下記コマンドを実行してみましょう。

cust_array = np.array([ cust_df[0].tolist(), cust_df[1].tolist(), cust_df[2].tolist(), cust_df[3].tolist()], np.int32)
cust_array = cust_array.T # 転置行列の作成
cust_array
array([[5, 3, 1, 0],
[4, 3, 1, 0],
[4, 3, 1, 0],
[4, 3, 1, 0],
[5, 3, 1, 0],
[5, 3, 1, 0],
[4, 3, 1, 0],
[5, 3, 1, 0],
[4, 2, 1, 0],
〜中略〜
[6, 3, 5, 2],
[6, 3, 5, 2],
[6, 3, 5, 2],
[6, 2, 5, 1],
[6, 3, 5, 2],
[6, 3, 5, 2],
[5, 3, 5, 1]], dtype=int32)

これでデータの前処理は終了です。では、いよいよ本題のクラスタ分析を実行してみましょう!!

クラスタ分析(K-means法)を実行してみる

K-means法でクラスタ分析を実行するには、KMeansメソッドを利用します。
今回は、クラスタ数は4(n_clusters=3)としています。

pred = KMeans(n_clusters=3).fit_predict(cust_array)
pred
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, 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, 1, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2], dtype=int32)

お!何やらそれっぽい感じの結果が返ってきましたね!
Pandasのデータフレームにクラスタ番号を追加して、各クラスタに属するサンプル数の分布を見てみましょう。

cust_df[ 'cluster_id']=pred
cust_df[ 'cluster_id'].value_counts()
2 56
0 50
1 44
Name: cluster_id, dtype: int64

cluster_idは、それぞれ「setosa=0」、「versicolor=1」、「virginic=2」と定義していますので、setosaのクラスタに50件、versicolorのクラスタに44件、virginicのクラスタに56件のデータがクラスタリングされたことがわかります。

おわりに

本日は、PythonでK-meansというクラスタ分析についてお話させていただきました。あくまで基礎的な内容ですので、実際に案件などで利用する際は、もっと周辺知識含めて勉強しないとですね……。現業をやりながら粛々と勉強をしていこうと思います。