クリーム色の背景、色付き表示、高コントラスト、大きな文字のほうが読みやすいですか?配色と文字を選ぶと、すべてのページに一度で反映されます。

無料レッスン

ラベルなしのデータを分ける(k-means)

このレッスンのあとで: k-means で、ラベルのないデータをグループに分けられる。

50分のレッスンコマンド2件JupyterLab データサイエンスラボ:pandas、Matplotlib、scikit-learn をブラウザーで

だれも名前をつけていない日の種類

店は、シフト表を3種類作りたいと考えています。暇な日用、ふつうの日用、混む日用です。けれど、どの日が暇で、どの日が混んだかを記録した人はいません。

学ぶための答えの列がないのです。日が自分でグループに分かれ、そのグループが筋の通ったものかを、あなたが判断します。

このレッスンのゴール

メモ

k-means で、ラベルのないデータをグループに分けられる。

キーワード

ことばいみれい
ラベルなしデータ答えの列がない行
クラスタたがいに近い行のまとまり
重心クラスタの点の平均の位置
k-meansグループが変わらなくなるまで k 個の重心を動かす方法
標準化距離を測る前に、特徴量の散らばりをそろえること
慣性各点から重心までの距離の2乗の合計inertia

学生が入力するセルは、このプレビューでは空白です。

k-meansは2つの手順をくり返す

まず、グループの数 k を選びます。点のあいだに、中心を k 個置きます。

そして2つの手順をくり返します。すべての点を、いちばん近い中心に入れます。すべての中心を、自分の点の平均へ動かします。これが重心です。グループが変わる点がなくなったら終わりです。始める場所が違うと結果も変わりうるので、scikit-learn は何度か試して、いちばんよいものを残します。

1ステップを手で

コード: python
# 6日分を、台数だけで k-means の1ステップにかけます。
days = [110, 140, 175, 290, 320, 430]
centres = [100, 400]

groups = [[], []]
for one in days:
    if abs(one - centres[0]) <= abs(one - centres[1]):
        groups[0].append(one)
    else:
        groups[1].append(one)
print("グループ:", groups)
for n in range(2):
    centres[n] = round(sum(groups[n]) / len(groups[n]), 1)
print("新しい中心:", centres)
# 新しい中心から、もう一度ステップを実行してください。
# グループが変わる日はありますか。

距離を測る前に尺度をそろえる

台数は1日に41台から487台まで動きます。気温は約 -1 度から25度です。台数の10の差は小さく、気温の10度の差は大きいものです。

けれど距離は、どちらの10も同じに扱います。尺度をそろえないと、台数がすべてを決めてしまいます。StandardScaler は、各特徴量の平均を0にし、散らばりをそろえます。こうすると、どの特徴量も公平に数えられます。

ノートブックに入力: そろえない場合

コード: python
import pandas as pd
from sklearn.cluster import KMeans

hires = pd.read_csv("hires.csv")
# 尺度をそろえません。台数は数百、気温は26ほどの幅です。
hires["raw"] = KMeans(n_clusters=3, n_init=10, random_state=0).fit_predict(hires[["temp_c", "hires"]])
hires.groupby("raw")[["temp_c", "hires"]].agg(["min", "max"])

そろえてから日を分ける

コマンド
docker exec jupyter python3 steps/kmeans.py

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

ノートブックに入力: グループの月

コード: python
from sklearn.preprocessing import StandardScaler

scaled = StandardScaler().fit_transform(hires[["temp_c", "hires"]])
hires["group"] = KMeans(n_clusters=3, n_init=10, random_state=0).fit_predict(scaled)
# グループごとに、いちばん多い月を見ます。
hires.groupby("group")["month"].agg(lambda s: s.value_counts().index[0])

よくある間違い

注意

k-means は、データに本当はいくつのグループがあるかを見つけると考えがちです。実際は、グループのないデータからでも、頼まれたとおり k 個のグループを返します。k を選ぶことと、グループに名前をつけることは、あなたの判断です。

エルボーがkの選び方を助ける

慣性は、各点から重心までの距離の2乗の合計です。グループを増やすと必ず下がり、1点に1グループなら0になります。

そこでエルボー、つまりひじを探します。そこから先は、グループを足してもあまり得をしない k です。そのうえで、そのグループが店の役に立つかを問います。

kを1から6まで変えて散らばりを見る

コマンド
docker exec jupyter python3 steps/elbow.py

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

さらに挑戦: 3つの特徴量で分ける

ノートブックで、気温、雨、台数の3つを、すべてそろえてから分けてください。k = 3 と k = 4 を試します。

グループごとに、日数と、各特徴量の平均を表示します。シフトを組む人にわかる名前を各グループにつけ、どちらの k を選ぶか、理由と一緒に書きましょう。

このラボとソースについて: JupyterLab データサイエンスラボ:pandas、Matplotlib、scikit-learn をブラウザーで

授業で使いますか?このモジュールを学生に割り当てると、教員用ガイド、自動採点つきの課題、学生ごとのラボを使えます。