DBSCAN
- 두 가지 주요 파라미터인 epsilon ε (주변 반경)과 min_samples (최소 샘플 수)를 설정하여 군집을 형성
- 데이터의 지역적인 구조(지역적인 밀집 정도)를 이용
- 주변 데이터에서 멀어지는 데이터의 특징을 찾아서 분류하여 특이점을 발견
- 밀도가 낮은 지역의 데이터 포인트를 이상치로 간주

원리
- ε : 주변 반경
- min_samples : 핵심 포인트(Core Point) 판정 기준
ㄴ 최소 이웃의 수에 자기 자신을 포함한다.
ㄴ ex. 최소 이웃 수에 자기 자신을 포함하지 않고 코어 포인트가 되기 위한 이웃의 수가 9라면 10을 설정해야 한다.
1. 모든 포인트에 대해 ε 반경 안에 이웃이 몇 개 있는지 확인
2. 각 포인트를 3가지 유형으로 분류
| 유형 | 조건 | 역할 |
| Core Point | 주변 영역 내에 최소 데이터 개수 이상의 타 데이터를 가지고 있을 경우 이웃 수 ≥ min_samples |
군집의 중심 → 군집 확장 가능 |
| Border Point | 주변 영역 내에 최소 개수 이상의 이웃 포인터를 가지고 있지 않지만 핵심 포인트를 이웃으로 가짐 ε 반경 내 이웃 수 < min_samples |
군집의 경계, 확장 불가능 군집의 외곽을 형성 |
| Noise Point | 최소 데이터 개수 이상의 이웃 포인터를 가지고 있지 않으며, 핵심 포인트도 이웃 포인트로 가지고 있지 않음 어떤 Core Point의 이웃도 아님 |
군집에 속하지 않음 label = -1인 데이터 |
* Neighbor Point : 주변 영역 내에 위치한 타 데이터
- 군집 확장은 Core Point들 간의 연결성 으로 이루어짐
- Border Point는 군집에 속하지만 다른 Border Point와 직접 연결되어 군집을 만들 수 없음
3. Core Point에서 시작하여 직접 도달(Directly Reachable) 가능한 Core Point들을 계속 연결
→ 하나의 군집 형성
4. 연결이 끝나면 Core에 접한 Border Point를 해당 군집에 포함
하이퍼 파라미터
from sklearn.cluster import DBSCAN
DBSCAN(
eps=0.5,
min_samples=5,
metric='euclidean',
metric_params=None,
algorithm='auto',
leaf_size=30,
p=None,
n_jobs=None,
)
eps (epsilon)
- 두 샘플 사이가 이 값 이하일 때, 이웃(neighbor) 으로 간주
- 이는 클러스터 내 점들 간 거리의 최대값이 아니라, "이웃으로 인정하는 최대 반경"이다.
- 어떤 점을 기준으로 이 반경 안에 몇 개의 점이 있어야 밀집된 지역이라고 볼지를 결정하는 기준.
- 값이 작으면 → 촘촘하게 붙어 있어야 클러스터를 인정
- 값이 크면 → 넓게 퍼져 있어도 클러스터로 인정
- K-distance plot(Elbow 방식)로 eps 추정하는 것이 일반적
min_samples
- 어떤 점을 핵심(core) 포인트로 판단하기 위한 이웃 샘플의 최소 개수.
- 해당 점 자신도 포함된다.
ex. 최소 이웃 수에 자기 자신을 포함하지 않고 코어 포인트가 되기 위한 이웃의 수가 9라면 10을 설정해야 한다.
- 기준점 포함해서 min_samples 만큼 이웃이 있으면 그 점은 Core Point가 됨.
- min_samples가 크면 → 더 밀집된 군집만 인정
- min_samples가 작으면 → 작은 뭉치도 클러스터로 인식
- n_features × 2 정도 권장
metric
- 특징 벡터 간 거리를 계산할 때 사용할 거리(metric).
- sklearn.metrics.pairwise_distances 에서 허용되는 metric
- "precomputed"로 설정하면, 입력 X 를 거리 행렬로 간주하며 반드시 정방 행렬이어야 한다.
- 희소 행렬(sparse matrix)도 가능하며, 이 경우 "0이 아닌 값"만 이웃으로 고려될 수 있다.
- 기본값 : 'euclidean' (유클리드 거리), 'manhattan', 'cosine', custom_function 등도 가능
metric_params
- 거리 함수에 전달할 추가 파라미터
- ex. DBSCAN(metric=hamming, metric_params={"threshold":0.4})
algorithm
- {'auto', 'ball_tree', 'kd_tree', 'brute'}, optional
- brute : 거리 직접 계산
- NearestNeighbors 모듈이 거리 계산 및 최근접 이웃 탐색 시 사용할 알고리즘
leaf_size
- BallTree 또는 KDTree에 전달되는 리프 노드 크기
- 구축 및 탐색 속도, 메모리 사용에 영향을 준다.
- 최적의 값은 문제 특성에 따라 다르다.
- 트리 노드의 크기 조절 → 메모리, 계산시간 영향
p
- Minkowski 거리 계산 시의 지수값.
- metric='minkowski' 일 때만 의미 있음
- (euclidean=2, manhattan=1)
Attritbues
core_sample_indices_ : array, shape = [n_core_samples]
Indices of core samples.
components_ : array, shape = [n_core_samples, n_features]
Copy of each core sample found by training.
labels_ : array, shape = [n_samples]
Cluster labels for each point in the dataset given to fit().
Noisy samples are given the label -1.
core_sample_indices_ : array (n_core_samples)
- 핵심 포인트(core sample)의 인덱스.
components_ : array (n_core_samples, n_features)
- 훈련 시 발견된 핵심 샘플들의 복사본.
→ components_ == X[ core_sample_indices_ ]
labels_ : array (n_samples)
- 각 샘플의 클러스터 레이블
- 노이즈 포인트(noise)는 -1로 라벨링됨
K-distance Plot
- 적정한 eps를 찾는 휴리스틱 방법
- 그래프가 완만하다가 갑자기 급격히 증가하는 지점

metric=' precomputed'
다음 데이터로 DBSCAN을 실행해 보자.
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
# ---- 데이터 생성 ----
X, y = make_blobs(
n_samples=500,
centers=[(-5, -5), (0, 0), (5, 5)], # 3개의 클러스터
cluster_std=[0.5, 1.0, 0.3], # 클러스터 밀도 다르게
random_state=42
)
# 노이즈 추가
noise = np.random.uniform(low=-8, high=8, size=(40, 2))
X = np.vstack([X, noise])
# ---- 시각화 ----
plt.scatter(X[:, 0], X[:, 1], s=10)
plt.title("DBSCAN Test Data")
plt.show()

metric을 manhattan으로 설정하면 다음과 같은 결과를 얻을 수 있다.
from sklearn.cluster import DBSCAN
db = DBSCAN(eps=0.7, min_samples=5, metric='manhattan')
labels0 = db.fit_predict(X)
plt.scatter(X[:, 0], X[:, 1], c=labels0, s=10, cmap='tab10')
plt.title("DBSCAN Result")
plt.show()

precomputed 옵션을 사용하기 위해 커스텀 함수를 만들자.
def my_manhattan(u, v):
return np.sum(np.abs(u - v))
precumputed 옵션을 사용하면 pairwise_distances를 이용해서 정방 행렬을 만들어야 한다.
from sklearn.cluster import DBSCAN
from sklearn.metrics import pairwise_distances
db = DBSCAN(eps=0.7, min_samples=5, metric='precomputed')
dist = pairwise_distances(X, metric=my_manhattan)
labels1 = db.fit_predict(dist)
plt.scatter(X[:, 0], X[:, 1], c=labels1, s=10, cmap='tab10')
plt.title("DBSCAN Result")
plt.show()'개발 > Python' 카테고리의 다른 글
| K-Nearest Neighbors Hyper Parameters (0) | 2025.11.18 |
|---|---|
| RandomForest Hyper Parameters and Attributes (0) | 2025.11.16 |
| Distance Matrix (1) | 2025.11.15 |
| 불편추정량 (Unbiased Estimator) (0) | 2025.11.15 |
| Dictionary (0) | 2025.11.15 |
댓글