SparkでDBSCANを実行したいと思います。私は現在2つの実装を見つけました:
私はそのgithubで与えられたsbt構成で最初のものをテストしましたが:
jar内の関数は、ドキュメントまたはgithubのソース内の関数と同じではありません。たとえば、jarファイルにtrain関数が見つかりません
fit関数(jarにあります)を使用してテストを実行できましたが、イプシロンの構成が不適切(少しから大きい)でコードが挿入されました無限ループ。
コード:
val model = DBSCAN.fit(eps, minPoints, values, parallelism)
誰かが最初のライブラリで何かをすることができましたか?
誰かが2番目のものをテストしましたか?
[〜#〜] elki [〜#〜] を試してください。これはJavaなので、Scalaから簡単に呼び出すことができます。
ELKIは非常によく最適化されており、インデックスを使用すると、非常に大きなデータセットに拡張できます。
これらのSpark実装の1つをベンチマーク調査に含めようとしましたが、メモリが不足しました(そして、メモリが不足した唯一の実装でした...のk-means = SparkとMahoutも最も遅い)の中にありました:
ハンス・ペーター・クリーゲル、エーリヒ・シューベルト、アーサー・ジメク。
ランタイム評価の(黒)技術:アルゴリズムまたは実装を比較していますか?
In:知識と情報システム(KAIS)。 2016、1〜38
Neukirchen教授は、このテクニカルレポートでDBSCANの並列実装のベンチマークを行いました。
Helmut Neukirchen
ビッグデータおよび高性能コンピューティングパラダイムのためのDBSCAN空間クラスタリング実装の調査およびパフォーマンス評価
どうやら彼はいくつかのSpark実装を機能させましたが、次のことに注意しました:
結果は壊滅的です:Apache Sparkの実装はHPC実装に近いところはありません。特に、より大きな(しかしまだかなり小さい)データセットでは、それらのほとんどは完全に失敗し、正しい結果さえ提供しません。
以前:
クラスタで使用可能なすべてのコアを使用しながら「SparkDBSCAN」実装のいずれかを実行すると、メモリ不足の例外が発生しました。
(また、「Spark DBSCAN」は928コアで2406秒かかり、ELKIは小さいベンチマークの1コアで997秒かかりました-他のSpark実装もうまくいきませんでした、特にそれ正しい結果が返されませんでした...)
「DBSCANonSpark」はクラッシュしませんでしたが、完全に間違ったクラスターを返しました。
「DBSCANonSpark」はより速く終了しますが、完全に間違ったクラスタリング結果をもたらしました。 Sparkはすでにコア数が最大であるため、DBSCAN実装の実行時間が絶望的に長いため、コア数が少ない測定は実行しませんでした。
_double[][]
_配列をELKIデータベースとしてラップできます。
_// Adapter to load data from an existing array.
DatabaseConnection dbc = new ArrayAdapterDatabaseConnection(data);
// Create a database (which may contain multiple relations!)
Database db = new StaticArrayDatabase(dbc, null);
// Load the data into the database (do NOT forget to initialize...)
db.initialize();
// Squared Euclidean is faster than Euclidean.
Clustering<Model> c = new DBSCAN<NumberVector>(
SquaredEuclideanDistanceFunction.STATIC, eps*eps, minpts).run(db);
for(Cluster<KMeansModel> clu : c.getAllClusters()) {
// Process clusters
}
_
参照: Java APIの例 (特に、DBIDを行インデックスにマップする方法)。パフォーマンスを向上させるには、インデックスファクトリ(new CoverTree.Factory(...)
など)を2番目のパラメーターとしてStaticArrayDatabase
コンストラクターに渡します。
プロジェクトで2番目のライブラリ( https://github.com/alitouka/spark_dbscan )を正常に使用しました。実際、次のように使用することはできません。
libraryDependencies += "org.alitouka" % "spark_dbscan_2.10" % "0.0.4"
resolvers += "Aliaksei Litouka's repository" at "http://alitouka-public.s3-website-us-east-1.amazonaws.com/"
代わりに、コードをダウンロードしてspark 2.2.1バージョンに更新します。さらに、いくつかのライブラリを追加する必要があります。最後に、コードをプロジェクトに追加すると、機能します。
私はテストしました https://github.com/irvingc/dbscan-on-spark そしてそれは多くのメモリを消費すると言うことができます。スムーズに分散された400Kデータセットの場合、-Xmx12084mを使用しましたが、この場合でも動作が長すぎます(> 20分)。また、2Dのみです。私はsbtではなくMavenでプロジェクトを使用しました。
2番目の実装もテストしました。これはまだ私が見つけた最高です。残念ながら、作成者は2015年以降サポートしていません。Sparkのバージョンを上げて、バージョンの競合を解決するのに本当に時間がかかりました。awsにデプロイする必要がありました。
DBSCANの実装を提供する smile の使用を検討することもできます。最も直接的な方法でgroupBy
をmapGroups
またはflatMapGroups
と組み合わせて使用する必要があり、そこでdbscan
を実行します。次に例を示します。
import smile.clustering._
val dataset: Array[Array[Double]] = Array(
Array(100, 100),
Array(101, 100),
Array(100, 101),
Array(100, 100),
Array(101, 100),
Array(100, 101),
Array(0, 0),
Array(1, 0),
Array(1, 2),
Array(1, 1)
)
val dbscanResult = dbscan(dataset, minPts = 3, radius = 5)
println(dbscanResult)
// output
DBSCAN clusters of 10 data points:
0 6 (60.0%)
1 4 (40.0%)
Noise 0 ( 0.0%)
パフォーマンスを向上させる必要がある場合は、ユーザー定義集計関数(UDAF)を作成することもできます。
私はこのアプローチを使用して時系列データのクラスタリングを行っているため、Sparkのタイムウィンドウ関数を使用してグループ化し、各ウィンドウ内でDBSCANを実行できるようにすることで、実装を並列化できます。
私はこれを行うために次の 記事 に触発されました