論文一覧に戻る 📚 用語集トップ 🗺 概念マップ
📚 用語解説(ジャストインタイム型データサイエンス教育)
クラスタリング(教師なし学習)
Clustering
似たものを集める — ラベルなしデータから構造を見つける
教師なし学習距離ベース評価指標必要結果は仮説

📍 あなたが今見ているもの

本ページでは、 クラスタリングを統合的に解説します。 k-means階層クラスタリングDBSCANGMM (混合ガウス)クラスタ評価を一気通貫で扱います。

クラスタリングは「ラベルなしデータをグループに分ける」教師なし学習の代表手法。 顧客セグメンテーション・異常検知・データ探索の基本ツールです。

🔖 🔖 キーワード索引(チップから該当箇所へジャンプ)

論文記事から各用語のリンクをクリックすると、 該当箇所が開きます:

クラスタリングとは 距離 k-means クラスタ数K選び エルボー法 シルエット係数 階層クラスタリング デンドログラム リンケージ DBSCAN GMM EMアルゴリズム ARI / NMI 標準化必須 次元の呪い

💡 30秒で分かる結論

📚 章構成

内容
1. クラスタリングとは教師なし学習の代表
2. 距離と前処理標準化が必須
3. k-means最も基本的な手法
4. K の選び方エルボー・シルエット
5. 階層クラスタリングデンドログラム
6. DBSCAN密度ベース
7. GMM確率モデル
8. クラスタ評価内部・外部指標

🎯 1. クラスタリングとは

正解ラベルがないデータを、 何らかの「類似性」に基づきグループに分ける手法群。 教師なし学習の中核。

主な用途

本ページの方針

クラスタリングは「解釈」が結果のすべて。 同じデータでも手法・距離・K で結果が変わる。 単一手法に頼らず、 複数手法・複数 K で結果を見比べる方針で進めます。

📏 2. 距離と前処理

主な距離

2.1 標準化を必ず行う

距離はスケールに敏感。 SSDSE-B では「県民所得(数百万)」と「世帯人員(数)」が同じ重みになるよう、 必ず標準化。

🎯 解説: SSDSE-B-2026 の複数指標を使い、 都道府県をクラスタリング(教師なし学習)する。 k-means、 階層クラスタ、 GMM などで「似た都道府県」をグループ化し、 地域類型を発見する。
1
2
from sklearn.preprocessing import StandardScaler
X_scaled = StandardScaler().fit_transform(X)
📥 入力例: data/raw/SSDSE-B-2026.csv 特徴量: A1101(総人口)、 D210101(県民所得)、 高齢化率、 出生率 前処理: StandardScaler で平均 0、 分散 1 に標準化
📤 実行例: KMeans(n_clusters=4).fit(X) 各クラスタの代表都道府県: C0: 東京・大阪・愛知(都市集中型) C1: 神奈川・千葉・埼玉(首都圏ベッドタウン) C2: 北海道・新潟・福島(広域・中位) C3: 秋田・高知・島根(高齢化・過疎) シルエット係数 = 0.42(中程度の分離)
💬 読み方: k-means は球状クラスタに強いが、 非球状や密度異質には弱い。 シルエット係数 0.42 は「クラスタが妥当に分離されている」程度。 K を増やすと係数は上がるが解釈性が下がる ── エルボー法・BIC で適切な K を選ぶのが基本。 都道府県の 4 類型化は社会保障・地方創生政策の議論に使える。

2.2 次元の呪い

高次元では「すべての点が等距離」に近づき、 距離ベースのクラスタリングが破綻する。 100 次元以上では PCA や UMAP で次元削減してから。

🎯 3. k-means クラスタリング

3.1 アルゴリズム

  1. K 個の重心 $\boldsymbol{\mu}_1, \dots, \boldsymbol{\mu}_K$ をランダム初期化
  2. 各点を最近傍の重心に割り当てる
  3. 各クラスタの重心を平均で更新
  4. 変化がなくなるまで 2-3 を反復

3.2 目的関数

$$J = \sum_{k=1}^{K} \sum_{\mathbf{x} \in C_k} \|\mathbf{x} - \boldsymbol{\mu}_k\|^2 \quad (\text{= WCSS, 群内平方和})$$

$J$ を反復で減少させる。 局所最適に陥るため複数 seed で試す(n_init='auto' が既定)。

3.3 K-means++

2007 年 Arthur & Vassilvitskii。 初期重心を「離れた点」を優先して選ぶ改良。 sklearn の既定(init='k-means++')。

🎯 解説: SSDSE-B-2026 の複数指標を使い、 都道府県をクラスタリング(教師なし学習)する。 k-means、 階層クラスタ、 GMM などで「似た都道府県」をグループ化し、 地域類型を発見する。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import pandas as pd
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='utf-8', skiprows=1)
X = df[['一人当たり県民所得', '世帯人員', '高齢化率', '人口密度', '就業率']]
X_scaled = StandardScaler().fit_transform(X)

kmeans = KMeans(n_clusters=4, n_init=10, random_state=42)
df['cluster'] = kmeans.fit_predict(X_scaled)
print(df.groupby('cluster')['都道府県'].apply(list))
📥 入力例: data/raw/SSDSE-B-2026.csv 特徴量: A1101(総人口)、 D210101(県民所得)、 高齢化率、 出生率 前処理: StandardScaler で平均 0、 分散 1 に標準化
📤 実行例: KMeans(n_clusters=4).fit(X) 各クラスタの代表都道府県: C0: 東京・大阪・愛知(都市集中型) C1: 神奈川・千葉・埼玉(首都圏ベッドタウン) C2: 北海道・新潟・福島(広域・中位) C3: 秋田・高知・島根(高齢化・過疎) シルエット係数 = 0.42(中程度の分離)
💬 読み方: k-means は球状クラスタに強いが、 非球状や密度異質には弱い。 シルエット係数 0.42 は「クラスタが妥当に分離されている」程度。 K を増やすと係数は上がるが解釈性が下がる ── エルボー法・BIC で適切な K を選ぶのが基本。 都道府県の 4 類型化は社会保障・地方創生政策の議論に使える。

🔢 4. K の選び方

4.1 エルボー法

K vs WCSS(慣性)をプロットし、 「肘」となる K を選ぶ。 主観的。

🎯 解説: SSDSE-B-2026 の複数指標を使い、 都道府県をクラスタリング(教師なし学習)する。 k-means、 階層クラスタ、 GMM などで「似た都道府県」をグループ化し、 地域類型を発見する。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import matplotlib.pyplot as plt
inertias = []
for k in range(2, 11):
    km = KMeans(n_clusters=k, n_init=10, random_state=42).fit(X_scaled)
    inertias.append(km.inertia_)
plt.plot(range(2, 11), inertias, 'o-')
plt.xlabel('K')
plt.ylabel('WCSS (慣性)')
plt.title('エルボー法')
plt.show()
📥 入力例: data/raw/SSDSE-B-2026.csv 特徴量: A1101(総人口)、 D210101(県民所得)、 高齢化率、 出生率 前処理: StandardScaler で平均 0、 分散 1 に標準化
📤 実行例: KMeans(n_clusters=4).fit(X) 各クラスタの代表都道府県: C0: 東京・大阪・愛知(都市集中型) C1: 神奈川・千葉・埼玉(首都圏ベッドタウン) C2: 北海道・新潟・福島(広域・中位) C3: 秋田・高知・島根(高齢化・過疎) シルエット係数 = 0.42(中程度の分離)
💬 読み方: k-means は球状クラスタに強いが、 非球状や密度異質には弱い。 シルエット係数 0.42 は「クラスタが妥当に分離されている」程度。 K を増やすと係数は上がるが解釈性が下がる ── エルボー法・BIC で適切な K を選ぶのが基本。 都道府県の 4 類型化は社会保障・地方創生政策の議論に使える。

4.2 シルエット係数

$$s_i = \frac{b_i - a_i}{\max(a_i, b_i)} \in [-1, 1]$$

$a_i$=同クラスタ内の平均距離、 $b_i$=最近隣クラスタ平均距離。 全データの平均が大きい K が良い。

🎯 解説: SSDSE-B-2026 の複数指標を使い、 都道府県をクラスタリング(教師なし学習)する。 k-means、 階層クラスタ、 GMM などで「似た都道府県」をグループ化し、 地域類型を発見する。
1
2
3
4
5
from sklearn.metrics import silhouette_score
for k in range(2, 11):
    km = KMeans(n_clusters=k, n_init=10, random_state=42).fit(X_scaled)
    s = silhouette_score(X_scaled, km.labels_)
    print(f'K={k}: silhouette = {s:.3f}')
📥 入力例: data/raw/SSDSE-B-2026.csv 特徴量: A1101(総人口)、 D210101(県民所得)、 高齢化率、 出生率 前処理: StandardScaler で平均 0、 分散 1 に標準化
📤 実行例: KMeans(n_clusters=4).fit(X) 各クラスタの代表都道府県: C0: 東京・大阪・愛知(都市集中型) C1: 神奈川・千葉・埼玉(首都圏ベッドタウン) C2: 北海道・新潟・福島(広域・中位) C3: 秋田・高知・島根(高齢化・過疎) シルエット係数 = 0.42(中程度の分離)
💬 読み方: k-means は球状クラスタに強いが、 非球状や密度異質には弱い。 シルエット係数 0.42 は「クラスタが妥当に分離されている」程度。 K を増やすと係数は上がるが解釈性が下がる ── エルボー法・BIC で適切な K を選ぶのが基本。 都道府県の 4 類型化は社会保障・地方創生政策の議論に使える。

4.3 BIC / AIC(GMM)

GMM では BIC・AIC で K を選べる。 後述。

🌲 5. 階層クラスタリング

「凝集型」(bottom-up) と「分割型」(top-down) があるが、 実務は凝集型。

5.1 凝集型アルゴリズム

  1. 各点を 1 クラスタとして開始
  2. 最も近い 2 クラスタを統合
  3. 1 クラスタになるまで反復

5.2 リンケージ(クラスタ間距離)

5.3 デンドログラム

クラスタの統合過程を樹形図に。 横線の高さで「どこで切るか」= K を決められる。

🎯 解説: SSDSE-B-2026 の複数指標を使い、 都道府県をクラスタリング(教師なし学習)する。 k-means、 階層クラスタ、 GMM などで「似た都道府県」をグループ化し、 地域類型を発見する。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
from scipy.cluster.hierarchy import dendrogram, linkage, fcluster
import matplotlib.pyplot as plt

Z = linkage(X_scaled, method='ward')
plt.figure(figsize=(14, 6))
dendrogram(Z, labels=df['都道府県'].values, leaf_rotation=90)
plt.title('Ward法デンドログラム')
plt.tight_layout()
plt.show()

# 4 クラスタに切る
df['cluster_h'] = fcluster(Z, t=4, criterion='maxclust')
📥 入力例: data/raw/SSDSE-B-2026.csv 特徴量: A1101(総人口)、 D210101(県民所得)、 高齢化率、 出生率 前処理: StandardScaler で平均 0、 分散 1 に標準化
📤 実行例: KMeans(n_clusters=4).fit(X) 各クラスタの代表都道府県: C0: 東京・大阪・愛知(都市集中型) C1: 神奈川・千葉・埼玉(首都圏ベッドタウン) C2: 北海道・新潟・福島(広域・中位) C3: 秋田・高知・島根(高齢化・過疎) シルエット係数 = 0.42(中程度の分離)
💬 読み方: k-means は球状クラスタに強いが、 非球状や密度異質には弱い。 シルエット係数 0.42 は「クラスタが妥当に分離されている」程度。 K を増やすと係数は上がるが解釈性が下がる ── エルボー法・BIC で適切な K を選ぶのが基本。 都道府県の 4 類型化は社会保障・地方創生政策の議論に使える。

🌀 6. DBSCAN(密度ベース)

密度の高い領域をクラスタ、 低密度の点を「ノイズ」として扱う。 K の事前指定不要。 任意形状を捉える。

6.1 パラメータ

6.2 点の分類

🎯 解説: SSDSE-B-2026 の複数指標を使い、 都道府県をクラスタリング(教師なし学習)する。 k-means、 階層クラスタ、 GMM などで「似た都道府県」をグループ化し、 地域類型を発見する。
1
2
3
4
5
from sklearn.cluster import DBSCAN
db = DBSCAN(eps=0.5, min_samples=3).fit(X_scaled)
df['cluster_db'] = db.labels_  # -1 はノイズ
print('クラスタ数:', len(set(db.labels_)) - (1 if -1 in db.labels_ else 0))
print('ノイズ件数:', (db.labels_ == -1).sum())
📥 入力例: data/raw/SSDSE-B-2026.csv 特徴量: A1101(総人口)、 D210101(県民所得)、 高齢化率、 出生率 前処理: StandardScaler で平均 0、 分散 1 に標準化
📤 実行例: KMeans(n_clusters=4).fit(X) 各クラスタの代表都道府県: C0: 東京・大阪・愛知(都市集中型) C1: 神奈川・千葉・埼玉(首都圏ベッドタウン) C2: 北海道・新潟・福島(広域・中位) C3: 秋田・高知・島根(高齢化・過疎) シルエット係数 = 0.42(中程度の分離)
💬 読み方: k-means は球状クラスタに強いが、 非球状や密度異質には弱い。 シルエット係数 0.42 は「クラスタが妥当に分離されている」程度。 K を増やすと係数は上がるが解釈性が下がる ── エルボー法・BIC で適切な K を選ぶのが基本。 都道府県の 4 類型化は社会保障・地方創生政策の議論に使える。

6.3 eps の選び方

k-distance plot:各点の k 番目に近い点までの距離を昇順プロット。 急に立ち上がる「肘」を eps に。

📊 7. GMM(混合ガウスモデル)

各クラスタが多変量正規分布に従うと仮定。 ソフトクラスタリング(所属確率)。

$$p(\mathbf{x}) = \sum_{k=1}^{K} \pi_k \mathcal{N}(\mathbf{x} | \boldsymbol{\mu}_k, \boldsymbol{\Sigma}_k)$$

記号読み:$\pi_k$ は「パイ・サブ・ケー」混合比、 $\boldsymbol{\Sigma}_k$ はクラスタ $k$ の共分散行列。

7.1 EM アルゴリズム

  1. E ステップ:各点の所属確率(responsibility)を計算
  2. M ステップ:所属確率に基づき $\pi_k, \boldsymbol{\mu}_k, \boldsymbol{\Sigma}_k$ を更新
  3. 対数尤度の変化が小さくなるまで反復
🎯 解説: SSDSE-B-2026 の複数指標を使い、 都道府県をクラスタリング(教師なし学習)する。 k-means、 階層クラスタ、 GMM などで「似た都道府県」をグループ化し、 地域類型を発見する。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
from sklearn.mixture import GaussianMixture

# BIC で K を選ぶ
bics = []
for k in range(2, 11):
    gmm = GaussianMixture(n_components=k, covariance_type='full', random_state=42)
    gmm.fit(X_scaled)
    bics.append(gmm.bic(X_scaled))
import matplotlib.pyplot as plt
plt.plot(range(2, 11), bics, 'o-')
plt.xlabel('K'); plt.ylabel('BIC')
plt.show()

# 最良 K で学習
gmm = GaussianMixture(n_components=4, random_state=42).fit(X_scaled)
df['cluster_gmm'] = gmm.predict(X_scaled)
df[['proba_0','proba_1','proba_2','proba_3']] = gmm.predict_proba(X_scaled)
📥 入力例: data/raw/SSDSE-B-2026.csv 特徴量: A1101(総人口)、 D210101(県民所得)、 高齢化率、 出生率 前処理: StandardScaler で平均 0、 分散 1 に標準化
📤 実行例: KMeans(n_clusters=4).fit(X) 各クラスタの代表都道府県: C0: 東京・大阪・愛知(都市集中型) C1: 神奈川・千葉・埼玉(首都圏ベッドタウン) C2: 北海道・新潟・福島(広域・中位) C3: 秋田・高知・島根(高齢化・過疎) シルエット係数 = 0.42(中程度の分離)
💬 読み方: k-means は球状クラスタに強いが、 非球状や密度異質には弱い。 シルエット係数 0.42 は「クラスタが妥当に分離されている」程度。 K を増やすと係数は上がるが解釈性が下がる ── エルボー法・BIC で適切な K を選ぶのが基本。 都道府県の 4 類型化は社会保障・地方創生政策の議論に使える。

7.2 共分散の型

📏 8. クラスタリング評価

8.1 内部評価(正解ラベルなし)

8.2 外部評価(正解ラベルあり)

🎯 解説: SSDSE-B-2026 の複数指標を使い、 都道府県をクラスタリング(教師なし学習)する。 k-means、 階層クラスタ、 GMM などで「似た都道府県」をグループ化し、 地域類型を発見する。
1
2
3
4
5
6
from sklearn.metrics import silhouette_score, davies_bouldin_score, calinski_harabasz_score
for name, labels in [('kmeans', kmeans.labels_), ('gmm', gmm.predict(X_scaled))]:
    sil = silhouette_score(X_scaled, labels)
    db = davies_bouldin_score(X_scaled, labels)
    ch = calinski_harabasz_score(X_scaled, labels)
    print(f'{name}: sil={sil:.3f}, DB={db:.3f}, CH={ch:.1f}')
📥 入力例: data/raw/SSDSE-B-2026.csv 特徴量: A1101(総人口)、 D210101(県民所得)、 高齢化率、 出生率 前処理: StandardScaler で平均 0、 分散 1 に標準化
📤 実行例: KMeans(n_clusters=4).fit(X) 各クラスタの代表都道府県: C0: 東京・大阪・愛知(都市集中型) C1: 神奈川・千葉・埼玉(首都圏ベッドタウン) C2: 北海道・新潟・福島(広域・中位) C3: 秋田・高知・島根(高齢化・過疎) シルエット係数 = 0.42(中程度の分離)
💬 読み方: k-means は球状クラスタに強いが、 非球状や密度異質には弱い。 シルエット係数 0.42 は「クラスタが妥当に分離されている」程度。 K を増やすと係数は上がるが解釈性が下がる ── エルボー法・BIC で適切な K を選ぶのが基本。 都道府県の 4 類型化は社会保障・地方創生政策の議論に使える。

📊 9. 手法比較

手法 K指定 形状 ノイズ スケール 速度
k-means必要球形弱い
階層後で決定柔軟弱い
DBSCAN不要任意強い
GMM必要 (BIC)楕円弱い
HDBSCAN不要任意強い

⚠️ 10. よくある落とし穴

落とし穴 対処
標準化せずに距離計算必ず StandardScaler。 大きいスケールの変数だけが効いてしまう。
K=2 から始めて 1 つの解で報告複数 K・複数手法を比較。 シルエットや BIC で選ぶ。
k-means で乱数固定なし必ず random_state を指定。 n_init を 10 以上に。
非球形データに k-meansDBSCAN / GMM / スペクトラルに切り替え。
クラスタ番号に意味を与える番号は順序なし。 各クラスタの特徴量プロファイルで命名する。
高次元データに直接適用PCA / UMAP で次元削減してから。 次元の呪い。
DBSCAN の eps を恣意的にk-distance plot で根拠ある選択。

🏋️ 11. 練習問題(SSDSE-B-2026)

Q1. 47 都道府県を k-means で 4 クラスタに分け、 各クラスタを言語的に命名しなさい。
🎯 解説: SSDSE-B-2026 の複数指標を使い、 都道府県をクラスタリング(教師なし学習)する。 k-means、 階層クラスタ、 GMM などで「似た都道府県」をグループ化し、 地域類型を発見する。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import pandas as pd
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='utf-8', skiprows=1)
X = df[['一人当たり県民所得', '世帯人員', '高齢化率', '人口密度', '就業率']]
X_scaled = StandardScaler().fit_transform(X)
km = KMeans(n_clusters=4, n_init=10, random_state=42)
df['cluster'] = km.fit_predict(X_scaled)
print(df.groupby('cluster')[X.columns].mean().round(1))
print(df.groupby('cluster')['都道府県'].apply(lambda s: ', '.join(s)))
📥 入力例: data/raw/SSDSE-B-2026.csv 特徴量: A1101(総人口)、 D210101(県民所得)、 高齢化率、 出生率 前処理: StandardScaler で平均 0、 分散 1 に標準化
📤 実行例: KMeans(n_clusters=4).fit(X) 各クラスタの代表都道府県: C0: 東京・大阪・愛知(都市集中型) C1: 神奈川・千葉・埼玉(首都圏ベッドタウン) C2: 北海道・新潟・福島(広域・中位) C3: 秋田・高知・島根(高齢化・過疎) シルエット係数 = 0.42(中程度の分離)
💬 読み方: k-means は球状クラスタに強いが、 非球状や密度異質には弱い。 シルエット係数 0.42 は「クラスタが妥当に分離されている」程度。 K を増やすと係数は上がるが解釈性が下がる ── エルボー法・BIC で適切な K を選ぶのが基本。 都道府県の 4 類型化は社会保障・地方創生政策の議論に使える。
Q2. K = 2〜10 を試し、 シルエット係数とエルボーの両方で最適 K を決めなさい。
🎯 解説: SSDSE-B-2026 の複数指標を使い、 都道府県をクラスタリング(教師なし学習)する。 k-means、 階層クラスタ、 GMM などで「似た都道府県」をグループ化し、 地域類型を発見する。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
from sklearn.metrics import silhouette_score
import matplotlib.pyplot as plt
sils, inertias = [], []
for k in range(2, 11):
    km = KMeans(n_clusters=k, n_init=10, random_state=42).fit(X_scaled)
    sils.append(silhouette_score(X_scaled, km.labels_))
    inertias.append(km.inertia_)
fig, axes = plt.subplots(1, 2, figsize=(12, 4))
axes[0].plot(range(2,11), inertias, 'o-'); axes[0].set_title('Elbow')
axes[1].plot(range(2,11), sils, 'o-'); axes[1].set_title('Silhouette')
plt.show()
📥 入力例: data/raw/SSDSE-B-2026.csv 特徴量: A1101(総人口)、 D210101(県民所得)、 高齢化率、 出生率 前処理: StandardScaler で平均 0、 分散 1 に標準化
📤 実行例: KMeans(n_clusters=4).fit(X) 各クラスタの代表都道府県: C0: 東京・大阪・愛知(都市集中型) C1: 神奈川・千葉・埼玉(首都圏ベッドタウン) C2: 北海道・新潟・福島(広域・中位) C3: 秋田・高知・島根(高齢化・過疎) シルエット係数 = 0.42(中程度の分離)
💬 読み方: k-means は球状クラスタに強いが、 非球状や密度異質には弱い。 シルエット係数 0.42 は「クラスタが妥当に分離されている」程度。 K を増やすと係数は上がるが解釈性が下がる ── エルボー法・BIC で適切な K を選ぶのが基本。 都道府県の 4 類型化は社会保障・地方創生政策の議論に使える。
Q3. Ward 法でデンドログラムを描き、 k-means と階層クラスタリングで結果が一致するかを ARI で評価しなさい。
🎯 解説: SSDSE-B-2026 の複数指標を使い、 都道府県をクラスタリング(教師なし学習)する。 k-means、 階層クラスタ、 GMM などで「似た都道府県」をグループ化し、 地域類型を発見する。
1
2
3
4
5
from scipy.cluster.hierarchy import linkage, fcluster
from sklearn.metrics import adjusted_rand_score
Z = linkage(X_scaled, method='ward')
labels_h = fcluster(Z, t=4, criterion='maxclust')
print('ARI(km, hier) =', adjusted_rand_score(km.labels_, labels_h))
📥 入力例: data/raw/SSDSE-B-2026.csv 特徴量: A1101(総人口)、 D210101(県民所得)、 高齢化率、 出生率 前処理: StandardScaler で平均 0、 分散 1 に標準化
📤 実行例: KMeans(n_clusters=4).fit(X) 各クラスタの代表都道府県: C0: 東京・大阪・愛知(都市集中型) C1: 神奈川・千葉・埼玉(首都圏ベッドタウン) C2: 北海道・新潟・福島(広域・中位) C3: 秋田・高知・島根(高齢化・過疎) シルエット係数 = 0.42(中程度の分離)
💬 読み方: k-means は球状クラスタに強いが、 非球状や密度異質には弱い。 シルエット係数 0.42 は「クラスタが妥当に分離されている」程度。 K を増やすと係数は上がるが解釈性が下がる ── エルボー法・BIC で適切な K を選ぶのが基本。 都道府県の 4 類型化は社会保障・地方創生政策の議論に使える。

📝 12. 報告フォーマット

❌ NG例

「k-means で 4 グループに分かれました。」

✅ OK例

「47 都道府県を 5 次元(所得・世帯人員・高齢化率・人口密度・就業率、 標準化済み)で k-means クラスタリング。 K=2〜10 のシルエット係数と Ward 法 BIC から K=4 を選択。 シルエット = 0.42(中程度)。 各クラスタを特徴量プロファイルから「大都市圏」「成長地方」「高齢過疎」「観光・農村」と命名。 Ward 法との ARI = 0.71(高い一致)。 再現性のため random_state=42, n_init=10 を明記。」

🐍 13. ライブラリ早見表

手法 クラス・関数
k-meanssklearn.cluster.KMeans / MiniBatchKMeans
階層scipy.cluster.hierarchy.linkage / dendrogram / fcluster または sklearn.cluster.AgglomerativeClustering
DBSCANsklearn.cluster.DBSCAN / HDBSCAN
GMMsklearn.mixture.GaussianMixture / BayesianGaussianMixture
スペクトラルsklearn.cluster.SpectralClustering
アフィニティ伝播sklearn.cluster.AffinityPropagation
Mean Shiftsklearn.cluster.MeanShift
シルエットsklearn.metrics.silhouette_score
ARI / NMIsklearn.metrics.adjusted_rand_score / normalized_mutual_info_score

📜 14. クラスタリングの歴史

💼 15. 実務応用

🔖 キーワード索引(拡張)

クラスタリング手法・距離・評価指標:

k-means / k-means++ 階層クラスタリング DBSCAN / HDBSCAN Gaussian Mixture Ward 法 エルボー法 シルエット係数 Calinski-Harabasz 標準化忘れ k の決め打ち 初期値依存 sklearn.cluster scipy.cluster.hierarchy hdbscan

🧮 SSDSE-B 実値計算 — 47都道府県を 4 クラスターに分ける

SSDSE-B-2026 の経済・人口・社会指標(標準化後 8 変数)を k-means、 Ward 階層、 GMM で分け、 シルエットで比較する。

🎯 解説: SSDSE-B-2026 の複数指標を使い、 都道府県をクラスタリング(教師なし学習)する。 k-means、 階層クラスタ、 GMM などで「似た都道府県」をグループ化し、 地域類型を発見する。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans, AgglomerativeClustering, DBSCAN
from sklearn.mixture import GaussianMixture
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import (silhouette_score, calinski_harabasz_score,
                              davies_bouldin_score)

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', header=1)
df.columns = [c.strip() for c in df.columns]

feats = ['総人口', '65歳以上人口', '製造品出荷額等',
         '小売業年間商品販売額', '現金給与総額',
         '一般病院数', '完全失業率', '出生率']
X = StandardScaler().fit_transform(df[feats].astype(float))

methods = {
    'KMeans(k=4)'        : KMeans(n_clusters=4, n_init=20, random_state=0),
    'KMeans(k=5)'        : KMeans(n_clusters=5, n_init=20, random_state=0),
    'Agglo Ward(k=4)'    : AgglomerativeClustering(n_clusters=4, linkage='ward'),
    'GaussianMixture(k=4)': GaussianMixture(n_components=4, random_state=0),
}
for name, m in methods.items():
    labels = m.fit_predict(X)
    sil = silhouette_score(X, labels)
    ch  = calinski_harabasz_score(X, labels)
    db  = davies_bouldin_score(X, labels)
    print(f'{name:<22s} silhouette={sil:.3f}  CH={ch:6.1f}  DB={db:.3f}')
📥 入力例: data/raw/SSDSE-B-2026.csv 特徴量: A1101(総人口)、 D210101(県民所得)、 高齢化率、 出生率 前処理: StandardScaler で平均 0、 分散 1 に標準化
📤 実行例: KMeans(n_clusters=4).fit(X) 各クラスタの代表都道府県: C0: 東京・大阪・愛知(都市集中型) C1: 神奈川・千葉・埼玉(首都圏ベッドタウン) C2: 北海道・新潟・福島(広域・中位) C3: 秋田・高知・島根(高齢化・過疎) シルエット係数 = 0.42(中程度の分離)
💬 読み方: k-means は球状クラスタに強いが、 非球状や密度異質には弱い。 シルエット係数 0.42 は「クラスタが妥当に分離されている」程度。 K を増やすと係数は上がるが解釈性が下がる ── エルボー法・BIC で適切な K を選ぶのが基本。 都道府県の 4 類型化は社会保障・地方創生政策の議論に使える。

典型的な観察例: k=4 でシルエット ≈ 0.32、 k=5 で 0.28。 k=4 がやや優位だが「東京・神奈川」「大阪・愛知」「地方中核(北海道・福岡など)」「その他地方」という直感的グループに分かれる。 GMM だと「東京」が単独クラスタになることがあり、 解釈は手法依存。 評価指標は 1 つに頼らず、 シルエット・CH・DB の 3 つを並列で見る。

エルボー法 + シルエットで k を決める

🎯 解説: SSDSE-B-2026 の複数指標を使い、 都道府県をクラスタリング(教師なし学習)する。 k-means、 階層クラスタ、 GMM などで「似た都道府県」をグループ化し、 地域類型を発見する。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
ks = range(2, 11)
inertia, sils = [], []
for k in ks:
    km = KMeans(n_clusters=k, n_init=20, random_state=0).fit(X)
    inertia.append(km.inertia_)
    sils.append(silhouette_score(X, km.labels_))

fig, ax = plt.subplots(1, 2, figsize=(11, 4.5))
ax[0].plot(ks, inertia, 'o-'); ax[0].set_title('Elbow(SSE)')
ax[1].plot(ks, sils, 's-', color='orange'); ax[1].set_title('Silhouette')
for a in ax: a.set_xlabel('k'); a.grid(alpha=.3)
plt.tight_layout(); plt.savefig('elbow_silhouette.png', dpi=140)
📥 入力例: data/raw/SSDSE-B-2026.csv 特徴量: A1101(総人口)、 D210101(県民所得)、 高齢化率、 出生率 前処理: StandardScaler で平均 0、 分散 1 に標準化
📤 実行例: KMeans(n_clusters=4).fit(X) 各クラスタの代表都道府県: C0: 東京・大阪・愛知(都市集中型) C1: 神奈川・千葉・埼玉(首都圏ベッドタウン) C2: 北海道・新潟・福島(広域・中位) C3: 秋田・高知・島根(高齢化・過疎) シルエット係数 = 0.42(中程度の分離)
💬 読み方: k-means は球状クラスタに強いが、 非球状や密度異質には弱い。 シルエット係数 0.42 は「クラスタが妥当に分離されている」程度。 K を増やすと係数は上がるが解釈性が下がる ── エルボー法・BIC で適切な K を選ぶのが基本。 都道府県の 4 類型化は社会保障・地方創生政策の議論に使える。

Ward 法のデンドログラム

🎯 解説: SSDSE-B-2026 の複数指標を使い、 都道府県をクラスタリング(教師なし学習)する。 k-means、 階層クラスタ、 GMM などで「似た都道府県」をグループ化し、 地域類型を発見する。
1
2
3
4
5
6
7
8
9
from scipy.cluster.hierarchy import linkage, dendrogram, fcluster
Z = linkage(X, method='ward')
fig, ax = plt.subplots(figsize=(13, 5))
dendrogram(Z, labels=df['都道府県'].tolist(), leaf_font_size=8, ax=ax)
ax.axhline(8, ls='--', color='red')   # k=4 になる切り高さ
plt.tight_layout(); plt.savefig('dendrogram.png', dpi=140)
labels = fcluster(Z, t=4, criterion='maxclust')
df['cluster_ward'] = labels
print(df.groupby('cluster_ward')['都道府県'].apply(list))
📥 入力例: data/raw/SSDSE-B-2026.csv 特徴量: A1101(総人口)、 D210101(県民所得)、 高齢化率、 出生率 前処理: StandardScaler で平均 0、 分散 1 に標準化
📤 実行例: KMeans(n_clusters=4).fit(X) 各クラスタの代表都道府県: C0: 東京・大阪・愛知(都市集中型) C1: 神奈川・千葉・埼玉(首都圏ベッドタウン) C2: 北海道・新潟・福島(広域・中位) C3: 秋田・高知・島根(高齢化・過疎) シルエット係数 = 0.42(中程度の分離)
💬 読み方: k-means は球状クラスタに強いが、 非球状や密度異質には弱い。 シルエット係数 0.42 は「クラスタが妥当に分離されている」程度。 K を増やすと係数は上がるが解釈性が下がる ── エルボー法・BIC で適切な K を選ぶのが基本。 都道府県の 4 類型化は社会保障・地方創生政策の議論に使える。

⚠️ クラスタリングの落とし穴 — 6 つの典型ミス

① 標準化せずに距離を計算する

「総人口(数百万)」と「失業率(%)」を同じスケールで距離計算すると、 距離はほぼ「総人口の差」だけで決まり、 失業率は無視される。 これは k-means、 階層クラスタリング、 DBSCAN、 すべてに共通する罠。 必ず StandardScaler や RobustScaler で標準化してから距離計算する。 ロバストにしたいなら MinMaxScaler は外れ値に弱く非推奨、 RobustScaler(中央値と IQR でスケーリング)を勧める。

② k を決め打ちで「3 つに分けた」と報告する

k-means で k=3 を最初に指定したら、 必ず 3 つに分かれて結果が出る。 問題は「その 3 つが意味ある分割か」。 必ずエルボー法 (SSE)、 シルエット係数、 Gap statistic、 BIC(GMM 用)で k を選ぶか、 複数の k で結果を比較する。 加えて、 k が違うと「同じ都道府県が違うクラスタに入る」のは普通で、 安定性をチェックするにはブートストラップやランダム部分集合で再実行する。

③ 初期値依存を無視する(n_init=1 のまま)

k-means は初期重心に依存し、 局所最適に落ちる。 sklearn は既定で n_init=10 を 1.4 以降は 'auto' に切り替えたが、 古い API では 1 のまま。 信頼できる結果を得るには n_init ≥ 20 を明示的に指定し、 random_state を固定して再現性を確保。 k-means++(既定)を使うことで初期化品質は上がるが、 完全には除けない。 数百回の再起動で最良の inertia を採用するのが安全。

④ k-means で「非球形クラスタ」を期待する

k-means はユークリッド距離ベースで、 暗黙的に「球形・等分散・等密度」のクラスタを仮定する。 三日月型・リング状・密度の違うクラスタは分離できない。 こうした形状なら DBSCAN・HDBSCAN・Spectral Clustering・Gaussian Mixture を使う。 SSDSE のような都道府県データは球形に近いので k-means で十分だが、 顧客セグメントや画像分類など複雑形状ではダメ。 形状を疑うなら PCA で 2D 散布図を先に確認する。

⑤ シルエット係数を絶対基準にする

シルエットは「クラスタ内の凝集度 vs 外の分離度」を測る便利な指標だが、 球形クラスタを暗黙仮定しており、 DBSCAN の「ノイズ点」や非球形クラスタには不利になる。 評価には Calinski-Harabasz、 Davies-Bouldin、 Adjusted Rand Index(外部ラベルがある場合)を併用し、 ドメイン解釈(「この群は何を意味するか」)も含めて総合判断する。

⑥ 「クラスタが見つかった」を「実在する」と確信する

クラスタリングは「データを必ず k 個に分ける」アルゴリズムで、 一様乱数を入れても k 個に分けて返す。 「クラスタが存在するか」を検定するには Hopkins 統計量(> 0.75 でクラスタ性あり)や、 ランダム化テスト(同じデータをシャッフルしたものとの比較)を実施する。 結果を信じる前に「そもそも構造があるか」を確認する習慣をつける。

🐍 Python 実装バリエーション — sklearn / scipy / hdbscan

1. sklearn.cluster — 5 大手法を一気に比較

🎯 解説: SSDSE-B-2026 の複数指標を使い、 都道府県をクラスタリング(教師なし学習)する。 k-means、 階層クラスタ、 GMM などで「似た都道府県」をグループ化し、 地域類型を発見する。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
from sklearn.cluster import (KMeans, AgglomerativeClustering,
                              DBSCAN, SpectralClustering, MeanShift)
from sklearn.mixture import GaussianMixture

models = {
    'KMeans'         : KMeans(n_clusters=4, n_init=20, random_state=0),
    'Agglo (ward)'   : AgglomerativeClustering(n_clusters=4, linkage='ward'),
    'Agglo (average)': AgglomerativeClustering(n_clusters=4, linkage='average'),
    'DBSCAN'         : DBSCAN(eps=1.2, min_samples=3),
    'Spectral'       : SpectralClustering(n_clusters=4, affinity='rbf',
                                          random_state=0),
    'GMM'            : GaussianMixture(n_components=4, random_state=0),
    'MeanShift'      : MeanShift(),
}
labels_dict = {n: m.fit_predict(X) for n, m in models.items()}
📥 入力例: data/raw/SSDSE-B-2026.csv 特徴量: A1101(総人口)、 D210101(県民所得)、 高齢化率、 出生率 前処理: StandardScaler で平均 0、 分散 1 に標準化
📤 実行例: KMeans(n_clusters=4).fit(X) 各クラスタの代表都道府県: C0: 東京・大阪・愛知(都市集中型) C1: 神奈川・千葉・埼玉(首都圏ベッドタウン) C2: 北海道・新潟・福島(広域・中位) C3: 秋田・高知・島根(高齢化・過疎) シルエット係数 = 0.42(中程度の分離)
💬 読み方: k-means は球状クラスタに強いが、 非球状や密度異質には弱い。 シルエット係数 0.42 は「クラスタが妥当に分離されている」程度。 K を増やすと係数は上がるが解釈性が下がる ── エルボー法・BIC で適切な K を選ぶのが基本。 都道府県の 4 類型化は社会保障・地方創生政策の議論に使える。

2. scipy.cluster.hierarchy — Ward 法の linkage / dendrogram

🎯 解説: SSDSE-B-2026 の複数指標を使い、 都道府県をクラスタリング(教師なし学習)する。 k-means、 階層クラスタ、 GMM などで「似た都道府県」をグループ化し、 地域類型を発見する。
1
2
3
4
5
6
7
from scipy.cluster.hierarchy import linkage, dendrogram, fcluster
from scipy.spatial.distance import pdist
D = pdist(X, metric='euclidean')
Z_ward     = linkage(D, method='ward')
Z_complete = linkage(D, method='complete')
Z_average  = linkage(D, method='average')
labels = fcluster(Z_ward, t=4, criterion='maxclust')
📥 入力例: data/raw/SSDSE-B-2026.csv 特徴量: A1101(総人口)、 D210101(県民所得)、 高齢化率、 出生率 前処理: StandardScaler で平均 0、 分散 1 に標準化
📤 実行例: KMeans(n_clusters=4).fit(X) 各クラスタの代表都道府県: C0: 東京・大阪・愛知(都市集中型) C1: 神奈川・千葉・埼玉(首都圏ベッドタウン) C2: 北海道・新潟・福島(広域・中位) C3: 秋田・高知・島根(高齢化・過疎) シルエット係数 = 0.42(中程度の分離)
💬 読み方: k-means は球状クラスタに強いが、 非球状や密度異質には弱い。 シルエット係数 0.42 は「クラスタが妥当に分離されている」程度。 K を増やすと係数は上がるが解釈性が下がる ── エルボー法・BIC で適切な K を選ぶのが基本。 都道府県の 4 類型化は社会保障・地方創生政策の議論に使える。

3. hdbscan — 密度ベース・k 不要

🎯 解説: SSDSE-B-2026 の複数指標を使い、 都道府県をクラスタリング(教師なし学習)する。 k-means、 階層クラスタ、 GMM などで「似た都道府県」をグループ化し、 地域類型を発見する。
1
2
3
4
5
6
import hdbscan
clusterer = hdbscan.HDBSCAN(min_cluster_size=4, min_samples=2)
labels = clusterer.fit_predict(X)
print('クラスタ数:', len(set(labels)) - (1 if -1 in labels else 0))
print('ノイズ点 :', np.sum(labels == -1))
print('安定性  :', clusterer.cluster_persistence_)
📥 入力例: data/raw/SSDSE-B-2026.csv 特徴量: A1101(総人口)、 D210101(県民所得)、 高齢化率、 出生率 前処理: StandardScaler で平均 0、 分散 1 に標準化
📤 実行例: KMeans(n_clusters=4).fit(X) 各クラスタの代表都道府県: C0: 東京・大阪・愛知(都市集中型) C1: 神奈川・千葉・埼玉(首都圏ベッドタウン) C2: 北海道・新潟・福島(広域・中位) C3: 秋田・高知・島根(高齢化・過疎) シルエット係数 = 0.42(中程度の分離)
💬 読み方: k-means は球状クラスタに強いが、 非球状や密度異質には弱い。 シルエット係数 0.42 は「クラスタが妥当に分離されている」程度。 K を増やすと係数は上がるが解釈性が下がる ── エルボー法・BIC で適切な K を選ぶのが基本。 都道府県の 4 類型化は社会保障・地方創生政策の議論に使える。

4. 評価指標を一括計算

🎯 解説: SSDSE-B-2026 の複数指標を使い、 都道府県をクラスタリング(教師なし学習)する。 k-means、 階層クラスタ、 GMM などで「似た都道府県」をグループ化し、 地域類型を発見する。
1
2
3
4
5
6
7
8
from sklearn.metrics import (silhouette_score, calinski_harabasz_score,
                              davies_bouldin_score, adjusted_rand_score)
for name, lab in labels_dict.items():
    valid = lab != -1   # DBSCAN のノイズを除外
    if len(set(lab[valid])) < 2: continue
    print(f'{name:<18s} sil={silhouette_score(X[valid], lab[valid]):.3f}  '
          f'CH={calinski_harabasz_score(X[valid], lab[valid]):.1f}  '
          f'DB={davies_bouldin_score(X[valid], lab[valid]):.3f}')
📥 入力例: data/raw/SSDSE-B-2026.csv 特徴量: A1101(総人口)、 D210101(県民所得)、 高齢化率、 出生率 前処理: StandardScaler で平均 0、 分散 1 に標準化
📤 実行例: KMeans(n_clusters=4).fit(X) 各クラスタの代表都道府県: C0: 東京・大阪・愛知(都市集中型) C1: 神奈川・千葉・埼玉(首都圏ベッドタウン) C2: 北海道・新潟・福島(広域・中位) C3: 秋田・高知・島根(高齢化・過疎) シルエット係数 = 0.42(中程度の分離)
💬 読み方: k-means は球状クラスタに強いが、 非球状や密度異質には弱い。 シルエット係数 0.42 は「クラスタが妥当に分離されている」程度。 K を増やすと係数は上がるが解釈性が下がる ── エルボー法・BIC で適切な K を選ぶのが基本。 都道府県の 4 類型化は社会保障・地方創生政策の議論に使える。

5. UMAP/t-SNE で可視化

🎯 解説: SSDSE-B-2026 の複数指標を使い、 都道府県をクラスタリング(教師なし学習)する。 k-means、 階層クラスタ、 GMM などで「似た都道府県」をグループ化し、 地域類型を発見する。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
from sklearn.decomposition import PCA
from sklearn.manifold import TSNE
import umap

emb_pca  = PCA(n_components=2).fit_transform(X)
emb_tsne = TSNE(n_components=2, perplexity=8, random_state=0).fit_transform(X)
emb_umap = umap.UMAP(n_neighbors=8, random_state=0).fit_transform(X)

fig, axes = plt.subplots(1, 3, figsize=(15, 4.5))
for ax, emb, t in zip(axes, [emb_pca, emb_tsne, emb_umap],
                      ['PCA','t-SNE','UMAP']):
    ax.scatter(emb[:,0], emb[:,1], c=labels_dict['KMeans'], cmap='Set2', s=50)
    ax.set_title(t)
📥 入力例: data/raw/SSDSE-B-2026.csv 特徴量: A1101(総人口)、 D210101(県民所得)、 高齢化率、 出生率 前処理: StandardScaler で平均 0、 分散 1 に標準化
📤 実行例: KMeans(n_clusters=4).fit(X) 各クラスタの代表都道府県: C0: 東京・大阪・愛知(都市集中型) C1: 神奈川・千葉・埼玉(首都圏ベッドタウン) C2: 北海道・新潟・福島(広域・中位) C3: 秋田・高知・島根(高齢化・過疎) シルエット係数 = 0.42(中程度の分離)
💬 読み方: k-means は球状クラスタに強いが、 非球状や密度異質には弱い。 シルエット係数 0.42 は「クラスタが妥当に分離されている」程度。 K を増やすと係数は上がるが解釈性が下がる ── エルボー法・BIC で適切な K を選ぶのが基本。 都道府県の 4 類型化は社会保障・地方創生政策の議論に使える。

🎨 直感で掴む — クラスタリングを 47 都道府県で実感

クラスタリングは「似た者同士をテーブルに集める」操作です。 SSDSE-B-2026 で 47 都道府県を眺めると、 「人口が多く出生率は低い」群(東京 ・ 大阪)と「人口は少ないが高齢化率が高い」群(秋田 ・ 高知)が自然に浮かびます。 k-means はこの「テーブル分け」を距離だけで自動化するシンプルな比喩です。

📐 数式 — k-means 目的関数

$$ J = \sum_{k=1}^{K} \sum_{x_i \in C_k} \| x_i - \mu_k \|^2 $$

🔬 数式を言葉で読み解く

🌐 関連手法・派生