AI: 教師なし学習

最終更新:2026-08-26

もしデータにラベルが付いていなかったら?大規模なユーザー行動記録、遺伝子配列、センサーデータといった「正解」のないデータに直面したとき、教師なし学習は隠れたパターンを掘り起こす強力な道具になります。この章ではクラスタリングと次元削減という二つの主なアプローチを取り上げ、K-Means と PCA の原理と実践的応用を理解します。

1. 学べること



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) なぜ教師なし学習が必要か?



4. K-Means クラスタリング

(1) クラスタリングとは何か?

クラスタリングは、似たデータ点を同じグループに、異なるものを別のグループにまとめるプロセスです。鍵となる問いは:「似ている」とは何か? ――これは通常、距離尺度で測ります。最も一般的なのはユークリッド距離です。

(2) K-Means アルゴリズムの流れ

K-Means は最も古典的で実用的なクラスタリングアルゴリズムです。その核心アイデアは:「データを k 個のクラスタに分割し、各データ点とそのクラスタ重心までの距離の和を最小化する」ことです。

100%
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

アルゴリズムの手順:

  1. 初期化: k 個の点をランダムに選び初期重心とする
  2. 割り当て: 各データ点を、最も近い重心を持つクラスタに割り当てる
  3. 更新: 各クラスタの重心(クラスタ内全点の平均)を再計算する
  4. 反復: 重心が変わらなくなるか、最大反復回数に達するまで手順 2–3 を繰り返す

▶ サンプル: 顧客データの K-Means クラスタリング(難易度:⭐)

PYTHON
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]}")
💻 出力:

TEXT 📖 参照専用
クラスタ中心:
[[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 を選ぶ(難易度:⭐)

PYTHON
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()

出力: (例を実行して実際の出力を確認するか、上のコードコメントの期待出力の注釈を参照してください。)

💡 ヒント: エルボー法はイナーシャ低下の「変曲点」を探します。k=4 以降、イナーシャの低下が顕著に緩やかになり、4 つのクラスタが妥当であることを示しています。

(2) シルエット係数

シルエット係数は、各点と自身のクラスタの類似度と、最も近い他クラスタとの類似度を測ります。値の範囲は [-1, 1] で、大きいほど良いです。

▶ サンプル: シルエット係数で k を選ぶ(難易度:⭐⭐)

PYTHON
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}")
💻 出力:

TEXT 📖 参照専用
k | シルエット係数
--|------------------
2 | 0.5812
3 | 0.6234
4 | 0.6891
5 | 0.5543
6 | 0.4672
7 | 0.3891
💡 ヒント: シルエット係数は k=4 のとき最大で、エルボー法の結論と一致します。両手法の交差検証を行うとより信頼できる結果が得られます。

(3) クラスタリング評価手法の比較

手法 測るもの 値の範囲 長所 短所
イナーシャ クラスタ内密度 ≥0、小さいほど良い 計算が速い。K-Means 組み込み k 増加とともに単調減少。単独では使えない
シルエット コンパクトさ+分散 [-1, 1]、大きいほど良い 異なる k の比較が可能 計算が遅い、O(n²)
Calinski-Harabasz クラスタ間/クラスタ内分散比 ≥0、大きいほど良い 計算が速い 凸クラスタを好む
Davies-Bouldin クラスタ内発散/クラスタ間距離比 ≥0、小さいほど良い 直感的 凸クラスタを好む


6. PCA 次元削減

(1) なぜ次元削減が必要か?

(2) PCA:直感的な説明

PCA(主成分分析)の核心アイデアは、「データ内で分散が最大の方向を見つけ、データをその方向に射影する」ことです。分散が大きいほど情報が多く、射影後も元の情報をできるだけ保つことが目標です。

3D のデータ点が「平べったい」楕円体に並んでいると想像してください。PCA は最も長い軸(分散が最大の軸)を見つけ、データをその軸に射影することで、情報損失を最小にしつつ 3D を 1D に変換します。

▶ サンプル: PCA で 2 次元に削減し、結果を可視化する(難易度:⭐⭐)

PYTHON
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()
💻 出力:

TEXT 📖 参照専用
元の形状: (150, 4)
PCA 後:      (150, 2)
説明分散比: [0.9246 0.0530]
説明された分散の合計: 0.9776
💡 ヒント: 4 次元から 2 次元に削減しても、情報の 97.8% を保っています!最初の 2 つの主成分でほぼ「全部の話」を語ってくれます。

(3) 次元削減手法の比較

手法 種類 核心概念 大域構造を保つ 局所構造を保つ 解釈性 適用シナリオ
PCA 線形 分散が最大の方向 良好 弱い 高い(特徴の重みが解釈可能) 高速な次元削減、ノイズ除去
t-SNE 非線形 近傍確率を保つ 弱い 良好 低い 可視化(2D/3D)
UMAP 非線形 位相構造を保つ まずまず 良好 低い 可視化、大規模データ
オートエンコーダ 非線形 ニューラルネットワークによる圧縮 構造aware 構造aware 中程度 画像/テキストの次元削減


7. t-SNE 可視化入門

PCA は線形次元削減であり、大域構造の保持には優れるものの非線形関係を「平べったく」しがちです。t-SNE(t-Distributed Stochastic Neighbor Embedding)は可視化のために特化して設計されており、局所近傍構造の保持に優れます。似た点は 2D でも近くに留まります。

▶ サンプル: t-SNE で高次元データを可視化する(難易度:⭐⭐)

PYTHON
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()

出力: (例を実行して実際の出力を確認するか、上のコードコメントの期待出力の注釈を参照してください。)

⚠️ 注意: t-SNE は可視化にのみ適しており、下流モデルの前処理ステップとして使うべきではありません。再現性がなく(実行ごとに結果が変わる)、大域距離を保たず、計算も遅い(O(n²))からです。本番環境での次元削減には PCA か UMAP を使ってください。



8. クラスタリングと次元削減の実践的応用

(1) 顧客セグメンテーション

e コマース、金融、ゲーム業界はクラスタリングでユーザーを異なるグループに分け、差別化戦略を立案します。

業界 クラスタリング特徴 クラスタリング結果 ビジネスアクション
e コマース 支出額、頻度、カテゴリ嗜好 高価値/低価値/離反リスク 個別クーポン
金融 収入、負債、信用履歴 低リスク/中リスク/高リスク 多層金利
ゲーム プレイ時間、課金、ソーシャル活動 鯨( whales)/海豚(dolphins)/タダ乗り(freeloaders) 差別化運営

(2) 画像圧縮

K-Means は画像のカラー量子化に使えます。数百万色を k 個のカテゴリにまとめることで、ファイルサイズを大幅に削減できます。

(3) 異常検知

いずれのクラスタにも属さない点は外れ値の可能性があります。DBSCAN がノイズとマークした点や、クラスタ重心から遠い点には注意が必要です。

(4) 特徴エンジニアリング

PCA で得た主成分を新しい特徴として教師あり学習モデルに入力でき、ノイズの除去、多重共線性の低減、学習の高速化が図れます。



9. クラスタリング結果と元ラベルの比較

ラベルはあるものの、教師なしクラスタリングがそれらのカテゴリを「自力で発見」できるか見たい場合があります。これはクラスタリングの質を試す優れた方法です。

▶ サンプル: クラスタリング結果と元ラベルを比較する(難易度:⭐⭐)

PYTHON
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}")
💻 出力:

TEXT 📖 参照専用
混同行列(クラスタ vs 真ラベル):
[[50  0  0]
 [ 0 48  2]
 [ 0 14 36]]

整列後の精度: 0.8933
💡 ヒント: 教師なしクラスタリングが、ラベルを知らずに 89.3% の分類精度を自動達成しました!これは 3 種の Iris が特徴空間に確かに明確なクラスタ構造を持っていることを示しています。



10. 教師なし学習の限界

限界 説明
結果の保証なし ラベルがないため「正しい/間違い」を定量化できず、ビジネス判断に頼るしかない
k の選択が主観的 「エルボー法」の変曲点が明確でない場合があり、手法によって結論が分かれる
初期化に敏感 K-Means の初期重心が異なると結果が変わる可能性がある(n_init > 1 が必要)
凸クラスタしか検出できない K-Means はクラスタが球形と仮定。環状や三日月状のデータには DBSCAN が必要
次元削減で情報損失 PCA は分散の低い次元を捨てるため、重要な微細な差が失われる可能性がある
評価が難しい 「正解」がないため、評価はドメイン知識と可視化に依存する


11. 総合例:「Mall Customer」データセットを使った顧客セグメンテーション

▶ サンプル: データ駆動の顧客セグメンテーションの全体フロー(難易度:⭐⭐⭐)

PYTHON
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")
💻 出力:

TEXT 📖 参照専用
データセット形状: (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

❓ よくある質問

Q クラスタリング結果の質をどう評価するか?
A ラベルがないときは内部指標を使います。シルエット係数([-1,1]、大きいほど良い)、Calinski-Harabasz 指数(大きいほど良い)、Davies-Bouldin 指数(小さいほど良い)です。ラベルがあるときは結果を真ラベルと比較します(整列後に精度を計算)。最も信頼できるのはビジネス検証――クラスタリング結果がビジネスの直感と一致し、アクション可能かを確認することです。
Q K-Means の k 値はどう選ぶか?
A まず「エルボー法」でイナーシャ曲線の変曲点を特定し、次にシルエット係数で結果を交差検証します。両手法が一致すればその値を安心して使えます。一致しない場合はビジネス要件を優先してください。4 クラスタの方が 8 クラスタより差別化戦略を立てやすいからです。k は数学の問題ではなく、ビジネスの問題です。
Q PCA の次元削減で情報損失は起きるか?
A はい、しかし「失われる」情報が必ずしも悪いとは限りません。PCA は分散の高い順に次元を並べ、分散の低い次元を捨てることはノイズを捨てることと等価です。鍵はどれだけの分散を保つかです。通常、85% 以上保てれば十分です。pca.explained_variance_ratio_ で各主成分の寄与を見て、いくつ保つか決めてください。
Q 教師なし学習の実践的応用は?
A 5 つの典型シナリオ:① 顧客セグメンテーション(パーソナライズドマーケティング)② 異常検知(不正検知)③ 次元削減(特徴エンジニアリング)④ 画像圧縮(カラー量子化)⑤ 推薦システムのコールドスタート(行動データがないとき先にクラスタリング)。核心は「探索的分析」――まずデータの様子を見てから、どう扱うか決めることです。
Q クラスタリングと分類、どちらが難しいか?
A クラスタリングの方が難しいです。「正解」がないからです。分類にはラベルがあり、精度を測って性能が分かります。クラスタリングにはラベルがなく、評価は内部指標とビジネス判断に依存します。さらに K-Means は初期化に敏感、k の選択は主観的、凸クラスタにしか向かないという点もあります。分類は「正解のある試験」、クラスタリングは「正解のない記述式問題」のようなものです。

📖 まとめ


📝 練習問題

  1. 基本問題(難易度:⭐): sklearn.datasets.make_blobs で 3 クラスタのデータを生成し、K-Means クラスタリングを行い、散布図を描きなさい(クラスタごとに異なる色、クラスタ中心にラベルを付ける)。

  2. 応用問題(難易度:⭐⭐): 上のデータのエルボー図とシルエット係数図を描き、最適な k 値を決定しなさい。次にわざと k=2 と k=8 でそれぞれクラスタリングし、結果を比較して、k を間違えると結果が悪くなる理由を説明しなさい。

  3. 挑戦問題(難易度:⭐⭐⭐): sklearn.datasets.load_digits で手書き数字データセット(64 次元)を読み込みなさい。まず PCA で 2D 可視化に削減し、次に t-SNE で 2D 可視化に削減し、両手法の結果を比較しなさい。分析を書きなさい:PCA と t-SNE はそれぞれどんな構造的特徴を保つのか?このデータセットの可視化にはどちらが向いているか?

Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%