1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

HDBSCANとは?初心者向けにわかりやすく解説

1
Last updated at Posted at 2026-04-15

HDBSCAN(Hierarchical Density-Based Spatial Clustering of Applications with Noise)

一言でいうと:「クラスター数を指定しなくていい、密度ベースの賢いクラスタリング手法。ノイズ(どこにも属さない点)も自動的に検出してくれる」


k-meansとの違い

クラスタリングといえばk-meansが有名ですが、テキスト分析では相性が悪いケースがあります。

比較項目 k-means HDBSCAN
クラスター数の指定 必要(k=?を事前に決める) 不要(自動で決まる)
クラスターの形状 球形のみ想定 任意の形状に対応
ノイズの扱い 全データをどこかに強制割当 ノイズとして検出できる
外れ値への耐性 弱い(外れ値がセントロイドを歪める) 強い
密度の違いへの対応 苦手 得意(密度が違うクラスターも分離)

k-meansの限界

k-means の問題:「k=5 って決めたけど、本当に5クラスターあるの?」

k=3 と決めたとき          実際のデータ分布
  ○ ○ ○               ●●●   ●●●   ●●●●●
  ↑ ↑ ↑               (自然に3つの塊がある)
  セントロイドを
  無理やり3つ配置
  → 形のいびつなクラスターが生まれる

商品レビューの話題(トピック)は「何種類あるか」が事前にわかりません。HDBSCANはそれを自動で見つけてくれます。


密度の直感的な説明

「色が濃い部分」がクラスターの核心

HDBSCANの「密度」を一番わかりやすく理解する方法は、散布図の色の濃さで考えることです。

散布図のイメージ:

  ・  ・                ← スカスカ(密度が低い)=ノイズ候補
      ●●●●
    ●●●●●●●           ← 色が濃い(密度が高い)=クラスターの核心
      ●●●●
  ・                    ← 一匹狼(どこにも属さない)=ノイズ
            ●●●
          ●●●●●●       ← 別の塊=別のクラスター
            ●●●

「点が密集している=色が濃い部分」がクラスターの中心になり、その周辺に薄くつながっている点がクラスターのメンバーになる、という直感は正しいです。

HDBSCANは内部的に「ある点の周囲にどれだけ点があるか」を密度として計算しています。密度が高い領域同士がつながっている塊を1つのクラスターと認識します。


ノイズの概念——一匹狼的なレビュー

「ノイズって何?」という疑問

最初にHDBSCANを使ったとき、ラベルに -1 が現れるのを見て戸惑うかもしれません。

labels = hdbscan.HDBSCAN().fit_predict(embeddings)
# array([0, 1, 0, -1, 2, -1, 1, ...])
#                ^^        ^^
#               ノイズ!?

-1 はエラーではありません。これが「ノイズ」です。

ノイズ=どのクラスターにも属さないレビュー

商品レビューのデータセットで考えてみましょう。

クラスター0:「配送が遅い」系のレビュー   → 100件
クラスター1:「品質が良い」系のレビュー   → 80件
クラスター2:「価格が高い」系のレビュー   → 60件

ノイズ(-1):
  - 「配送への不満と品質の称賛を混ぜたようなレビュー」1件
  - 「文脈が特殊すぎて他と似ていないレビュー」3件
  - 「誤ってデータセットに入った無関係な投稿」2件

これらは「どのクラスターにも半端にしか似ていない、一匹狼的なレビュー」です。

k-meansなら 強制的にどこかのクラスターに割り当ててしまいますが、HDBSCANは正直に「これはノイズ」と言ってくれます。分析の精度を守るために、あえて「わからない」と言える設計になっています。

ノイズ率の目安

ノイズ率 = ノイズ件数 / 全件数

~10% : 許容範囲(クラスターがうまく分離できている)
10〜30% : 要検討(min_cluster_size を下げると取り込める可能性あり)
30%〜  : パラメータ調整が必要(クラスターが細かすぎる)

パラメータの説明

min_cluster_size——クラスターと認めるための最小サイズ

hdbscan.HDBSCAN(min_cluster_size=100)

HDBSCANで最も重要なパラメータです。

  • **「最低でもこの件数がいないとクラスターとは呼ばない」**という閾値
  • 小さいほどクラスター数が増え、細かい分割になる
  • 大きいほどクラスター数が減り、大きな塊だけが残る
min_cluster_size=50  → クラスター数:多い  ノイズ:少ない
min_cluster_size=500 → クラスター数:少ない ノイズ:多い(小さな塊がノイズ扱い)

クラスター数を「指定」していないのに結果が変わる理由はここにあります。「最小サイズの閾値」を変えると、どの密度の塊をクラスターと認めるかが変わるからです。


min_samples——ノイズ判定の厳しさ

hdbscan.HDBSCAN(min_samples=5)  # デフォルト:min_cluster_sizeと同値
  • ある点が「コア点(クラスターの核心)」と認められるために、周囲に必要な点の数
  • 大きくするほど厳しくなり、ノイズが増える
  • 小さくするほど寛容になり、ノイズが減る
  • 通常は min_cluster_size と同じかやや小さい値にする

cluster_selection_method——クラスター境界の決め方

hdbscan.HDBSCAN(cluster_selection_method='eom')  # デフォルト
hdbscan.HDBSCAN(cluster_selection_method='leaf')
特徴
'eom'(Excess of Mass) 階層的なクラスター木の「安定した部分」を選ぶ。大小様々なクラスターを自然に検出
'leaf' 木の末端(葉)を使う。クラスターが細かく・均一なサイズになりやすい

テキストクラスタリングでは 'eom'(デフォルト) が多くの場合うまく機能します。


今回のパラメータ調整の試行錯誤

min_cluster_size を段階的に変えて、クラスタリング結果がどう変わるかを確認しました。

min_cluster_size クラスター数 ノイズ件数 ノイズ率 所感
50 42 312 8.4% 細かすぎて解釈が大変。類似クラスターが乱立
150 18 489 13.2% まだ多い。細かい話題まで拾いすぎ
300 9 671 18.1% バランスが取れてきた。主要な話題が見えてくる
500 5 1,024 27.6% 大きすぎる塊に。ノイズが多く情報損失が気になる

min_cluster_size=300 を採用

調整の基準にしたのは以下の3点:

  1. 各クラスターに「意味のある共通テーマ」が読み取れるか
  2. ノイズ率が20%以下に収まっているか
  3. クラスター数が人間がレビューできる範囲(5〜15個)か

今回の使い方——商品レビュークラスタリングパイプラインでの役割

パイプライン内での位置づけ

高次元埋め込み(1536次元)
    ↓ UMAP(15次元に削減)
低次元ベクトル(15次元)
    ↓ HDBSCAN ← ここ
クラスターラベル(0, 1, 2, ..., -1)
    ↓ UMAP(2次元に削減・可視化)
散布図 + クラスター色分け

HDBSCANが担う役割

主なタスク:レビュー話題の自動グルーピング

import hdbscan

clusterer = hdbscan.HDBSCAN(
    min_cluster_size=300,
    min_samples=30,
    cluster_selection_method='eom',
    metric='euclidean'  # UMAP削減後なのでユークリッドでOK
)
labels = clusterer.fit_predict(umap_embeddings)

注意:UMAPで次元削減した後のベクトルに対してHDBSCANを適用しています。UMAPの出力はユークリッド距離が有効になっているため、metric='euclidean' を使います(生の埋め込みに直接かける場合は metric='cosine' を検討)。

結果の解釈

import numpy as np

n_clusters = len(set(labels)) - (1 if -1 in labels else 0)
n_noise = np.sum(labels == -1)
noise_rate = n_noise / len(labels)

print(f"クラスター数: {n_clusters}")
print(f"ノイズ件数: {n_noise} ({noise_rate:.1%})")

# 各クラスターのサイズ確認
for i in range(n_clusters):
    size = np.sum(labels == i)
    print(f"クラスター{i}: {size}")

ノイズを活用する

ノイズと判定された投稿も捨てずに分析します:

  • 希少なレビュー話題の候補:まだ表面化していない新しい不満や要望かもしれない
  • 多言語・多文化のレビュー:日本語と英語が混在するなど、クラスターに馴染みにくいレビュー
  • 誤分類の検出:関係ないデータが混入していたことを示すシグナル

まとめ

項目 ポイント
何をするか 密度ベースの自動クラスタリング
k-meansとの違い クラスター数不要・任意形状・ノイズ検出
密度の直感 散布図で「色が濃い部分」=クラスターの核心、その通り
ノイズ(-1)の意味 どのクラスターにも馴染まない一匹狼的なレビュー。捨てずに活用
最重要パラメータ min_cluster_size(これを変えるとクラスター数が変わる)
今回の採用値 min_cluster_size=300(50→150→300→500 で試した結果)

参考

  • HDBSCAN公式ドキュメント
  • Campello et al. (2013). Density-Based Clustering Based on Hierarchical Density Estimates
  • [[UMAP]] — 次元削減(HDBSCANの前処理として使用)
  • [[review-clustering]] — 本プロジェクトでの実装

tags: #ML #クラスタリング #HDBSCAN #密度ベース #NLP #レビュー分析

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?