論文一覧に戻る 📚 用語解説(ジャストインタイム型データサイエンス教育)
DBSCAN(密度ベースクラスタリング)
Density-Based Spatial Clustering of Applications with Noise
「点が密集しているところを 1 つのかたまり」とみなし、まばらな点は雑音 (noise) として扱うクラスタリング手法。
k-means と違い クラスタ数を指定不要外れ値を自動で識別 できる。
教師なし学習 クラスタリング 密度ベース 外れ値検出
💡 30秒結論 📍 文脈 🎨 直感 📐 数式・定義 🔬 記号の読み解き 🧮 SSDSE-B で計算 🐍 Python 実装 ⚠️ 落とし穴 🌐 関連手法 🔗 関連用語 📚 グループ教材 🗺 概念マップ

💡 30 秒で分かる結論

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

論文の手法欄で、こんな記述を見たことがあるはずです:

本研究では DBSCAN (eps=0.5, min_samples=4) を用い、 47 都道府県を密度ベースでクラスタリングした。
その結果、 3 つの主要クラスタ4 県の外れ値(東京・大阪・神奈川・愛知) が検出された。

この DBSCAN は、 k-means や階層的クラスタリングとは 発想がまったく違うクラスタリング手法 です。 「データ点の密度」だけで自然なまとまりを見つけ、 例外的に孤立した点を「noise」として除外 します。 GPS 軌跡・画像解析・地理空間データ・ソーシャルネットワーク分析など、 不規則な形状や外れ値を含むデータで特に強力です。

🎨 直感で掴む — 「人だかり」を見つける魔法

夜の繁華街を上空から見るところを想像してください。 ある場所には人が密集しています(駅前広場、 ライブ会場、 屋台)。 別の場所はぽつぽつとしか歩いていません(住宅街、 公園の隅)。 DBSCAN は「人がたくさんいる場所」を 1 つのかたまりと認識し、 「ぽつんと孤立した人」は「群衆ではない」と分離する アルゴリズムです。

3 種類の「点」 ― これだけ覚えればよい

DBSCAN は、 すべてのデータ点を次の 3 種類に分類します:

種類定義例えるなら
コア点
(Core point)
半径 ε 以内に minPts 個以上 の点が存在する点 「人だかりの真ん中で、 周りが密集している人」
境界点
(Border point)
コア点ではないが、 あるコア点の ε 以内 にいる点 「人だかりの周縁にいて、 中の人と肩が触れている人」
雑音点
(Noise point)
コア点でも境界点でもない点(誰のクラスタにも属さない) 「ぽつんと一人で離れて立っている人」 → 外れ値扱い

クラスタ形成のイメージ

コア点同士で「半径 ε 以内」に到達できる関係を全部つないでいくと、 1 つのクラスタが浮かび上がります。 その周りに境界点をくっつければ完成。 残った点はすべて noise です。

k-means との根本的違い
  • k-means は 「重心からの距離」で割り当てる → クラスタは 球形に近い形しか作れない
  • DBSCAN は 「密度のつながり」で割り当てる → 三日月型・らせん型でも OK
  • k-means は クラスタ数 K を事前指定、 DBSCAN は 自動決定
  • k-means は 全点をどこかに割り当てる、 DBSCAN は 外れ値を雑音として除外できる

📐 数式と厳密な定義

データ集合 $D = \{x_1, x_2, \dots, x_n\} \subset \mathbb{R}^d$ と 2 つのパラメータ ($\varepsilon, \text{minPts}$) を考えます。

【ε 近傍 (epsilon-neighborhood)】
$$N_\varepsilon(x) = \{y \in D \mid \mathrm{dist}(x, y) \le \varepsilon\}$$
点 $x$ から半径 $\varepsilon$ 以内に存在するすべての点の集合。$\mathrm{dist}$ は通常ユークリッド距離。
【コア点 (core point) の条件】
$$x \text{ がコア点} \iff |N_\varepsilon(x)| \ge \text{minPts}$$
自分自身を含めて minPts 以上の点が ε 近傍にあれば、 その点はコア点。
【密度到達可能 (density-reachable)】
$$y \text{ は } x \text{ から密度到達可能} \iff \exists\, x = p_1, p_2, \dots, p_k = y \text{ s.t. } p_{i+1} \in N_\varepsilon(p_i)\, \land\, p_i \text{ はコア点}$$
コア点を「踏み石」のように経由して y にたどり着けるかどうか。
【密度連結 (density-connected) によるクラスタ】
$$C = \{x \mid \exists z \in D \text{ s.t. } x \text{ と } z \text{ がともに } z \text{ から密度到達可能}\}$$
この同値類で 1 つのクラスタを形成する。 どのクラスタにも属さない点が noise。

🔬 数式を「言葉」で読み解く

$\varepsilon$ (eps)
近い」と判定する距離のしきい値。 小さくすると 1 クラスタが細切れになりやすく、 noise が増える。 大きくすると逆に「全部 1 つ」になりがち。
minPts (min_samples)
コア点と認めるのに必要な近傍点数(自分を含む)。 経験則として 2 次元データでは minPts = 4 程度、 一般的には minPts ≥ d + 1($d$ は特徴量の次元数)を推奨。
$N_\varepsilon(x)$
点 $x$ から距離 $\varepsilon$ 以内にある点の集合(自分自身も含む)。 「近所付き合いの範囲」と思えばよい。
$\mathrm{dist}(x, y)$
距離関数。 デフォルトは ユークリッド距離。 sklearn では metric 引数でマンハッタン距離・コサイン距離なども選択可。
密度到達可能
コア点を経由した「連鎖的な近さ」。 これにより、 細長い形状や曲線状のクラスタも 1 つにまとめられる。
noise (ラベル −1)
どのクラスタにも属せない点。 sklearn の labels_ 配列で -1 として返される。

🧮 SSDSE-B 47 都道府県データで計算してみる

SSDSE-B(2026 年版)の 「人口総数」 ($x$)「県内総生産」 ($y$) の 2 変数で、 47 都道府県を DBSCAN でクラスタリングします。 まずは 7 県だけのサンプルで手計算してみましょう(標準化済み)。

都道府県人口 $z_x$(標準化)県内総生産 $z_y$(標準化)位置イメージ
東京+4.91+5.43右上の極端な外れ値
神奈川+1.86+1.55右上中央
大阪+1.71+1.74右上中央
愛知+1.22+1.66右上中央
福岡+0.39+0.21中央付近
広島−0.10−0.05中央付近
島根−0.97−1.08左下小規模県
STEP 1 パラメータ設定
$\varepsilon = 0.5$, $\text{minPts} = 3$ とする。 標準化済み座標を使う。
STEP 2 各点の ε 近傍を列挙
・東京:周辺に他県が無い(神奈川との距離 ≈ √((4.91−1.86)²+(5.43−1.55)²) ≈ 4.94 > 0.5)→ 近傍 0 個
・神奈川:大阪 (dist=√(0.0225+0.0361)≈0.24) と愛知 (dist≈0.65) → 大阪のみ近い
・大阪:神奈川 (0.24)、 愛知 (0.49) → 近傍 3 個(自分含む) → コア候補
・愛知:大阪 (0.49) → 近傍 2 個
・福岡:広島 (dist=√(0.24+0.068)≈0.55) → ぎりぎり外
・広島:福岡 (0.55)、 島根 (dist=√(0.76+1.06)≈1.35) → 近傍 1 個
・島根:単独
STEP 3 コア点・境界点・noise を判定
コア点:大阪のみ(minPts=3 を満たす)
境界点:神奈川、 愛知(大阪の ε 近傍にいる)
noise (−1)東京、 福岡、 広島、 島根(コアの ε 近傍に入れない)
STEP 4 結果
クラスタ 0:{神奈川、 大阪、 愛知} / noise:{東京、 福岡、 広島、 島根}
解釈:たった 7 県ではほとんど noise になる。 47 県全部・ε を少し緩めると、 「地方圏」が 1 大クラスタにまとまり、 大都市圏の 4 県が noise として浮かび上がる構造になります。

ポイント:DBSCAN の結果は ε と minPts の設定に強く依存します。 上の例では ε=0.5 でしたが、 ε=0.8 にすれば noise が 2 県(東京・島根)に減ります。 「最適な ε」を探すには次節の k-distance graph を使います。

🐍 Python 実装 — SSDSE-B で 47 都道府県をクラスタリング

scikit-learn の DBSCAN クラスを使えば数行で実行できます。 標準化 を忘れないこと。

1. 基本的な使い方

 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
import pandas as pd
import numpy as np
from sklearn.cluster import DBSCAN
from sklearn.preprocessing import StandardScaler

# SSDSE-B 2026 を読み込む(自治体コードと人口/県内総生産)
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='utf-8-sig', header=1)

# 2023 年だけに絞り、必要 2 変数を抜き出す
df_23 = df[df['年度'] == 2023].copy()
X = df_23[['A1101', 'A1102']].values  # 人口総数, 県内総生産(億円)

# 標準化(必須!)
X_std = StandardScaler().fit_transform(X)

# DBSCAN 実行
db = DBSCAN(eps=0.5, min_samples=4).fit(X_std)
labels = db.labels_

# クラスタ数(noise=−1 は除く)と noise 数
n_clusters = len(set(labels)) - (1 if -1 in labels else 0)
n_noise = list(labels).count(-1)
print(f'クラスタ数: {n_clusters}, noise: {n_noise}件')

# どの県が noise か
df_23['cluster'] = labels
print(df_23[df_23['cluster'] == -1][['地域', 'A1101', 'A1102']])

2. 最適な ε を k-distance graph で決める

「ε をいくつにすればよいか」迷ったときは、 k-distance graph(k 番目最近傍点までの距離の昇順プロット)の 肘 (elbow) を ε に取るのが定石です。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
from sklearn.neighbors import NearestNeighbors
import matplotlib.pyplot as plt

k = 4  # minPts と同じ値が定番
nn = NearestNeighbors(n_neighbors=k).fit(X_std)
dist, _ = nn.kneighbors(X_std)
k_dist = np.sort(dist[:, k-1])  # k番目最近傍までの距離を昇順ソート

plt.figure(figsize=(8, 4))
plt.plot(k_dist)
plt.xlabel('Points sorted by distance')
plt.ylabel(f'{k}-NN distance')
plt.title('k-distance graph (elbow = eps)')
plt.grid(True, alpha=0.3)
plt.show()

# 急に立ち上がる点(肘)の y 座標を eps に採用する

3. 結果を散布図で可視化

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import matplotlib.pyplot as plt

fig, ax = plt.subplots(figsize=(9, 6))
colors = ['#1976D2', '#E64A19', '#388E3C', '#7B1FA2', '#FBC02D']
for lbl in set(labels):
    mask = labels == lbl
    color = '#333' if lbl == -1 else colors[lbl % len(colors)]
    name = 'noise' if lbl == -1 else f'cluster {lbl}'
    ax.scatter(X_std[mask, 0], X_std[mask, 1],
               c=color, s=90, alpha=0.85, label=name,
               edgecolor='white', linewidth=1.2)
ax.set_xlabel('人口(標準化)')
ax.set_ylabel('県内総生産(標準化)')
ax.legend(loc='lower right')
ax.set_title('DBSCAN: 47 都道府県の密度ベースクラスタリング')
plt.tight_layout()
plt.show()

4. パラメータの感度分析

同じデータでも (ε, minPts) を変えると結果は大きく変わります。 感度を確認しましょう。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
from itertools import product

results = []
for eps, mp in product([0.3, 0.5, 0.8, 1.0], [3, 4, 5]):
    db = DBSCAN(eps=eps, min_samples=mp).fit(X_std)
    lab = db.labels_
    n_cl = len(set(lab)) - (1 if -1 in lab else 0)
    n_no = int((lab == -1).sum())
    results.append({'eps': eps, 'minPts': mp,
                    'クラスタ数': n_cl, 'noise数': n_no})

print(pd.DataFrame(results).pivot(index='eps', columns='minPts', values='noise数'))

5. シルエット係数でクラスタリングの質を評価

1
2
3
4
5
6
7
8
9
from sklearn.metrics import silhouette_score

# noise を除く点だけで評価する
mask = labels != -1
if len(set(labels[mask])) >= 2:
    s = silhouette_score(X_std[mask], labels[mask])
    print(f'silhouette = {s:.3f}')
else:
    print('クラスタ数 )

⚠️ 5 つの「DBSCAN 落とし穴」

① 標準化を忘れて ε の意味が崩壊する
人口(単位:人、 桁数:100 万〜10000 万)と県内総生産(単位:億円、 桁数:1 万〜100 万)を そのまま 入れると、 距離は人口の差だけで決まり、 県内総生産は無視されます。 必ず StandardScalerMinMaxScaler で同じスケールに揃える こと。 ε もスケール後の単位で考える。
② 密度が場所によって違うデータが苦手
DBSCAN は 全空間で同じ ε を使うため、 「中心は密、 端は疎」のような密度が不均一な分布では、 端のクラスタが noise に潰れたり、 中心が大きすぎる 1 つに合体したりします。
対処:拡張版の HDBSCAN(階層的 DBSCAN、 局所密度を考慮)や OPTICS を試す。 sklearn にも OPTICS がある。
③ 高次元では距離が劣化する(curse of dimensionality)
特徴量 d ≧ 10〜20 を超えると、 「すべての点がほぼ等距離」 になり、 ε 近傍が壊れます。
対処:先に PCA・UMAP などで次元削減してから DBSCAN を適用。 もしくは類似度メトリック(コサイン距離など)を使う。
④ ε と minPts の選び方が結果を決定する
ε が小さすぎる → ほぼ全部 noise、 大きすぎる → 全部 1 クラスタ。 k-distance graph の肘シルエット係数 を使って客観的に決める。 デフォルト値を盲信しない。 minPts は最小 3、 一般的に min_samples ≈ 2d(d は次元数)。
⑤ 大規模データでは遅い ― O(n²) の壁
naive 実装では計算量が $O(n^2)$。 1 万点以上で実用上厳しい。 sklearn の algorithm='ball_tree'kd_tree を指定すると $O(n \log n)$ に近くなる。 さらに大規模なら GPU 版 cuML、 分散版 ELKI を検討。

🌐 関連手法・派生

手法特徴DBSCAN との関係
OPTICS 各点の到達可能距離をプロットし、 「ε を 1 つに決めずに」階層的に密度クラスタを抽出 密度が不均一なデータに強い。 sklearn にあり
HDBSCAN 階層的 DBSCAN。 局所的に最適な ε を自動で見つける 近年の実務での 第一選択hdbscan パッケージ
Mean Shift 密度の山(モード)に向かって点を移動させる 密度ベースだが、 noise 概念は持たない
Gaussian Mixture Model (GMM) 混合ガウス分布で確率的にクラスタ割り当て パラメトリック。 球形〜楕円形クラスタに向く
k-means 重心ベース、 K を事前指定 球形クラスタに最適。 DBSCAN とよく比較される
階層的クラスタリング 樹形図(dendrogram)で階層を可視化 小規模データで構造を可視化したいとき有用

📚 関連グループ教材

DBSCAN を含むクラスタリング手法を体系的に学ぶには、 以下のグループ教材が役立ちます:

🗺 概念マップ — DBSCAN の位置づけ

階層 概念 関係
上位教師なし学習 → クラスタリングDBSCAN はこのカテゴリの 1 手法
同列k-means, 階層的, GMM, Mean Shift同じ「クラスタリング」だが原理が異なる
下位(発展)OPTICS, HDBSCANDBSCAN の弱点(密度不均一性)を改良
前提距離計算、 標準化、 ハイパーパラメータどれが欠けても結果が崩れる
応用外れ値検出、 異常検知、 GPS 軌跡分析noise ラベルをそのまま活用