クラスタリングを学習することによって、顧客を特徴によって分割できます。うまく分割できれば、それぞれ別のモデルを作って精度を上げられます。
クラスタリング(clustering)とは、機械学習の1種でデータ間の類似度にもとづいて、データをグループ分けする手法です。この単語は機械学習や統計学の文脈以外でも使われることが多いため、これらの分野で用いられる際にはクラスタ分析やデータ・クラスタリングと呼ばれるのが通例となっています。
https://www.tryeting.jp/column/1049/#:~:text=%E3%82%AF%E3%83%A9%E3%82%B9%E3%82%BF%E3%83%AA%E3%83%B3%E3%82%B0%EF%BC%88clustering%EF%BC%89%E3%81%A8%E3%81%AF%E3%80%81,%E9%80%9A%E4%BE%8B%E3%81%A8%E3%81%AA%E3%81%A3%E3%81%A6%E3%81%84%E3%81%BE%E3%81%99%E3%80%82
機械学習において、「正解がないデータを扱う学習」を教師なし学習といいます。主に教師なしで分類する方法を言う。
ここでは、教師なし学習の1つであるk-means法を使って、クラスタリング(グループ分け、セグメンテーション)をしてみましょう。
顧客をクラスタリングすることで、クラスター(グループ、セグメント)ごとの販売傾向がわかり、販売促進に役立てられます。
%run 1.ipynb
df.head()
前回からの引継ぎ
# クラスタリングする
from sklearn.cluster import k_means
n_clusters = 2
centroid, label, inertia = k_means(df, n_clusters, random_state=0)
centroid, label, inertia
(array([[ 3878.18181818, 48025. , 4523.18181818, 611.47727273],
[39687.14285714, 16130.35714286, 2213.75 , 247.19642857]]),
array([0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0,
1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0,
0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1,
0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0,
0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0], dtype=int32),
39727838655.12175)
# ラベル0を取り出す
df0 = df[label == 0]
df0_mean = df0.mean()
df0_mean
Recruit 3878.181818
Custom 48025.000000
Shirt 4523.181818
Accessory 611.477273
dtype: float64
# ラベル1を取り出す
df1 = df[label == 1]
df1_mean = df1.mean()
df1_mean
Recruit 39687.142857
Custom 16130.357143
Shirt 2213.750000
Accessory 247.196429
dtype: float64
k-means法(sklearn.cluster.k_means
)では、クラスターの数(n_clusters
)を指定する必要があります。
今回は、2
を指定します。
k-means法では、ランダムな初期値を使いますが、デフォルトでは、k-means++法という、初期値がなるべく離れるように工夫された方法を使います。
乱数を使うので、実行するたびに結果が変わることがあります。もし、何度実行しても同じ結果が欲しいのであれば、乱数の元であるrandom_state
に適当な値を指定してください。
返り値は、「クラスターごとの中心、クラスターのラベルの配列、中心との距離の自乗和」のタプルです。
centroid
:クラスターごとの中心(行:クラスター、列:Recruit, Custom, Shirt, Accessory
)label
:クラスターのラベルの配列inertia
:中心との距離の自乗和(この値を最小化するようにクラスタリングします)
クラスターのラベルの配列を使って、顧客を2つに分けてみましょう。
df[label == 0]
とするとラベルが0
のものを取り出せます。
mean
で平均を見ると、ラベル0はCustom
系で、ラベル1がRecruit
系と言えそうです。また、ラベル1の方が全体的に販売額が高そうです。
この分析から、ラベル0に分類された顧客を参考にしてカスタムメイド用のコーディネートを、ラベル1に分類された顧客を参考にしてリクルート用のコーディネートが考えられます。
sklearn.cluster.KMeans
を使うとk-means法のモデルを作成して、分類と同じようにfit
やpredict
も使えます。
from sklearn.cluster import KMeans
km = KMeans(n_clusters, random_state=0) # k-means法のモデル
km.fit(df) # 当てはめ
km.predict(df) # labelsと同様の結果が得られます
n_clusters = 2
として、centroid, label, inertia = k_means(df, n_clusters, random_state=0)
で2つにクラスタリングしました。
centroid, label, inertia
は、「クラスターごとの中心、クラスターのラベルの配列、中心との距離の自乗和」でしたね。
2つのクラスターを以下のようになりました。
- ラベル0に割り当てられたクラスター:Customの売上が大きい
- ラベル1に割り当てられたクラスター:Recruitの売上が大きい
また、売上に占める割合は小さいですが、ラベル0の方がShirtとAccessoryの売上が大きいこともわかります。
補足
df.sum()
のようにDataFrameの多くのメソッドは、axis
オプションで行方向(=0
)か列方向(=1
)を指定できます。
デフォルトは、行方向に計算し、結果は列ごとになります。df.sum(1)
は、列方向に計算し、結果は行ごとになります。
行または列ではなく、表全体の要素の合計を調べるには、df.sum().sum()
のようにできます。
コメント