web-dev-qa-db-ja.com

scikit-DBSCANのメモリ使用量を学ぶ

PDATED:結局、大きなデータセットのクラスタリングに使用することを選択したソリューションは、以下のAnony-Mousseによって提案されたものでした。つまり、scikit-learnではなく、ELKIのDBSCAN実装を使用してクラスタリングを実行します。コマンドラインから実行でき、適切なインデックスを使用して、このタスクを数時間以内に実行します。 GUIと小さなサンプルデータセットを使用して、使用するオプションを決定してから、町に行きます。調べる価値があります。誰でも、私の元の問題の説明といくつかの興味深い議論を読んでください。

クラスター化しようとしている35個の特徴(浮動小数点値)をそれぞれ含む約250万個のサンプルを含むデータセットがあります。私は、マンハッタン距離メトリックと、データから抽出されたいくつかの小さなランダムサンプルから推定されたイプシロンの値を使用して、scikit-learnのDBSCANの実装でこれを実行しようとしています。ここまでは順調ですね。 (参考のために、ここにスニペットがあります)

_db = DBSCAN(eps=40, min_samples=10, metric='cityblock').fit(mydata)
_

現時点での私の問題は、メモリが簡単に不足することです。 (私は現在、16 GBのRAMを搭載したマシンで作業しています)

私の質問は、DBSCANが実行中にペアワイズ距離行列をその場で計算しているのか、それが私の記憶を奪っているのかということです。 (250万^ 2)* 8バイトは明らかにばかげているほど大きいと思います。 fit()メソッドを使用すべきではありませんか?そして、より一般的には、この問題を回避する方法はありますか、それとも私は一般的にここで間違った木を吠えていますか?

答えが明白になってしまったらお詫びします。私はこれについて数日間困惑してきました。ありがとう!

補遺:また、誰かがfit(X)fit_predict(X)の違いをもっと明確に説明できれば、私も感謝します-私はそれを完全に理解していないのではないかと心配しています。

補遺#2:確かに、これを最大550 GBのRAMのマシンで試したところ、まだ爆発しているので、DBSCANがペアワイズ距離行列を作成しようとしているように感じますまたは、明らかにやりたくないことです。今の大きな問題は、その動作を停止する方法、または自分のニーズにさらに適した他の方法を見つけることだと思います。ここでご協力いただきありがとうございます。

補遺#3(!):トレースバックを添付するのを忘れました。

_Traceback (most recent call last):
  File "tDBSCAN.py", line 34, in <module>
    db = DBSCAN(eps=float(sys.argv[2]), min_samples=10, metric='cityblock').fit(mydata)
  File "/home/jtownsend/.local/lib/python2.6/site-packages/sklearn/base.py", line 329, in fit_predict
    self.fit(X)
  File "/home/jtownsend/.local/lib/python2.6/site-packages/sklearn/cluster/dbscan_.py", line 186, in fit
    **self.get_params())
  File "/home/jtownsend/.local/lib/python2.6/site-packages/sklearn/cluster/dbscan_.py", line 69, in dbscan
    D = pairwise_distances(X, metric=metric)
  File "/home/jtownsend/.local/lib/python2.6/site-packages/sklearn/metrics/pairwise.py", line 651, in pairwise_distances
    return func(X, Y, **kwds)
  File "/home/jtownsend/.local/lib/python2.6/site-packages/sklearn/metrics/pairwise.py", line 237, in manhattan_distances
    D = np.abs(X[:, np.newaxis, :] - Y[np.newaxis, :, :])
MemoryError
_
25
JamesT

問題は明らかに、_scikit-learn_での非標準のDBSCAN実装です。

DBSCANは距離行列を必要としません。アルゴリズムは、regionQuery関数を高速化し、クエリ半径内のネイバーを効率的に返すことができるデータベースを使用して設計されました(空間インデックスはO(log n)でそのようなクエリをサポートする必要があります)。

ただし、scikitでの実装は、完全なO(n^2)距離行列を計算するようです。これには、メモリとランタイムの両方のコストがかかります。

したがって、2つの選択肢があります。

  1. 代わりに、 [〜#〜] elki [〜#〜] でDBSCAN実装を試してみることをお勧めします。これは、R *ツリーインデックスとともに使用すると、通常、単純な実装よりも大幅に高速になります。

  2. それ以外の場合は、scikitでの実装が明らかにあまり良くないため、DBSCANを再実装することをお勧めします。それを恐れないでください。DBSCANは自分で実装するのが本当に簡単です。優れたDBSCAN実装の最も難しい部分は、実際にはregionQuery関数です。このクエリを高速に取得できれば、DBSCANも高速になります。また、この関数を他のアルゴリズムに実際に再利用することもできます。

更新:これで、sklearnは距離を計算しなくなりましたmatrixそして、たとえば、kdツリーインデックスを使用できます。ただし、「ベクトル化」のため、stillすべてのポイントの近傍が事前計算されるため、大きなイプシロンのsklearnのメモリ使用量はO(n²)ですが、私の理解では、ELKIのバージョンはO(n)メモリ。したがって、メモリが不足した場合は、小さいイプシロンを選択および/または試してください [〜#〜] elki [〜 #〜]

これは、scikit-learnのDBSCANとhaversineメトリックおよびボールツリーアルゴリズムを使用して行うことができます。距離行列を事前に計算する必要はありません。

この例100万を超えるGPS緯度経度ポイントを超えるクラスターDBSCAN/haversineを使用し、メモリ使用量の問題を回避します。

df = pd.read_csv('gps.csv')
coords = df.as_matrix(columns=['lat', 'lon'])
db = DBSCAN(eps=eps, min_samples=ms, algorithm='ball_tree', metric='haversine').fit(np.radians(coords))

これは特にscikit-learnv0.15を使用することに注意してください。一部の以前/後のバージョンでは、完全な距離行列を計算する必要があるようです。これにより、RAMが非常に高速になります。ただし、アナコンダ、これは次の方法ですばやく設定できます。

conda install scikit-learn=0.15

または、このクラスタリングタスク用のクリーンな仮想環境を作成します。

conda create -n clusterenv python=3.4 scikit-learn=0.15 matplotlib pandas jupyter
activate clusterenv
12
eos

Sklearnのこの問題については、以下で説明します。

https://github.com/scikit-learn/scikit-learn/issues/5275

そこには2つのオプションがあります。

1つは、OPTICS(sklearn v21 +が必要)を使用することです。これは、DBSCANの代替であるが、密接に関連するアルゴリズムです。

https://scikit-learn.org/dev/modules/generated/sklearn.cluster.OPTICS.html

その他は、隣接行列を事前計算するか、サンプルの重みを使用することです。これらのオプションの詳細については、こちらのメモをご覧ください。

https://scikit-learn.org/stable/modules/generated/sklearn.cluster.DBSCAN.html

2
Isaac

複雑さがO(N ^ 2)だったため、sklearn0.19.1で古いバージョンを使用していたときに同じ問題に直面しました。

しかし、問題は新しいバージョン0.20.2で解決され、メモリエラーはなくなり、複雑さはO(n.d)ここで、dはネイバーの平均数です。アイドルの複雑さではありません。しかし、古いバージョンよりもはるかに優れています。

高いメモリ使用量を回避するために、このリリースの注意事項を確認してください: https://scikit-learn.org/stable/modules/generated/sklearn.cluster.DBSCAN.html

1
MMamdouh

DBSCANアルゴリズムは実際に距離行列を計算するため、ここではチャンスがありません。これだけのデータについては、MiniBatchKMeansを使用することをお勧めします。そのままではマンハッタンメトリックを使用することはできませんが、独自の実装を行うことはできます。たぶん、最初にユークリッド距離を使った標準的な実装を試してみてください。

ペアワイズ距離を実行しないクラスタリングアルゴリズムをあまり知りません。

新しく埋め込まれた チートシート 下部中央を使用:運が良かった。

0
Andreas Mueller