Data Science/머신러닝

Pyspark로 k-means clustering 구현하기.

히또아빠 2024. 1. 19. 11:17

 

pyspark로 k-means 클러스터링을 하는 code를 정리한다.

 

우선, pyspark에서 머신러닝 module을 사용하기 위해서는 알고리즘에 사용되는 features의 

vectorize 과정이 필요하다. (vector 형태의 column이 ML 알고리즘의 Input으로 들어가게됨)

여기서 pyspark의 vector에 대해 정리해뒀는데 참고!

https://sikmulation.tistory.com/45

 

[PySpark] dense 벡터와 sparse 벡터, UDF로 sparse vector 만들기

1.vector 개념 희소 벡터를 생성하려면 벡터 길이(엄격하게 증가해야 하는 0이 아닌 값과 0이 아닌 값의 인덱스)를 제공해야 합니다. pyspark.mllib.linag.Vecotors 라이브러리는 dense(고밀도), sparse(희소) 두

sikmulation.tistory.com

 

우선, vectorize 하기위해 VectorAssembler 모듈을 불러와 내가 클러스터링에 사용하고자 하는 Input을 vector 형식으로 변환했다.

변수가 이미 scaling 처리를 한 상태라 다른 스케일러는 적용안했는데, 기회가 된다면 추후에 이 부분도 정리하도록 하겠다.

from pyspark.ml.feature import VectorAssembler
# clustrting에 필요한 
assembler = VectorAssembler(inputCols = ["app_cnt_ratio", "label_app_cnt_ratio", "male_app_cnt_ratio", "female_app_cnt_ratio", "log_sum_ratio"\
                                        ,"label_app_log_ratio", "male_app_log_ratio", "female_app_log_ratio", "personal_label_app_cnt_ratio"\
                                        ,"personal_male_app_cnt_ratio", "personal_female_app_cnt_ratio", "personal_label_app_log_ratio"\
                                        ,"personal_male_app_log_ratio", "personal_female_app_log_ratio"], outputCol ="features")

df = assembler.transform(final_eda_90)

그리고 그다음 할것은 만든 features를 클러스터링 알고리즘에 넣는 것 뿐이다. 물론 K-means 클러스터를 몇개로 지정할지, 성능 체크 기준을 무엇으로 할지 등 문제를 정의하는 것이 필요한 부분이 많지만 현재는 단순 클러스터링을 pyspark에서 구현하는 방법만 다뤘다.

 

지금 코드에서는 k = 2개의 클러스터 부터 k = 20개의 클러스터까지 데이터를 묶으며 실루엣 계수를 측정했다.

실루엣 계수는 물체가 다른 클러스터(분리)에 비해 자기 클러스터(cohesion)와 얼마나 유사한지를 측정하는 척도다. -1에서 1 사이의 범위로, 값이 높으면 물체가 자기 클러스터와 잘 일치하지 않고 이웃 클러스터와 잘 일치하지 않는다는 것을 나타낸다. 

 

실루엣 계수 구분

  • 1 근처일때:  개체가 자신의 클러스터 내부에 있고 이웃 클러스터에서 멀리 떨어져 있음을 나타냄
  • 0 근처일때: 객체가 인접한 클러스터 중 하나에 할당될 수 있는 중첩된 클러스터를 나타냄
  • -1 근처일때: 개체가 잘못된 클러스터에 할당되었을 수 있음

일반적으로 실루엣 계수가 높을수록 잘정의된 클러스터로 정의하는데 현재는 2 ~ 11개까지의 클러스터는 0.99 ~ 0.96 까지 잘 유지를 하지만 12개부터 0.81 > 0.70 등 급속하게 실루엣 계수가 낮아짐으로 클러스터 갯수는 11개 이내로 정의하는 것이 적합해 보인다.

import numpy as np
from pyspark.ml.clustering import KMeans
from pyspark.ml.evaluation import ClusteringEvaluator

k_values = range(2, 20)
silhouette_scores = []

for k in k_values:
    kmeans = KMeans().setK(k).setSeed(1).setFeaturesCol("features").setPredictionCol("cluster")
    model = kmeans.fit(df)
    predictions = model.transform(df)

    evaluator = ClusteringEvaluator(predictionCol="cluster")
    silhouette = evaluator.evaluate(predictions)
    silhouette_scores.append(silhouette)

# Plot the silhouette scores for different k values
import matplotlib.pyplot as plt

plt.plot(k_values, silhouette_scores, marker='o')
plt.xlabel('Number of Clusters (k)')
plt.ylabel('Silhouette Score')
plt.title('Silhouette Score for Different Values of k')
plt.show()


silhouette_scores

[0.9993694578087788,
 0.9916014319513857,
 0.9920789577975849,
 0.9928132820234703,
 0.9915426523979542,
 0.9901357178076591,
 0.9874350258075568,
 0.967110616583866,
 0.9660596937690502,
 0.9753736746372378,
 0.9669224984299244,
 0.8135628967931758,
 0.7029545816047863,
 0.7039018424598599,
 0.7104851758490636,
 0.7035830643514563,
 0.7092261545244508,
 0.6996426548429274]

 

300x250
반응형