-
[군집화] DBSCAN머신러닝 & 딥러닝 2021. 11. 3. 22:02
DBSCAN (Density Based Spatial Clustering of Applications with Noise)
특정 공간 내에 데이터 밀도 차이를 기반 알고리즘으로 하고 있어서 복잡한 기하학적 분포도를 가진 데이터 세트에 대해서도 군집화를 잘 수행한다.
알고리즘이 데이터 밀도 차이를 자동으로 감지하며 군집을 생성하므로 사용자가 군집 개수를 지정할 수 없다.
데이터의 밀도가 자주 변하거나, 아예 모든 데이터의 밀도가 크게 변하지 않으면 군집화 성능이 떨어진다.
피처의 개수가 많으면 군집화 성능이 떨어진다.
DBSCAN 구성 요소
DBSCAN을 구성하는 가장 중요한 두 파라미터는 입실론(epsilon)으로 표기하는 주변 영역과 이 입실론 주변 영역에 포함되는 최소 데이터의 개수 min points
핵심 포인트 (Core Point): 주변 영역 내에 최소 데이터 개수 이상의 타 데이터를 가지고 있을 경우 해당 데이터를 핵심 포인트라 한다.
이웃 포인트 (Neighbor Point): 주변 영역 내에 위치한 타 데이터를 이웃 포인트라고 한다.
경계 포인트 (Border Point): 주변 영역 내에 최소 데이터 개수 이상의 이웃 포인트를 가지고 있지 않지만 핵심 포인트를 이웃 포인트로 가지고 있는 데이터를 경계 포인트라고 한다.
잡음 포인트 (Noise Point): 최소 데이터 개수 이상의 이웃 포인트를 가지고 있지 않으며, 핵심 포인트도 이웃 포인트로 가지고 있지 않는 데이터를 잡음 포인트라고 한다.
DBSCAN 적용하기 – 붓꽃 데이터 셋
from sklearn.datasets import load_iris import matplotlib.pyplot as plt import numpy as np import pandas as pd %matplotlib inline iris = load_iris() feature_names = ['sepal_length','sepal_width','petal_length','petal_width'] # 보다 편리한 데이타 Handling을 위해 DataFrame으로 변환 irisDF = pd.DataFrame(data=iris.data, columns=feature_names) irisDF['target'] = iris.target irisDF.head()
sepal_length sepal_width petal_length petal_width target 0 5.1 3.5 1.4 0.2 0 1 4.9 3.0 1.4 0.2 0 2 4.7 3.2 1.3 0.2 0 3 4.6 3.1 1.5 0.2 0 4 5.0 3.6 1.4 0.2 0 eps 0.6 min_samples=8 로 DBSCAN 군집화 적용
from sklearn.cluster import DBSCAN dbscan = DBSCAN(eps=0.6, min_samples=8, metric='euclidean') dbscan_labels = dbscan.fit_predict(iris.data) irisDF['dbscan_cluster'] = dbscan_labels iris_result = irisDF.groupby(['target'])['dbscan_cluster'].value_counts() print(iris_result)
target dbscan_cluster 0 0 49 -1 1 1 1 46 -1 4 2 1 42 -1 8 Name: dbscan_cluster, dtype: int64
### 클러스터 결과를 담은 DataFrame과 사이킷런의 Cluster 객체등을 인자로 받아 클러스터링 결과를 시각화하는 함수 def visualize_cluster_plot(clusterobj, dataframe, label_name, iscenter=True): if iscenter : centers = clusterobj.cluster_centers_ unique_labels = np.unique(dataframe[label_name].values) markers=['o', 's', '^', 'x', '*'] isNoise=False for label in unique_labels: label_cluster = dataframe[dataframe[label_name]==label] if label == -1: cluster_legend = 'Noise' isNoise=True else : cluster_legend = 'Cluster '+str(label) plt.scatter(x=label_cluster['ftr1'], y=label_cluster['ftr2'], s=70,\ edgecolor='k', marker=markers[label], label=cluster_legend) if iscenter: center_x_y = centers[label] plt.scatter(x=center_x_y[0], y=center_x_y[1], s=250, color='white', alpha=0.9, edgecolor='k', marker=markers[label]) plt.scatter(x=center_x_y[0], y=center_x_y[1], s=70, color='k',\ edgecolor='k', marker='$%d$' % label) if isNoise: legend_loc='upper center' else: legend_loc='upper right' plt.legend(loc=legend_loc) plt.show()
PCA 2개 컴포넌트로 기존 feature들을 차원 축소 후 시각화
from sklearn.decomposition import PCA # 2차원으로 시각화하기 위해 PCA n_componets=2로 피처 데이터 세트 변환 pca = PCA(n_components=2, random_state=0) pca_transformed = pca.fit_transform(iris.data) # visualize_cluster_2d( ) 함수는 ftr1, ftr2 컬럼을 좌표에 표현하므로 PCA 변환값을 해당 컬럼으로 생성 irisDF['ftr1'] = pca_transformed[:,0] irisDF['ftr2'] = pca_transformed[:,1] visualize_cluster_plot(dbscan, irisDF, 'dbscan_cluster', iscenter=False)
eps의 크기를 증가 한 후 노이즈 확인
from sklearn.cluster import DBSCAN dbscan = DBSCAN(eps=0.8, min_samples=8, metric='euclidean') dbscan_labels = dbscan.fit_predict(iris.data) irisDF['dbscan_cluster'] = dbscan_labels irisDF['target'] = iris.target iris_result = irisDF.groupby(['target'])['dbscan_cluster'].value_counts() print(iris_result) visualize_cluster_plot(dbscan, irisDF, 'dbscan_cluster', iscenter=False)
target dbscan_cluster 0 0 50 1 1 50 2 1 47 -1 3 Name: dbscan_cluster, dtype: int64
min_samples의 크기를 증가 후 노이즈 확인
dbscan = DBSCAN(eps=0.6, min_samples=16, metric='euclidean') dbscan_labels = dbscan.fit_predict(iris.data) irisDF['dbscan_cluster'] = dbscan_labels irisDF['target'] = iris.target iris_result = irisDF.groupby(['target'])['dbscan_cluster'].value_counts() print(iris_result) visualize_cluster_plot(dbscan, irisDF, 'dbscan_cluster', iscenter=False)
target dbscan_cluster 0 0 48 -1 2 1 1 44 -1 6 2 1 36 -1 14 Name: dbscan_cluster, dtype: int64
DBSCAN 적용하기 – make_circles() 데이터 세트
from sklearn.datasets import make_circles X, y = make_circles(n_samples=1000, shuffle=True, noise=0.05, random_state=0, factor=0.5) clusterDF = pd.DataFrame(data=X, columns=['ftr1', 'ftr2']) clusterDF['target'] = y visualize_cluster_plot(None, clusterDF, 'target', iscenter=False)
# KMeans로 make_circles( ) 데이터 셋을 클러스터링 수행. from sklearn.cluster import KMeans kmeans = KMeans(n_clusters=2, max_iter=1000, random_state=0) kmeans_labels = kmeans.fit_predict(X) clusterDF['kmeans_cluster'] = kmeans_labels visualize_cluster_plot(kmeans, clusterDF, 'kmeans_cluster', iscenter=True)
# GMM으로 make_circles( ) 데이터 셋을 클러스터링 수행. from sklearn.mixture import GaussianMixture gmm = GaussianMixture(n_components=2, random_state=0) gmm_label = gmm.fit(X).predict(X) clusterDF['gmm_cluster'] = gmm_label visualize_cluster_plot(gmm, clusterDF, 'gmm_cluster', iscenter=False)
# DBSCAN으로 make_circles( ) 데이터 셋을 클러스터링 수행. from sklearn.cluster import DBSCAN dbscan = DBSCAN(eps=0.2, min_samples=10, metric='euclidean') dbscan_labels = dbscan.fit_predict(X) clusterDF['dbscan_cluster'] = dbscan_labels visualize_cluster_plot(dbscan, clusterDF, 'dbscan_cluster', iscenter=False)
'머신러닝 & 딥러닝' 카테고리의 다른 글
[텍스트] 20개의 뉴스 그룹으로 분류하기 (0) 2021.11.28 [텍스트] 텍스트 분석 (Text Tokenization & CountVectorizer) (0) 2021.11.23 [군집화] Mean Shift (0) 2021.11.03 [군집화] K-Means (0) 2021.11.02 [군집화] Clustering 기본 개념 (0) 2021.11.01