データ分析の世界において、クラスタリングはデータの中に潜む構造を明らかにするための非常に強力な手法です。しかし、多くのクラスタリング手法では「クラスタ数をいくつにするか?」という問いに、分析者自身が答えを出す必要がありました。
「最適なクラスタ数が事前にわからない…」 「k-meansを使ってみたけど、綺麗な円形でないデータ群はうまく分割できない…」 「データに含まれるノイズ(外れ値)に分析結果が引っ張られてしまう…」
もしあなたがこのような課題に直面したことがあるなら、HDBSCANがその解決策になるかもしれません。
この記事では、密度ベースクラスタリングの進化形であるHDBSCANについて、その基本原理からPythonライブラリを使った具体的な実装、そして結果を改善するためのパラメータチューニングまで、ステップ・バイ・ステップで徹底的に解説します。
この記事を読み終える頃には、あなたは以下のスキルを習得しているでしょう。
- HDBSCANがどのようなアルゴリズムで、何が優れているのかを理解できる
- Pythonを使ってHDBSCANによるクラスタリングを実装できる
- 分析結果を可視化し、直感的に解釈できる
- 主要なパラメータを調整し、より良いクラスタリング結果を得られる
それでは、HDBSCANの強力な世界を一緒に探求していきましょう!
HDBSCANとは? 〜密度ベースクラスタリングの進化形〜
結論から言うと、HDBSCAN (Hierarchical Density-Based Spatial Clustering of Applications with Noise) は、データ自身が持つ密度の構造に基づいて、クラスタ数を自動で決定してくれる非常に賢いクラスタリング手法です。
従来のk-meansのようにデータが球状であることを前提とせず、様々な形状のクラスタを発見できるのが大きな強みです。
HDBSCANの3つの主な特徴(メリット)
HDBSCANがなぜ多くのデータサイエンティストに支持されているのか、その主な特徴を3つご紹介します。
- クラスタ数の事前指定が不要 これが最大のメリットです。HDBSCANはデータの密度を解析し、最も安定しているクラスタ構造を自動で抽出します。これにより、分析者の主観が入り込む余地を減らし、より客観的な分析が可能になります。
- 外れ値(ノイズ)の自動検出 どのクラスタにも属さないデータポイントを、自動的に「ノイズ」として分類します。これにより、外れ値に惑わされることなく、データの主要な構造に集中して分析を進めることができます。ノイズとして分類されたデータには
-1という特別なラベルが割り当てられます。 - 様々な密度のクラスタに対応可能 データセットの中に、密度が高いクラスタと低いクラスタが混在していても問題ありません。HDBSCANはそれぞれの密度に応じた適切なクラスタ境界を見つけ出すことができます。
DBSCANとの違いは?
HDBSCANを理解する上で、その前身であるDBSCANとの比較は欠かせません。DBSCANもまた、密度ベースの優れたクラスタリング手法ですが、2つの主要なパラメータ(epsilon:近傍の距離、min_samples:近傍に必要な最小点数)を分析者が設定する必要がありました。
特にepsilonの設定は非常にデリケートで、この値一つでクラスタリングの結果が大きく変わってしまいます。
HDBSCANは、このepsilonを固定値として与える必要がない点でDBSCANを大きく進化させました。内部的にあらゆるepsilonの値を試し、データの階層的なクラスタ構造を構築します。その中から「最も安定している(長く存続する)クラスタ」を最終的な結果として選択するのです。このアプローチにより、より柔軟で頑健なクラスタリングが実現されています。
準備編:HDBSCANライブラリのインストール
それでは、早速HDBSCANを使ってみましょう。HDBSCANは、scikit-learnと互換性のあるAPIを持つhdbscanという独立したライブラリとして提供されています。
ターミナルやコマンドプロンプトで以下のpipコマンドを実行して、ライブラリをインストールしてください。
pip install hdbscan依存関係にあるnumpyやscikit-learnなども同時にインストールされるため、基本的にはこの一行で準備は完了です。
実践編:Scikit-learnでHDBSCANを使ってみよう
ここからは、実際にコードを書きながらHDBSCANの使い方を学びます。サンプルデータを生成し、クラスタリングを実行、そして結果を可視化するまでの一連の流れを体験していきましょう。
1. 分析用データの準備
まず、分析に必要なライブラリをインポートし、クラスタリング用のサンプルデータを生成します。ここでは、scikit-learnのmake_blobs関数を使い、意図的に密度が異なる3つの塊と、いくつかのノイズ点を含むデータセットを作成します。
import hdbscan
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.datasets import make_blobs
# Seabornのスタイルを設定
sns.set_context('poster')
sns.set_style('white')
sns.set_color_codes()
plot_kwds = {'alpha' : 0.6, 's' : 80, 'linewidths':0}
# 1. データの生成
# 意図的に密度の異なるクラスタを生成
centers = [[1, 1], [-1, -1], [1.5, -1.5]]
X, labels_true = make_blobs(n_samples=750, centers=centers, cluster_std=[0.4, 0.2, 0.5],
random_state=0)
# データをプロットして確認
plt.figure(figsize=(10, 8))
plt.scatter(X.T[0], X.T[1], color='b', **plot_kwds)
plt.title('Original Data')
plt.show()このコードを実行すると、3つの点の集まりがプロットされます。これから、このデータに隠された構造をHDBSCANで見つけ出します。
2. HDBSCANモデルの学習とクラスタリング実行
hdbscanライブラリの使い方は、scikit-learnの他のモデルと非常によく似ており、直感的に操作できます。
hdbscan.HDBSCANクラスのインスタンスを作成し、fit_predict()メソッドを呼ぶだけで、学習とクラスタラベルの予測が一度に完了します。
# 2. HDBSCANモデルの学習とクラスタリング実行
# min_cluster_sizeは最も重要なパラメータの一つ
# クラスタとして認識されるための最小のサンプル数を指定
clusterer = hdbscan.HDBSCAN(min_cluster_size=10)
# fit_predictで学習とラベル予測を同時に実行
cluster_labels = clusterer.fit_predict(X)
# 結果のユニークなラベルと、各ラベルの数を表示
unique_labels, counts = np.unique(cluster_labels, return_counts=True)
print(f"ユニークなクラスタラベル: {unique_labels}")
print(f"各ラベルのデータ数: {counts}")min_cluster_sizeは「クラスタと見なされるための最小の点の数」を定義する、HDBSCANで最も重要なパラメータです。今回は「最低10個の点が集まっていればクラスタと見なす」と設定しました。
実行結果として、ユニークなクラスタラベルとその数が表示されます。-1はノイズ、0, 1, 2…がそれぞれ検出されたクラスタに対応します。
3. 結果の確認と可視化
最後に、クラスタリングの結果を可視化して、うまく分離できているかを確認しましょう。matplotlibとseabornを使って、クラスタごとに色分けした散布図を作成します。
ノイズ点(ラベルが-1)は灰色でプロットし、検出されたクラスタを鮮やかな色で表示することで、結果を直感的に理解できます。
# 3. 結果の確認と可視化
# カラーパレットを生成 (ノイズ用に-1も考慮)
unique_labels = np.unique(cluster_labels)
n_clusters = len(unique_labels[unique_labels > -1])
palette = sns.color_palette('deep', n_clusters)
# ノイズは灰色で、クラスタはカラーパレットの色でプロット
colors = [palette[l] if l != -1 else (0.5, 0.5, 0.5) for l in cluster_labels]
plt.figure(figsize=(10, 8))
plt.scatter(X.T[0], X.T[1], c=colors, **plot_kwds)
# 各クラスタの中心などを計算してラベル付けすることも可能
# (ここでは省略)
plt.title(f'HDBSCAN Clustering (Estimated clusters: {n_clusters})')
plt.show()
# ノイズとして判定された点の数を計算
noise_count = np.sum(np.array(cluster_labels) == -1)
print(f'ノイズとして検出された点の数: {noise_count}')生成されたプロットを見ると、元のデータにあった3つの塊がそれぞれ異なる色でクラスタリングされ、どの塊にも属さない点が灰色(ノイズ)として正しく分離されていることが確認できるはずです。
もう一歩踏み込む:HDBSCANの主要パラメータ解説
HDBSCANはデフォルト設定でも優れた性能を発揮しますが、いくつかの主要なパラメータを調整することで、さらに分析の精度を高めることができます。ここでは特に重要な2つのパラメータを紹介します。
min_cluster_size:最小クラスタサイズ
これは先ほども使用した、最も重要で直感的なパラメータです。この値は「クラスタとして存続するために必要な最小の点の数」を意味します。
- 値を大きくすると: 小さな集まりはノイズと見なされやすくなり、より大きく安定したクラスタが残りやすくなります。データの全体像を大まかに掴みたい場合に有効です。
- 値を小さくすると: 小さな集まりもクラスタとして検出されやすくなります。より細かな構造を捉えたい場合に有効ですが、ノイズを拾いやすくなる可能性もあります。
どの値が最適かはデータに依存するため、分析の目的に応じていくつかの値を試してみるのが良いでしょう。
min_samples:コア点と見なすための近傍サンプル数
このパラメータは、ある点が「密な領域」の中心(コア点)と見なされるために、その周辺にいくつの点が必要かを定義します。DBSCANのmin_ptsに相当する概念です。
- 値を大きくすると: より密度が高い領域だけがクラスタの核となるため、ノイズに対して非常に頑健になります。ただし、密度の低いクラスタを見逃してしまう可能性があります。
- 値を小さくすると: ノイズの多いデータセットでもクラスタを検出しやすくなりますが、本来ノイズであるべき点をクラスタに含めてしまうリスクも増えます。
一般的に、min_samplesはmin_cluster_sizeと同じか、それより小さい値に設定します。まずはmin_cluster_sizeを決め、その後にmin_samplesを調整してノイズの感度をコントロールするのがおすすめです。
cluster_selection_epsilon:クラスタを分割する距離
これはやや上級者向けのパラメータです。HDBSCANが内部で構築する階層ツリーから、最終的なクラスタを切り出す際の「距離の閾値」を指定します。DBSCANのepsilonに近い役割を果たしますが、通常はこのパラメータを調整する必要はほとんどありません。
まとめ:HDBSCANを使いこなしてデータ分析の精度を上げよう
今回は、密度ベースクラスタリングの強力な手法であるHDBSCANについて、その基礎からPythonでの実践的な使い方までを解説しました。
最後に、この記事の重要なポイントを振り返りましょう。
- HDBSCANはクラスタ数の事前指定が不要で、データの密度構造から自動的にクラスタを抽出する。
- どのクラスタにも属さない外れ値(ノイズ)を自動で検出し、
-1ラベルを付与してくれる。 - Pythonでは
hdbscanライブラリをインストールすれば、scikit-learnライクな簡単な操作で実装できる。 min_cluster_sizeは、結果をコントロールする上で最も重要なパラメータ。
HDBSCANは、クラスタ数が未知の探索的データ分析、金融取引における不正検知、顧客のセグメンテーションなど、非常に幅広い分野でその真価を発揮します。
ぜひ、今回学んだ知識を活かして、ご自身のデータセットでHDBSCANを試してみてください。きっと、これまで見えなかったデータの中に眠るインサイトを発見できるはずです。


コメント