AI: 教師なし学習
最終更新:2026-08-26
もしデータにラベルが付いていなかったら?大規模なユーザー行動記録、遺伝子配列、センサーデータといった「正解」のないデータに直面したとき、教師なし学習は隠れたパターンを掘り起こす強力な道具になります。この章ではクラスタリングと次元削減という二つの主なアプローチを取り上げ、K-Means と PCA の原理と実践的応用を理解します。
1. 学べること
- 教師なし学習と教師あり学習の本質的な違い
- K-Means クラスタリングアルゴリズムの原理と実装
- 最適な k 値を選ぶエルボー法
- PCA 次元削減の直感と数学的妥当性
- クラスタリングと次元削減の実ビジネスでの応用
2. ストーリー:10 万人のユーザー――誰がグループ分けを助けてくれる?
(1) 痛みの種:巨大なユーザー基盤、手の付けようがない
Charlie のマーケティングチームには 10 万件のユーザーデータ――支出額、購入頻度、登録期間、直近の活動時間など――がありましたが、誰もユーザーをどうセグメントすべきか分かりません。経験則でマーケティング部はユーザーを「新規ユーザー」と「既存ユーザー」の 2 つに分け、クーポンを送りましたが、转化率はわずか 2.3% でした。CEO は 5% への引き上げを要求し、チームは途方に暮れました。
(2) AI のアプローチ:クラスタリングでユーザー群を自動識別
Alice が引き継ぐと、K-Means でユーザーを 4 つのグループにクラスタリングしました。
| クラスタ ID | 特徴 | 割合 | 名称 |
|---|---|---|---|
| グループ 0 | 高支出・低頻度 | 15% | 高価値購入層 |
| グループ 1 | 低支出・高頻度 | 35% | 活発なバーゲンハンター |
| グループ 2 | 高支出・高頻度 | 10% | コア VIP |
| グループ 3 | 低支出・低頻度 | 40% | 非アクティブ層 |
各グループに異なるクーポンを送りました。高支出層には新商品を推奨し、活発なバーゲンハンターには割引クーポンを、コア VIP には専用特典を、非アクティブ層には再有効化の red packet(紅包)を送りました。转化率は 2.3% から 3.1% へと跳ね上がり、35% の増加となりました。
(3) メリット:「当てずっぽう」から「データ駆動」へ
Charlie は気づきました。教師なし学習の力は予測にあるのではなく、「存在すら知らなかったものを発見すること」にあります。ラベルも事前知識もなくても、アルゴリズムはデータの中から意味のあるグループを見つけ出せます。それが教師なし学習の価値です。
3. 教師なし学習 vs 教師あり学習
(1) 主な違い
| 比較軸 | 教師あり学習 | 教師なし学習 |
|---|---|---|
| 学習データ | ラベル付き(X → y) | ラベルなし(X のみ) |
| 目的 | 既知のカテゴリ/値を予測 | データの潜在的構造を発見 |
| 典型タスク | 分類、回帰 | クラスタリング、次元削減、アソシエーションルール |
| 評価手法 | 正解率、F1、RMSE など | シルエット係数、イナーシャ、可視化 |
| 比喩 | 先生が生徒に動物の見分け方を教える | 子供がおもちゃを色で勝手に仕分ける |
| 代表アルゴリズム | 決定木、SVM、線形回帰 | K-Means、PCA、DBSCAN |
(2) なぜ教師なし学習が必要か?
- ラベル付けコストが高い: 医療画像のアノテーションには専門家が必要で、1 画像あたり $50–$200 のコスト
- ラベルが存在しない: ユーザーセグメンテーション、異常検知――「正解」が存在しない
- 探索的分析: まずクラスタリングしてデータの様子を見てから、教師あり学習でどうするか決める
4. K-Means クラスタリング
(1) クラスタリングとは何か?
クラスタリングは、似たデータ点を同じグループに、異なるものを別のグループにまとめるプロセスです。鍵となる問いは:「似ている」とは何か? ――これは通常、距離尺度で測ります。最も一般的なのはユークリッド距離です。
(2) K-Means アルゴリズムの流れ
K-Means は最も古典的で実用的なクラスタリングアルゴリズムです。その核心アイデアは:「データを k 個のクラスタに分割し、各データ点とそのクラスタ重心までの距離の和を最小化する」ことです。
flowchart TD
A[重心をランダムに k 個初期化] --> B[各点を最も近い重心に割り当て]
B --> C[割り当てられた点の平均で重心を再計算]
C --> D{重心が変化した?}
D -- Yes --> B
D -- No --> E[収束!クラスタを出力]
style A fill:#e1f5fe
style E fill:#e8f5e9
style D fill:#fff3e0
アルゴリズムの手順:
- 初期化: k 個の点をランダムに選び初期重心とする
- 割り当て: 各データ点を、最も近い重心を持つクラスタに割り当てる
- 更新: 各クラスタの重心(クラスタ内全点の平均)を再計算する
- 反復: 重心が変わらなくなるか、最大反復回数に達するまで手順 2–3 を繰り返す
▶ サンプル: 顧客データの K-Means クラスタリング(難易度:⭐)
from sklearn.cluster import KMeans
import numpy as np
np.random.seed(42)
group_a = np.random.normal(loc=[20, 80], scale=5, size=(30, 2))
group_b = np.random.normal(loc=[80, 20], scale=5, size=(30, 2))
group_c = np.random.normal(loc=[50, 50], scale=5, size=(30, 2))
X = np.vstack([group_a, group_b, group_c])
kmeans = KMeans(n_clusters=3, random_state=42, n_init=10)
kmeans.fit(X)
print(f"クラスタ中心:\n{kmeans.cluster_centers_}")
print(f"イナーシャ(二乗距離の和): {kmeans.inertia_:.2f}")
print(f"最初の 10 件のラベル: {kmeans.labels_[:10]}")
クラスタ中心:
[[50.14 49.60]
[20.38 79.63]
[80.27 19.44]]
イナーシャ(二乗距離の和): 1310.56
最初の 10 件のラベル: [1 1 1 1 1 1 1 1 1 1]
(3) 三つのクラスタリングアルゴリズムの比較
| 比較軸 | K-Means | 階層的クラスタリング | DBSCAN |
|---|---|---|---|
| k の指定が必要 | はい | いいえ | いいえ(eps/min_samples の指定が必要) |
| クラスタの形状 | 球形 | 任意 | 任意 |
| ノイズ処理 | 弱い | まずまず | 良好(ノイズ点としてマーク) |
| 時間計算量 | O(nkt) | O(n²) ~ O(n³) | O(n log n) |
| スケーラビリティ | 大規模データに向く | 大規模データでは遅い | 中程度 |
| 応用 | 顧客セグメンテーション、画像圧縮 | 小規模データ、ツリー構造 | 異常検知、空間データ |
5. k の値の選び方
K-Means 最大の問題:k を事前に指定する必要があることです。k を間違えるとクラスタリング結果は無意味になります。最適な k を見つけるための 2 つの一般的な方法を紹介します。
(1) エルボー法(肘法)
異なる k に対応するイナーシャ曲線(クラスタ内二乗距離の和)をプロットし、「変曲点」――腕の肘のように、それ以降は k を増やしても効果が薄れる点――にある k 値を選びます。
▶ サンプル: エルボー図を描いて k を選ぶ(難易度:⭐)
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
import numpy as np
np.random.seed(42)
X = np.vstack([
np.random.normal(loc=[20, 80], scale=5, size=(50, 2)),
np.random.normal(loc=[80, 20], scale=5, size=(50, 2)),
np.random.normal(loc=[50, 50], scale=5, size=(50, 2)),
np.random.normal(loc=[80, 80], scale=5, size=(50, 2)),
])
inertias = []
K_range = range(1, 11)
for k in K_range:
km = KMeans(n_clusters=k, random_state=42, n_init=10)
km.fit(X)
inertias.append(km.inertia_)
plt.figure(figsize=(8, 5))
plt.plot(K_range, inertias, 'bo-', linewidth=2, markersize=8)
plt.xlabel('クラスタ数 (k)')
plt.ylabel('イナーシャ')
plt.title('最適 k のためのエルボー法')
plt.axvline(x=4, color='red', linestyle='--', label='k=4 で肘')
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('elbow_method.png', dpi=150)
plt.show()
出力: (例を実行して実際の出力を確認するか、上のコードコメントの期待出力の注釈を参照してください。)
(2) シルエット係数
シルエット係数は、各点と自身のクラスタの類似度と、最も近い他クラスタとの類似度を測ります。値の範囲は [-1, 1] で、大きいほど良いです。
▶ サンプル: シルエット係数で k を選ぶ(難易度:⭐⭐)
from sklearn.metrics import silhouette_score
from sklearn.cluster import KMeans
import numpy as np
np.random.seed(42)
X = np.vstack([
np.random.normal(loc=[20, 80], scale=5, size=(50, 2)),
np.random.normal(loc=[80, 20], scale=5, size=(50, 2)),
np.random.normal(loc=[50, 50], scale=5, size=(50, 2)),
np.random.normal(loc=[80, 80], scale=5, size=(50, 2)),
])
print("k | シルエット係数")
print("--|------------------")
for k in range(2, 8):
km = KMeans(n_clusters=k, random_state=42, n_init=10)
labels = km.fit_predict(X)
score = silhouette_score(X, labels)
print(f"{k} | {score:.4f}")
k | シルエット係数
--|------------------
2 | 0.5812
3 | 0.6234
4 | 0.6891
5 | 0.5543
6 | 0.4672
7 | 0.3891
(3) クラスタリング評価手法の比較
| 手法 | 測るもの | 値の範囲 | 長所 | 短所 |
|---|---|---|---|---|
| イナーシャ | クラスタ内密度 | ≥0、小さいほど良い | 計算が速い。K-Means 組み込み | k 増加とともに単調減少。単独では使えない |
| シルエット | コンパクトさ+分散 | [-1, 1]、大きいほど良い | 異なる k の比較が可能 | 計算が遅い、O(n²) |
| Calinski-Harabasz | クラスタ間/クラスタ内分散比 | ≥0、大きいほど良い | 計算が速い | 凸クラスタを好む |
| Davies-Bouldin | クラスタ内発散/クラスタ間距離比 | ≥0、小さいほど良い | 直感的 | 凸クラスタを好む |
6. PCA 次元削減
(1) なぜ次元削減が必要か?
- 次元の呪い: 特徴が多すぎると距離尺度の意味が失われ、モデル性能が低下する
- 可視化: 人間が知覚できるのは 2D と 3D だけ。高次元データは低次元に削減してからでなければ可視化できない
- ノイズ除去: 主情報は最初の数個の主成分に集中し、それ以降はノイズの可能性がある
- 高速化: 次元削減後は学習が速く、メモリ使用量も減る
(2) PCA:直感的な説明
PCA(主成分分析)の核心アイデアは、「データ内で分散が最大の方向を見つけ、データをその方向に射影する」ことです。分散が大きいほど情報が多く、射影後も元の情報をできるだけ保つことが目標です。
3D のデータ点が「平べったい」楕円体に並んでいると想像してください。PCA は最も長い軸(分散が最大の軸)を見つけ、データをその軸に射影することで、情報損失を最小にしつつ 3D を 1D に変換します。
▶ サンプル: PCA で 2 次元に削減し、結果を可視化する(難易度:⭐⭐)
from sklearn.decomposition import PCA
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt
import numpy as np
iris = load_iris()
X = iris.data
y = iris.target
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X)
print(f"元の形状: {X.shape}")
print(f"PCA 後: {X_pca.shape}")
print(f"説明分散比: {pca.explained_variance_ratio_}")
print(f"説明された分散の合計: {pca.explained_variance_ratio_.sum():.4f}")
plt.figure(figsize=(8, 6))
for target, color, label in zip([0, 1, 2], ['red', 'blue', 'green'], iris.target_names):
plt.scatter(X_pca[y == target, 0], X_pca[y == target, 1],
c=color, label=label, alpha=0.7, edgecolors='k', s=60)
plt.xlabel(f'PC1 ({pca.explained_variance_ratio_[0]:.1%} 分散)')
plt.ylabel(f'PC2 ({pca.explained_variance_ratio_[1]:.1%} 分散)')
plt.title('PCA: Iris データセットを 2D に削減')
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('pca_iris.png', dpi=150)
plt.show()
元の形状: (150, 4)
PCA 後: (150, 2)
説明分散比: [0.9246 0.0530]
説明された分散の合計: 0.9776
(3) 次元削減手法の比較
| 手法 | 種類 | 核心概念 | 大域構造を保つ | 局所構造を保つ | 解釈性 | 適用シナリオ |
|---|---|---|---|---|---|---|
| PCA | 線形 | 分散が最大の方向 | 良好 | 弱い | 高い(特徴の重みが解釈可能) | 高速な次元削減、ノイズ除去 |
| t-SNE | 非線形 | 近傍確率を保つ | 弱い | 良好 | 低い | 可視化(2D/3D) |
| UMAP | 非線形 | 位相構造を保つ | まずまず | 良好 | 低い | 可視化、大規模データ |
| オートエンコーダ | 非線形 | ニューラルネットワークによる圧縮 | 構造aware | 構造aware | 中程度 | 画像/テキストの次元削減 |
7. t-SNE 可視化入門
PCA は線形次元削減であり、大域構造の保持には優れるものの非線形関係を「平べったく」しがちです。t-SNE(t-Distributed Stochastic Neighbor Embedding)は可視化のために特化して設計されており、局所近傍構造の保持に優れます。似た点は 2D でも近くに留まります。
▶ サンプル: t-SNE で高次元データを可視化する(難易度:⭐⭐)
from sklearn.manifold import TSNE
from sklearn.datasets import load_digits
import matplotlib.pyplot as plt
import numpy as np
digits = load_digits()
X = digits.data
y = digits.target
print(f"元の形状: {X.shape}") # 64 次元の手書き数字
tsne = TSNE(n_components=2, random_state=42, perplexity=30)
X_tsne = tsne.fit_transform(X)
plt.figure(figsize=(10, 8))
scatter = plt.scatter(X_tsne[:, 0], X_tsne[:, 1], c=y, cmap='tab10',
alpha=0.7, edgecolors='k', s=30)
plt.colorbar(scatter, label='数字クラス')
plt.title('t-SNE: 64D 手書き数字 → 2D')
plt.xlabel('t-SNE 次元 1')
plt.ylabel('t-SNE 次元 2')
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('tsne_digits.png', dpi=150)
plt.show()
出力: (例を実行して実際の出力を確認するか、上のコードコメントの期待出力の注釈を参照してください。)
8. クラスタリングと次元削減の実践的応用
(1) 顧客セグメンテーション
e コマース、金融、ゲーム業界はクラスタリングでユーザーを異なるグループに分け、差別化戦略を立案します。
| 業界 | クラスタリング特徴 | クラスタリング結果 | ビジネスアクション |
|---|---|---|---|
| e コマース | 支出額、頻度、カテゴリ嗜好 | 高価値/低価値/離反リスク | 個別クーポン |
| 金融 | 収入、負債、信用履歴 | 低リスク/中リスク/高リスク | 多層金利 |
| ゲーム | プレイ時間、課金、ソーシャル活動 | 鯨( whales)/海豚(dolphins)/タダ乗り(freeloaders) | 差別化運営 |
(2) 画像圧縮
K-Means は画像のカラー量子化に使えます。数百万色を k 個のカテゴリにまとめることで、ファイルサイズを大幅に削減できます。
(3) 異常検知
いずれのクラスタにも属さない点は外れ値の可能性があります。DBSCAN がノイズとマークした点や、クラスタ重心から遠い点には注意が必要です。
(4) 特徴エンジニアリング
PCA で得た主成分を新しい特徴として教師あり学習モデルに入力でき、ノイズの除去、多重共線性の低減、学習の高速化が図れます。
9. クラスタリング結果と元ラベルの比較
ラベルはあるものの、教師なしクラスタリングがそれらのカテゴリを「自力で発見」できるか見たい場合があります。これはクラスタリングの質を試す優れた方法です。
▶ サンプル: クラスタリング結果と元ラベルを比較する(難易度:⭐⭐)
from sklearn.cluster import KMeans
from sklearn.datasets import load_iris
from sklearn.metrics import confusion_matrix, accuracy_score
from scipy.stats import mode
import numpy as np
iris = load_iris()
X = iris.data
y_true = iris.target
kmeans = KMeans(n_clusters=3, random_state=42, n_init=10)
y_pred = kmeans.fit_predict(X)
# クラスタラベルは任意なので、真ラベルに整列させる
aligned_pred = np.zeros_like(y_pred)
for i in range(3):
mask = y_pred == i
aligned_pred[mask] = mode(y_true[mask], keepdims=True).mode[0]
print("混同行列(クラスタ vs 真ラベル):")
print(confusion_matrix(y_true, aligned_pred))
print(f"\n整列後の精度: {accuracy_score(y_true, aligned_pred):.4f}")
混同行列(クラスタ vs 真ラベル):
[[50 0 0]
[ 0 48 2]
[ 0 14 36]]
整列後の精度: 0.8933
10. 教師なし学習の限界
| 限界 | 説明 |
|---|---|
| 結果の保証なし | ラベルがないため「正しい/間違い」を定量化できず、ビジネス判断に頼るしかない |
| k の選択が主観的 | 「エルボー法」の変曲点が明確でない場合があり、手法によって結論が分かれる |
| 初期化に敏感 | K-Means の初期重心が異なると結果が変わる可能性がある(n_init > 1 が必要) |
| 凸クラスタしか検出できない | K-Means はクラスタが球形と仮定。環状や三日月状のデータには DBSCAN が必要 |
| 次元削減で情報損失 | PCA は分散の低い次元を捨てるため、重要な微細な差が失われる可能性がある |
| 評価が難しい | 「正解」がないため、評価はドメイン知識と可視化に依存する |
11. 総合例:「Mall Customer」データセットを使った顧客セグメンテーション
▶ サンプル: データ駆動の顧客セグメンテーションの全体フロー(難易度:⭐⭐⭐)
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import silhouette_score
# ============================================
# ステップ 1: Mall Customer データセットの読み込みと探索
# ============================================
np.random.seed(42)
n = 200
data = {
'CustomerID': range(1, n + 1),
'Gender': np.random.choice(['Male', 'Female'], n),
'Age': np.random.randint(18, 70, n),
'Annual_Income_kUSD': np.random.randint(15, 137, n),
'Spending_Score': np.random.randint(1, 100, n),
}
df = pd.DataFrame(data)
# 現実的なクラスタ構造を注入
df.loc[:49, 'Annual_Income_kUSD'] = np.random.randint(15, 40, 50)
df.loc[:49, 'Spending_Score'] = np.random.randint(60, 100, 50)
df.loc[50:99, 'Annual_Income_kUSD'] = np.random.randint(70, 137, 50)
df.loc[50:99, 'Spending_Score'] = np.random.randint(60, 100, 50)
df.loc[100:149, 'Annual_Income_kUSD'] = np.random.randint(70, 137, 50)
df.loc[100:149, 'Spending_Score'] = np.random.randint(1, 40, 50)
df.loc[150:, 'Annual_Income_kUSD'] = np.random.randint(15, 40, 50)
df.loc[150:, 'Spending_Score'] = np.random.randint(1, 40, 50)
print("データセット形状:", df.shape)
print(df.head(10))
print("\n要約統計量:")
print(df[['Age', 'Annual_Income_kUSD', 'Spending_Score']].describe())
# ============================================
# ステップ 2: 特徴選択とスケーリング
# ============================================
features = ['Age', 'Annual_Income_kUSD', 'Spending_Score']
X = df[features].values
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# ============================================
# ステップ 3: エルボー法で最適 k を探す
# ============================================
inertias = []
silhouette_scores = []
K_range = range(2, 11)
for k in K_range:
km = KMeans(n_clusters=k, random_state=42, n_init=10)
labels = km.fit_predict(X_scaled)
inertias.append(km.inertia_)
silhouette_scores.append(silhouette_score(X_scaled, labels))
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
axes[0].plot(K_range, inertias, 'bo-', linewidth=2)
axes[0].set_xlabel('クラスタ数 (k)')
axes[0].set_ylabel('イナーシャ')
axes[0].set_title('エルボー法')
axes[0].axvline(x=4, color='red', linestyle='--', label='k=4 で肘')
axes[0].legend()
axes[0].grid(True, alpha=0.3)
axes[1].plot(K_range, silhouette_scores, 'go-', linewidth=2)
axes[1].set_xlabel('クラスタ数 (k)')
axes[1].set_ylabel('シルエット係数')
axes[1].set_title('シルエット法')
axes[1].axvline(x=4, color='red', linestyle='--', label='k=4 が最良')
axes[1].legend()
axes[1].grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('mall_elbow_silhouette.png', dpi=150)
plt.show()
# ============================================
# ステップ 4: k=4 で最終クラスタリング
# ============================================
kmeans = KMeans(n_clusters=4, random_state=42, n_init=10)
df['Cluster'] = kmeans.fit_predict(X_scaled)
# ============================================
# ステップ 5: 各クラスタを分析
# ============================================
cluster_summary = df.groupby('Cluster')[features].mean()
print("\nクラスタプロファイル(平均値):")
print(cluster_summary)
cluster_counts = df['Cluster'].value_counts().sort_index()
print("\nクラスタサイズ:")
print(cluster_counts)
# ============================================
# ステップ 6: PCA で 2D 可視化
# ============================================
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X_scaled)
plt.figure(figsize=(10, 7))
colors = ['red', 'blue', 'green', 'orange']
labels_text = [
'クラスタ 0: 若年高支出層',
'クラスタ 1: 富裕高支出層',
'クラスタ 2: 富裕低支出層',
'クラスタ 3: 節約低支出層',
]
for i in range(4):
mask = df['Cluster'] == i
plt.scatter(X_pca[mask, 0], X_pca[mask, 1],
c=colors[i], label=labels_text[i],
alpha=0.6, edgecolors='k', s=50)
centroids_pca = pca.transform(kmeans.cluster_centers_)
plt.scatter(centroids_pca[:, 0], centroids_pca[:, 1],
c='black', marker='X', s=200, label='重心')
plt.xlabel(f'PC1 ({pca.explained_variance_ratio_[0]:.1%})')
plt.ylabel(f'PC2 ({pca.explained_variance_ratio_[1]:.1%})')
plt.title('Mall 顧客セグメンテーション (K-Means + PCA)')
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('mall_clusters_pca.png', dpi=150)
plt.show()
# ============================================
# ステップ 7: ビジネス推奨
# ============================================
print("\n=== ビジネス推奨 ===")
for i in range(4):
row = cluster_summary.loc[i]
count = cluster_counts[i]
print(f"\nクラスタ {i} ({count} 人の顧客):")
print(f" 平均年齢: {row['Age']:.0f}, 収入: ${row['Annual_Income_kUSD']:.0f}k, 支出: {row['Spending_Score']:.0f}/100")
データセット形状: (200, 5)
CustomerID Gender Age Annual_Income_kUSD Spending_Score
0 1 Female 56 28 86
1 2 Male 25 32 79
2 3 Female 38 22 93
3 4 Female 36 37 74
4 5 Male 47 33 68
5 6 Female 32 27 82
6 7 Female 51 18 88
7 8 Male 19 38 95
8 9 Male 23 25 71
9 10 Female 27 39 91
要約統計量:
Age Annual_Income_kUSD Spending_Score
count 200.000000 200.000000 200.000000
mean 43.475000 60.720000 50.115000
std 15.441418 41.082376 31.494432
min 18.000000 15.000000 1.000000
max 69.000000 136.000000 99.000000
クラスタプロファイル(平均値):
Age Annual_Income_kUSD Spending_Score
Cluster
0 41.34 26.82 80.44
1 43.88 99.24 78.32
2 44.92 101.58 19.44
3 43.36 26.24 21.12
クラスタサイズ:
0 50
1 50
2 50
3 50
Name: Cluster, dtype: int64
=== ビジネス推奨 ===
クラスタ 0(50 人の顧客):
平均年齢: 41, 収入: $27k, 支出: 80/100
クラスタ 1(50 人の顧客):
平均年齢: 44, 収入: $99k, 支出: 78/100
クラスタ 2(50 人の顧客):
平均年齢: 45, 収入: $102k, 支出: 19/100
クラスタ 3(50 人の顧客):
平均年齢: 43, 収入: $26k, 支出: 21/100
❓ よくある質問
pca.explained_variance_ratio_ で各主成分の寄与を見て、いくつ保つか決めてください。📖 まとめ
- 教師なし学習はラベルを使わない。目的はデータの内在構造を発見すること――クラスタリングでグループを、次元削減でパターンを見つける。
- K-Means は最も実用的なクラスタリングアルゴリズム:初期化 → 割り当て → 更新 → 反復。単純で効率的。
- k の選択はエルボー法 + シルエット係数の交差検証。最終決定はビジネス要件による。
- PCA は分散が最大の方向にデータを射影し、高速な次元削減・ノイズ除去・可視化を可能にするが、非線形構造を捨てる。
- t-SNE は 2D/3D 可視化に適し局所近傍を保つが、モデル前処理には向かない。
- 教師なし学習の限界:評価が難しい、k 選択が主観的、初期化に敏感、凸クラスタしか検出できない。
📝 練習問題
-
基本問題(難易度:⭐):
sklearn.datasets.make_blobsで 3 クラスタのデータを生成し、K-Means クラスタリングを行い、散布図を描きなさい(クラスタごとに異なる色、クラスタ中心にラベルを付ける)。 -
応用問題(難易度:⭐⭐): 上のデータのエルボー図とシルエット係数図を描き、最適な k 値を決定しなさい。次にわざと k=2 と k=8 でそれぞれクラスタリングし、結果を比較して、k を間違えると結果が悪くなる理由を説明しなさい。
-
挑戦問題(難易度:⭐⭐⭐):
sklearn.datasets.load_digitsで手書き数字データセット(64 次元)を読み込みなさい。まず PCA で 2D 可視化に削減し、次に t-SNE で 2D 可視化に削減し、両手法の結果を比較しなさい。分析を書きなさい:PCA と t-SNE はそれぞれどんな構造的特徴を保つのか?このデータセットの可視化にはどちらが向いているか?