Databricksにおけるクラスタリング

こちらが非常に参考になりました。

https://data-analysis-stats.jp/%E6%A9%9F%E6%A2%B0%E5%AD%A6%E7%BF%92/pyspark%E3%81%A7%E3%81%AEk-mean%E3%82%AF%E3%83%A9%E3%82%B9%E3%82%BF%E3%83%AA%E3%83%B3%E3%82%B0/

MLlibのKmeansの説明はこちら。

https://spark.apache.org/docs/latest/ml-clustering.html#k-means

> [k\-means](http://en.wikipedia.org/wiki/K-means_clustering)は、データポイントを事前に定義した数のクラスターにクラスタリングを行うクラスタリングアルゴリズムで最もよく利用されるものの一つです。MLlibの実装には[kmeans\|\|](http://theory.stanford.edu/~sergei/papers/vldb12-kmpar.pdf)と呼ばれる[k\-means\+\+](http://en.wikipedia.org/wiki/K-means%2B%2B)の並列化バージョンが含まれています。
>
> `KMeans`は`Estimator`として実装されており、ベースモデルとして`KMeansModel`を生成します。

上の記事に沿って実行してみますが、一部新機能など活用しています。

# ライブラリのインポート

```py:Python
from pyspark.ml.clustering import KMeans
from pyspark.ml.evaluation import ClusteringEvaluator
from pyspark.sql import SparkSession
```

# データのダウンロード

[ワークスペースファイル](https://qiita.com/taka_yayoi/items/b0878db170c864d5bcf9)がサポートされたので、DBFSを使わずにファイルをダウンロードできます。便利です。

```py:Python
import urllib 

urllib.request.urlretrieve("http://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequality-red.csv", "/Workspace/Users/takaaki.yayoi@databricks.com/20230511_spark_clustering/winequality-red.csv")
```
![Screenshot 2023-05-11 at 16.36.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/66852f28-3926-d808-e246-0872219020ab.png)

# データの読み込み

ワークスペースファイルから直接Sparkデータフレームにロードすることもできます。

```py:Python
sp_path = 'file:/Workspace/Users/takaaki.yayoi@databricks.com/20230511_spark_clustering/winequality-red.csv'
sdf = spark.read.csv(sp_path, header=True, sep=';', inferSchema=True)
```

```py:Python
display(sdf)
```

ワインの化学特性のデータです。
![Screenshot 2023-05-11 at 16.39.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/01c7b726-bd28-765b-1d06-3a2caf549eb5.png)

# ベクトルの生成

MLlibのKMeansの入力`featuresCol`がVectorなので、`VectorAssembler`でデータフレームをベクトルに変換します。

```py:Python
from pyspark.ml.feature import VectorAssembler

train = VectorAssembler(inputCols=sdf.columns, outputCol="features").transform(sdf)
```
![Screenshot 2023-05-11 at 16.43.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/00b38e4f-43b1-27e2-ec9b-d8b4e0c80495.png)

# シルエットスコアの比較

シルエットスコアが高いほど、クラスターに含まれるオブジェクトが一致していることを示します。適切なクラスター数を特定する助けとなります。

```py:Python
for k in range(2,8):
  kmeans = KMeans().setK(k).setSeed(1)
  model = kmeans.fit(train)
  predictions = model.transform(train)
  evaluator = ClusteringEvaluator()
  silhouette = evaluator.evaluate(predictions)
  print("With K={}".format(k))
  print("Silhouette with squared euclidean distance = " + str(silhouette))
  print('--'*30)
  print("High value indicates that the object is well matched to its own cluster")
```

```
With K=2
Silhouette with squared euclidean distance = 0.772194945850551
------------------------------------------------------------
High value indicates that the object is well matched to its own cluster
With K=3
Silhouette with squared euclidean distance = 0.6895576732268774
------------------------------------------------------------
High value indicates that the object is well matched to its own cluster
With K=4
Silhouette with squared euclidean distance = 0.656312517141184
------------------------------------------------------------
High value indicates that the object is well matched to its own cluster
With K=5
Silhouette with squared euclidean distance = 0.6207361460993716
------------------------------------------------------------
High value indicates that the object is well matched to its own cluster
With K=6
Silhouette with squared euclidean distance = 0.613234543966971
------------------------------------------------------------
High value indicates that the object is well matched to its own cluster
With K=7
Silhouette with squared euclidean distance = 0.5619709932825219
------------------------------------------------------------
High value indicates that the object is well matched to its own cluster
```

# モデルの作成(k=2)

```py:Python
# k-meansモデルのトレーニング
kmeans = KMeans().setK(2).setSeed(1)
model = kmeans.fit(train)
```

なお、フィッテイングするたびにMLflowにモデルがトラッキングされます。これも便利。
![Screenshot 2023-05-11 at 16.46.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/42c49ecd-ae58-72dd-1bf2-8c22593ebf54.png)

```py:Python
# 予測の実行
predictions = model.transform(train)
```

```py:Python
# クラスター中心の表示
centers = model.clusterCenters()
print("Cluster Centers: ")
for center in centers:
    print(center)
```

```
Cluster Centers: 
[ 8.42425785  0.51933418  0.26653944  2.39427481  0.08544614 12.37192536
 30.34435963  0.99667684  3.31552163  0.65653096 10.5402177   5.72434266]
[ 8.02595238  0.55164286  0.28342857  2.94452381  0.0931381  25.70833333
 91.72857143  0.99694274  3.2987381   0.66269048 10.09388889  5.38809524]
```

# 可視化

```py:Python
countByCluster = predictions.groupBy("prediction").count()
display(countByCluster)
```

クラスタリングされていますね。
![Screenshot 2023-05-11 at 16.51.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/ab5f83b9-3850-e7a2-dc90-05eda274f6a8.png)


### Databricksクイックスタートガイド

[Databricksクイックスタートガイド](https://www.amazon.co.jp/dp/B09V1YXFVQ/)


### Databricks無料トライアル

[Databricks無料トライアル](https://databricks.com/jp/try-databricks)