DBSCAN은 Density-Based Spatial Clustering of Applications with Noise은 준말로 데이터 포인트들을 밀도를 기반으로 군집화하여 노이즈 데이터를 탐지하는 이상치 탐지 기법이다. 데이터들이 많은 구역을 클러스터로 식별하고 밀도가 낮은 데이터들은 노이즈로 간주한다.
원리
1. 초기화
모든 데이터를 방문하지 않은 상태로 시작하여 각 데이터 포인트의 반지름 r 이내에 있는 다른 데이터 포인트의 수를 확인한다.
2. 클러스터 조건 확인
이 데이터 포인트를 중심으로 주변 이웃의 수가 최소 데이터 개수보다 큰 지를 확인하여 클러스터 핵심 포인트와 경계 포인트, 이상치를 구분한다. 핵심 포인트는 주변 이웃의 수가 최소 데이터 개수보다 큰 데이터 포인트이며, 이들을 기준으로 클러스터의 중심이 형성된다.
3. 이상치 분류
핵심 포인트의 이웃이지만 이웃의 수가 최소 포인트를 넘기지 못하는 데이터 포인트는 경계 포인트가 되며, 둘에 속하지 못하는 포인트들은 이상치로 분류된다.
적용할 만한 상황
사전에 클러스터의 수나 조건에 대해서 알지 못한다면 자동으로 클러스터링을 할 수 있기 때문에 DBSCAN이 효과적이다. 또한 DBSCAN은 밀도 기반이기 때문에 클러스터 형태가 불규칙하더라도 탐지해낼 수 있다.
차원의 저주로 인해 고차원에서는 성능이 떨어지는 현
상이 있다. 이런 경우에는 PCA와 같은 기법으로 차원을 축소하거나 적절한 거리 척도를 사용하여 데이터 간의 상대적인 거리를 더 잘 반영할 수 있다.
예제 코드

from sklearn.cluster import DBSCAN
from sklearn.preprocessing import StandardScaler
#DBSCAN 설정
dbscan = DBSCAN(eps=0.3, min_samples=3)
#스케일링 과정
features = ['feature1', 'feature2']
data_fixed = train[features]
scaler = StandardScaler()
data_scaled = scaler.fit_transform(data_fixed)
data_scanned = DBSCAN(eps=0.5, min_samples=3).fit(data_scaled)
#클러스터링 결과 확인
result = data_scanned.labels_
pd.Series(result).value_counts()
>> 1 83
>>-1 9
>> 0 4
>> 2 4
eps는 클러스터의 반경을 나타내고, min_samples는 클러스터의 핵심 포인트과 되기 위한 최소 이웃 수를 의미한다. 0 이상의 정수들은 각각 클러스터 무리를 의미한다. 1번째와 0번째 2번째 클러스터가 형성되었다. -1은 노이즈를 의미한다. 위의 데이터셋에서는 9개의 노이즈가 발견되었다. 아래는 DBSCAN을 적용한 결과를 시각화한 값이다.

다음은 스케일링 후 DBSCAN을 적용한 코드이다.
from sklearn.cluster import DBSCAN
from sklearn.preprocessing import StandardScaler
features = ['feature1', 'feature2']
data_fixed = train[features]
scaler = StandardScaler()
data_scaled = scaler.fit_transform(data_fixed)
dbscan = DBSCAN(eps=0.3, min_samples=3)
# fit_predict로 학습 후 클러스터 라벨 리턴
clusters_result = dbscan.fit_predict(data_scaled)
train['labels'] = clusters_result
train_x = train[train['labels'] != -1]
스케일링을 하게 되면 데이터에 큰 변화가 생기기 때문에 데이터의 변화를 고려해야한다.
번외. 클러스터링 시각화
import matplotlib.pyplot as plt
# 클러스터 라벨 가져오기
labels = clusters_result
# 고유 클러스터와 노이즈 확인
unique_labels = set(labels)
# 시각화
plt.figure(figsize=(8, 6))
# 각 클러스터별로 데이터 포인트를 그리기
for label in unique_labels:
if label == -1:
# 노이즈 데이터 (클러스터 라벨 -1)
color = 'k' # 검은색
label_name = 'Noise'
else:
# 클러스터 데이터
color = plt.cm.nipy_spectral(float(label) / len(unique_labels))
label_name = f'Cluster {label}'
# 클러스터 데이터 선택
class_member_mask = (labels == label)
cluster_data = data_scaled[class_member_mask]
# 산점도 그리기
plt.scatter(cluster_data[:, 0], cluster_data[:, 1], c=[color], label=label_name, s=50, alpha=0.7)
# 그래프 꾸미기
plt.title('DBSCAN Clustering Results')
plt.xlabel('Feature 1 (scaled)')
plt.ylabel('Feature 2 (scaled)')
plt.legend(loc='upper right', bbox_to_anchor=(1.15, 1))
plt.grid()
plt.show()
'머신러닝 > EDA' 카테고리의 다른 글
| [SNS] sns.scatterplot(), 산점도 (5) | 2024.12.28 |
|---|---|
| [EDA] Isolation Forest (4) | 2024.12.25 |
| [EDA] Z-score (6) | 2024.12.24 |
| [EDA] IQR(Interquartile Range, 사분범위) (3) | 2024.12.23 |
| [EDA] K-최근접 이웃(K-Nearest Neighbors, KNN) (1) | 2024.12.23 |