scikit-learn機械学習㉛DBSCANクラスタリング
前回は、scikit-learnを使って、k-meansの実験を行いました。k-meansは単純明快で計算量も比較的少ない便利なアルゴリズムです。簡単な例では良い結果を出していました。
しかし、k-meansにもいくつか難点があります。例えば、クラスタ数$${k}$$を指定する必要があったり、境界の形状や外れ値などによってはクラスタリングの結果が悪くなる弱点があります。
そこで今回扱うのは、DBSCANです。クラスタリングの一種ですが、クラスタ数を指定する必要がありません。また、k-meansが不得意とする以下のような形状のクラスタリングも可能です。

さらにDBSCANは外れ値も自動的に除外できるという特徴があります。
なお、DBSCANという名前は「Density-Based Spatial Clustering of Applications with Noise」の略です。まあ、こじ付けのような名前ではありますが、それなりに意味が込められています。
DBSCANの意味
まずは、「Density-Based Spatial Clustering of Applications with Noise」の意味について考えて概要を掴んでみましょう。
Density-Based
「密度ベース」は、データの密度を基にクラスタを判定することを意味します。複雑なクラスタの境界や構造にも柔軟に対応できます。
Spatial Clustering
「空間的なクラスタリング」は、空間的な分布(距離に基づく関係)に基づいてクラスタを形成することを意味します。
Applications
これは「アプリケーション」や「応用」と直訳するよりも「いろんなデータ適用できる」くらいの意味で受け止めるのが良いでしょう。ノイズの多いデータや複雑な形状のクラスタが含まれる様々な応用シナリオで使用できることを強調したいのだと考えられます。
with Noise
「ノイズを含む」場合でも対応できるという意味です。DBSCANはどのクラスタにも属さない孤立したポイントを自動的にノイズとして検出し除外します。
では、この名前に値するような仕組みはどのようになっているのでしょうか。
DBSCANの仕組み
DBSCANは、データの密度に基づいてクラスタを形成するアルゴリズムです。以下に具体例を使って、その基本的な仕組みを紹介します。
まず、こんなデータがあるとします。2つのグループに分かれそうなので、k-meansだったら$${k=2}$$と指定するところですが、DBSCANではその必要はありません。

コアポイントの定義
DBSCANでは、まず各データポイントの近傍にいくつのデータポイントがあるかを調べます。この近傍の点が一定数あれば、その点を「コアポイント」(Core Point)とみなします。
例えば、下図の⊕でマークしたデータポイントを中心とした近傍を考えます。

この近傍に3つ以上のデータポイントがある場合に、中心のデータポイントをコアポイントとします。
つまり、DBSCANでは、近傍の半径とデータポイント数によって各データポイントが「コアポイント」であるかどうかの判断をします。
このルールに従って決めたコアポイントから徐々にクラスタを拡張していきます。
クラスタの拡張
コアポイントから開始し、その近傍のポイントも同じクラスタに含めます。

また、近傍にある別のコアポイントもクラスタに含め、その周囲の近傍に再度ポイントを追加するというように、クラスタを広げていきます。

ここではわかりやすく端っこから始めましたが、実際のデータはランダムな順番に並んでいることもあるでしょう。そういった場合は、他の場所にクラスタが生成されます。

それでも、「近傍の近傍はみな近傍だ」ということで、やがては同じクラスタにまとまっていきます。

つまり、密度(近傍の中のデータポイントの数)が一定以上の領域を基に小さなクラスタを形成し連結してきます。

なお、近傍の距離の外にあるデータポイントはクラスタに含まれません。よって、別のクラスタを形成することになります。

これを続けることで最終的にクラスタの数が自動的に決定されることなります。

ボーダーポイントとノイズ
DBSCANでは、以下のような特徴を持つデータポイントをボーダーポイント(Border Point)と呼びます。
コアポイントではない(指定半径内の密度が 最低限の数より少ない)
少なくとも1つのコアポイントの半径内に存在する
例えば、データポイントの最低限数が4だとします。すると、下図の⊕ は他のコアポイントの半径内に存在し、そのクラスタ(赤)に含まれていますが、コアポイントにはなりません。

つまり、クラスタの境界付近に存在するポイントで、密度が低いためコアポイントにはならないものをボーダーポイントと呼びます。
この判別をプログラムとして表現するとこんな感じになります。
# ボーダーポイントの判定
def is_border_point(point, eps, min_pts, points):
neighbors = get_neighbors(point, eps, points)
if len(neighbors) < min_pts: # コアポイントではない
for neighbor in neighbors:
# 少なくとも1つのコアポイントの半径内に存在する?
if is_core_point(neighbor, eps, min_pts, points):
return True
return False
# コアポイントの判別
def is_core_point(point, eps, min_pts, points):
neighbors = get_neighbors(point, eps, points)
return len(neighbors) >= min_pts上記の引数の意味は以下になります。
point : 判定するデータポイント
eps : 近傍の半径
min_pts : データポイント数の下限
points : 全てのデータポイント
まとめると、クラスタに含まれるがそれ自体はコアポイントでないものがボーダーポイントです。よって、クラスタにはコアポイントとボーダーポイントが共存しています。
一度クラスタに割り当てられたボーダーポイントは、他のクラスタには割り当てられません。つまり、ボーダーポイントが複数のクラスタのコアポイントに近接している場合、最初に見つかったクラスタに含まれるというルールが一般的です。
その一方、どのコアポイントにも属さないデータポイントは「ノイズ」として分類され、クラスタには含まれません。
どのコアポイントの近傍の半径内にも存在しない
クラスタには含まれない(ボーダーポイントでもない)
よって、データポイントの最低限数が4だとすると、下図の白いデータポイントはノイズとして判定されます。

よって、近傍の半径とデータポイント数の設定によってクラスタの形成とノイズとして除外されるデータポイントに大きな影響があります。
例えば、数は最低限のデータポイント数を3とした場合です。

この設定では、ノイズがなくなりボーダーポイントとなっています。
k-meansとの比較
以上より、DBSCANとk-meansの大きな違いが見えてきます。
トップダウン vs ボトムアップ
クラスタの形成のアプローチが大きく異なります。
k-meansは、まずクラスタの中心(セントロイド)を設定し、そこから各ポイントを割り当てる「トップダウン」型のアプローチです。クラスタの数を先に決め、それにデータを当てはめていくため、全体的な構造があらかじめ想定されています。
DBSCANは、個々のポイントから始めてコアポイントとその近傍を拡張していく「ボトムアップ」型のアプローチです。密度が一定以上の領域を基にクラスタを形成していくため、最初にクラスタの構造を決める必要がなく、より柔軟にデータの構造を捉えることができます。
つまり、DBSCANは密度ベースの手法で、コアポイントを中心に近傍の密度が高い領域をクラスタとして拡張するため、リング状や半月形など複雑な形状のクラスタも検出可能であり、k-means よりも優れている特徴です。
外れ値の自動処理
もう一つの大きな違いとして、k-means では問題となっていた「外れ値」の処理があります。
k-meansでは、外れ値がセントロイド(データポイントの平均)に大きな影響を与えます。前処理であらかじめ取り除くか、残して含めたままにするかなどを検討する必要があります。
DBSCANは、「外れ値」(ノイズ)を自動的に除外できます。よって、ノイズを含むデータにも適しています。ただし、近傍の半径やデータポイントの最低限数などを指定する必要があります。
DBSCANの問題点
DBSCANとk-meansを比較した場合の良い点と悪い点を以下に示します。
密度に敏感
これは当たり前でもあるのですが、DBSCANは近傍の半径とデータポイントの最低限数のパラメータに敏感です。これらのパラメータを適切に設定しないと、クラスタが適切に検出されない可能性があります。
これなら、k-meansでクラスタ数を指定する方がお手軽だと感じるかもしれません。クラスタ数を指定しないので、設定によってはとんでもない数のクラスタが形成されることもあります。
また、クラスタによってデータの密度が異なる場合は適切なパラメータ設定が難しくなる可能性があります。つまり、密なクラスタと疎なクラスタが混在する場合には、クラスタリング結果が不安定になるかもしれません。
言い方を変えると、DBSCANは一貫した密度を持つクラスタを見つけることに適しているため、密度が大きく異なるクラスタが存在する場合、それらを適切に分離できないことがあります。
高次元データには不向き
高次元ではデータは密になる方が稀なので、密度の概念が機能しにくくなります。
これは2次元と3次元で同じデータ数をばら撒いたときに、3次元の方がより疎になることを考えるとわかりやすいでしょう。例えば、3次元での分布を上から眺めたら密に見えても、横から眺めると高低がバラバラになっていればそれは密ではありません。よって、次元数が増えると密度が薄くなりがちなので、DBSCANによるクラスタリングが機能しにくくなります。
この場合は、k-meanのように中心から一定の距離内にあるものを含めるアプローチの方がよく機能する可能性があります。
言うまでもないですが、それぞれのアルゴリズムには得意な状況が異なるため、データの性質に応じて使い分けるのが理想的です。
次回予告
次回は、scikit-learnを使ってDBSCANで実験を行います。
お楽しみに!
