제퍼넷 로고

Python에서 Scikit-Learn을 사용한 DBSCAN

시간

개요

당신은 컨설팅 회사에서 데이터 과학자로 일하고 있습니다. 현재 할당된 프로젝트에는 최근에 재정 관련 과정을 마친 학생들의 데이터가 있습니다. 과정을 진행하는 금융 회사는 학생들이 동일한 과정을 구매하거나 다른 과정을 구매하는 데 영향을 미치는 공통 요인이 있는지 이해하려고 합니다. 회사는 이러한 요소를 이해함으로써 학생 프로필을 만들고 각 학생을 프로필별로 분류하고 코스 목록을 추천할 수 있습니다.

다른 학생 그룹의 데이터를 조사할 때 아래 1, 2 및 3과 같이 세 가지 포인트 배치를 발견했습니다.

플롯 1에는 보라색 점이 반원으로 구성되어 있고 그 원 안에 많은 분홍색 점이 있고 반원 외부에 약간의 주황색 점이 집중되어 있으며 다른 모든 점과 멀리 떨어져 있는 XNUMX개의 회색 점이 있습니다.

플롯 2에는 자주색 점의 둥근 덩어리, 주황색 점의 또 다른 점, 그리고 다른 모든 점과 멀리 떨어져 있는 XNUMX개의 회색 점이 있습니다.

그리고 플롯 3에서 보라색, 파란색, 주황색, 분홍색의 네 가지 점 집중과 세 개의 더 먼 회색 점을 볼 수 있습니다.

이제 신입생 데이터를 이해하고 유사한 그룹을 결정할 수 있는 모델을 선택한다면 그러한 종류의 데이터에 흥미로운 결과를 줄 수 있는 클러스터링 알고리즘이 있습니까?

플롯을 설명할 때 다음과 같은 용어를 언급했습니다. 점의 질량포인트 집중, 모든 그래프에 밀도가 더 높은 영역이 있음을 나타냅니다. 우리는 또한 참조 원형의반원형 직선을 그리거나 단순히 가장 가까운 점을 검사하는 것만으로는 식별하기 어려운 모양. 또한 주요 데이터 분포에서 벗어날 가능성이 있는 몇 가지 먼 지점이 있어 더 많은 문제가 발생하거나 소음 그룹을 결정할 때.

다음과 같은 노이즈를 필터링할 수 있는 밀도 기반 알고리즘 DBSCAN (D엔시 티Based SPatial C광택 A응용 프로그램 Noise)는 밀도가 높은 영역, 둥근 모양 및 노이즈가 있는 상황에 적합한 선택입니다.

DBSCAN 소개

DBSCAN은 연구에서 가장 많이 인용되는 알고리즘 중 하나이며, 1996년에 첫 번째 간행물이 나타납니다. 원본 DBSCAN 용지. 이 논문에서 연구자들은 알고리즘이 어떻게 비선형 공간 클러스터를 식별하고 더 높은 차원의 데이터를 효율적으로 처리할 수 있는지 보여줍니다.

DBSCAN의 기본 아이디어는 결정된 거리 또는 반지름 라고 하는 가장 "중앙" 클러스터 지점에서 핵심 포인트. 해당 반경 내의 점은 이웃 점이며 해당 이웃의 가장자리에 있는 점은 경계점 or 경계점. 반지름 또는 이웃 거리는 호출됩니다. 엡실론 이웃, ε-이웃 또는 ε (그리스 문자 엡실론 기호).

또한, 결정된 군집에 속하는 반지름을 초과하여 핵심점 또는 경계점이 아닌 점이 있고, 또한 핵심점이 되기 위한 최소한의 점이 없는 경우에도 해당 점을 고려한다. 노이즈 포인트.

즉, 세 가지 다른 유형의 포인트가 있습니다. core, 경계소음. 또한 주요 아이디어는 근본적으로 반지름 또는 거리를 기반으로 하므로 대부분의 클러스터링 모델과 마찬가지로 DBSCAN이 해당 거리 메트릭에 따라 달라집니다. 이 메트릭은 Euclidean, Manhattan, Mahalanobis 등이 될 수 있습니다. 따라서 데이터의 맥락을 고려한 적절한 거리 메트릭을 선택하는 것이 중요합니다. 예를 들어 GPS의 운전 거리 데이터를 사용하는 경우 맨해튼 거리와 같이 거리 레이아웃을 고려하는 메트릭을 사용하는 것이 흥미로울 수 있습니다.

참고 : DBSCAN은 노이즈를 구성하는 포인트를 매핑하기 때문에 이상값 탐지 알고리즘으로도 사용할 수 있습니다. 예를 들어 어떤 은행 거래가 사기일 수 있고 사기 거래 비율이 적은지 확인하려는 경우 DBSCAN은 이러한 지점을 식별하는 솔루션이 될 수 있습니다.

핵심 포인트를 찾기 위해 DBSCAN은 먼저 무작위로 포인트를 선택하고 ε-neighborhood 내의 모든 포인트를 매핑한 다음 선택한 포인트의 이웃 수를 최소 포인트 수와 비교합니다. 선택한 포인트가 최소 포인트 수보다 같거나 더 많은 이웃이 있는 경우 코어 포인트로 표시됩니다. 이 코어 포인트와 인접 포인트는 첫 번째 클러스터를 구성합니다.

그런 다음 알고리즘은 첫 번째 클러스터의 각 포인트를 검사하고 ε 내의 최소 포인트 수보다 이웃 포인트가 같거나 더 많은지 확인합니다. 그렇다면 해당 인접 포인트도 첫 번째 클러스터에 추가됩니다. 이 프로세스는 첫 번째 클러스터의 포인트가 ε 내의 최소 포인트 수보다 적은 이웃을 가질 때까지 계속됩니다. 그런 일이 발생하면 알고리즘은 해당 클러스터에 포인트 추가를 중지하고 해당 클러스터 외부의 다른 코어 포인트를 식별하고 해당 새 코어 포인트에 대한 새 클러스터를 생성합니다.

그런 다음 DBSCAN은 해당 클러스터에 더 이상 추가할 포인트가 없을 때까지 두 번째 클러스터의 새 코어 포인트에 연결된 모든 포인트를 찾는 첫 번째 클러스터 프로세스를 반복합니다. 그런 다음 다른 핵심 포인트를 만나 세 번째 클러스터를 생성하거나 이전에 살펴보지 않은 모든 포인트를 반복합니다. 이러한 점이 군집에서 ε 거리에 있으면 해당 군집에 추가되어 경계 점이 됩니다. 그렇지 않은 경우 노이즈 지점으로 간주됩니다.

조언: DBSCAN 이면의 아이디어에는 많은 규칙과 수학적 증명이 포함되어 있습니다. 더 깊이 파고들고 싶다면 위에 링크된 원본 논문을 살펴보는 것이 좋습니다.

DBSCAN 알고리즘이 어떻게 작동하는지 아는 것은 흥미롭지만 다행스럽게도 Python의 Scikit-Learn 라이브러리에 이미 구현이 있으면 알고리즘을 코딩할 필요가 없습니다.

실제로 어떻게 작동하는지 봅시다!

클러스터링을 위한 데이터 가져오기

DBSCAN이 실제로 어떻게 작동하는지 확인하기 위해 프로젝트를 약간 변경하고 200명의 고객에 대한 장르, 연령, 연간 소득 및 지출 점수가 있는 작은 고객 데이터 세트를 사용합니다.

지출 점수의 범위는 0에서 100까지이며, 1에서 100까지의 척도로 쇼핑몰에서 얼마나 자주 돈을 쓰는지를 나타냅니다. 즉, 고객의 점수가 0이면 절대 돈을 쓰지 않으며 점수가 100, 그들은 가장 높은 지출자입니다.

참고 : 데이터 세트를 다운로드할 수 있습니다. 여기에서 지금 확인해 보세요..

데이터 세트를 다운로드하면 CSV(쉼표로 구분된 값) 파일이라는 것을 알 수 있습니다. 쇼핑 데이터.csv, Pandas를 사용하여 DataFrame에 로드하고 customer_data 변하기 쉬운:

import pandas as pd path_to_file = '../../datasets/dbscan/dbscan-with-python-and-scikit-learn-shopping-data.csv'
customer_data = pd.read_csv(path_to_file)

데이터의 처음 XNUMX개 행을 보려면 다음을 실행할 수 있습니다. customer_data.head():

결과 :

 CustomerID Genre Age Annual Income (k$) Spending Score (1-100)
0 1 Male 19 15 39
1 2 Male 21 15 81
2 3 Female 20 16 6
3 4 Female 23 16 77
4 5 Female 31 17 40

데이터를 검토하여 고객 ID 번호, 장르, 연령, k$ 수입 및 지출 점수를 확인할 수 있습니다. 이러한 변수 중 일부 또는 전부가 모델에서 사용된다는 점을 명심하십시오. 예를 들어, AgeSpending Score (1-100) 거리 측정법을 사용하는 DBSCAN의 변수로 왜곡을 방지하기 위해 공통 척도로 가져오는 것이 중요합니다. Age 년 단위로 측정되며 Spending Score (1-100) 0에서 100까지의 제한된 범위를 가집니다. 이것은 일종의 데이터 스케일링을 수행할 것임을 의미합니다.

또한 데이터 유형이 일관성이 있는지 확인하고 Panda의 info() 방법:

customer_data.info()

다음이 표시됩니다.

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 200 entries, 0 to 199
Data columns (total 5 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 CustomerID 200 non-null int64 1 Genre 200 non-null object 2 Age 200 non-null int64 3 Annual Income (k$) 200 non-null int64 4 Spending Score (1-100) 200 non-null int64 dtypes: int64(4), object(1)
memory usage: 7.9+ KB

각 고객 기능에 대해 null이 아닌 항목이 200개 있기 때문에 누락된 값이 없음을 관찰할 수 있습니다. 또한 장르 열은 범주형 변수이므로 다음과 같이 표시되는 장르 열에만 텍스트 콘텐츠가 있음을 알 수 있습니다. object, 기타 모든 기능은 유형의 숫자입니다. int64. 따라서 데이터 유형의 일관성과 null 값이 없다는 점에서 데이터를 추가로 분석할 준비가 되었습니다.

계속해서 데이터를 시각화하고 DBSCAN에서 사용하기에 흥미로운 기능을 결정할 수 있습니다. 이러한 기능을 선택한 후 확장할 수 있습니다.

이 고객 데이터 세트는 계층적 클러스터링에 대한 최종 가이드에서 사용된 것과 동일합니다. 이 데이터, 탐색 방법 및 거리 메트릭에 대해 자세히 알아보려면 다음을 살펴보십시오. Python 및 Scikit-Learn을 사용한 계층적 클러스터링에 대한 최종 가이드!

데이터 시각화

씨본즈를 이용하여 pairplot(), 각 기능 조합에 대한 산포 그래프를 그릴 수 있습니다. 부터 CustomerID 기능이 아니라 식별일 뿐이므로 다음과 같이 제거합니다. drop() 플로팅하기 전에:

import seaborn as sns customer_data = customer_data.drop('CustomerID', axis=1) sns.pairplot(customer_data);

이 결과는 다음과 같습니다.

에 의해 생성된 기능의 조합을 볼 때 pairplot, 그래프 Annual Income (k$)Spending Score (1-100) 약 5개의 포인트 그룹을 표시하는 것 같습니다. 이것은 가장 유망한 기능 조합 인 것 같습니다. 이름으로 목록을 만들고 목록에서 선택할 수 있습니다. customer_data DataFrame에 저장하고 선택 항목을 customer_data 향후 모델에서 사용하기 위해 다시 변수.

selected_cols = ['Annual Income (k$)', 'Spending Score (1-100)']
customer_data = customer_data[selected_cols]

열을 선택한 후 이전 섹션에서 설명한 크기 조정을 수행할 수 있습니다. 기능을 동일한 배율로 가져오거나 표준화하다 Scikit-Learn's를 가져올 수 있습니다. StandardScaler, 생성하고 데이터에 맞춰 평균과 표준편차를 계산한 다음 평균을 빼고 표준편차로 나누어 데이터를 변환합니다. 이것은 다음과 같이 한 단계로 수행할 수 있습니다. fit_transform() 방법:

from sklearn.preprocessing import StandardScaler ss = StandardScaler() scaled_data = ss.fit_transform(customer_data)

이제 변수의 크기가 조정되었으며 단순히 scaled_data 변하기 쉬운. 또는 새 항목에 추가할 수도 있습니다. scaled_customer_data 열 이름과 함께 DataFrame을 사용하고 head() 다시 방법:

scaled_customer_data = pd.DataFrame(columns=selected_cols, data=scaled_data)
scaled_customer_data.head()

이 결과는 다음과 같습니다.

 Annual Income (k$) Spending Score (1-100)
0 -1.738999 -0.434801
1 -1.738999 1.195704
2 -1.700830 -1.715913
3 -1.700830 1.040418
4 -1.662660 -0.395980 

이 데이터는 클러스터링할 준비가 되었습니다! DBSCAN을 도입할 때 최소 포인트 수와 엡실론을 언급했습니다. 이 두 값은 모델을 생성하기 전에 선택해야 합니다. 어떻게 되는지 봅시다.

최소 선택 샘플 및 엡실론

DBSCAN 클러스터링을 위한 최소 포인트 수를 선택하려면 다음과 같이 데이터의 차원 수에 XNUMX을 더한 값보다 크거나 같아야 한다는 경험 법칙이 있습니다.

$$
텍스트{분. 포인트} >= 텍스트{데이터 치수} + 1
$$

차원은 데이터 프레임의 열 수이며 2개 열을 사용하므로 최소값입니다. 포인트는 2+1, 즉 3 이상이어야 합니다. 이 예에서는 다음을 사용하겠습니다. 5 분. 포인트들.

$$
text{5(최소 포인트)} >= text{2(데이터 차원)} + 1
$$

모범 사례, 업계에서 인정하는 표준 및 포함된 치트 시트가 포함된 Git 학습에 대한 실습 가이드를 확인하십시오. 인터넷 검색 Git 명령을 중지하고 실제로 배움 이것!

이제 ε 값을 선택하기 위해 다음과 같은 방법이 있습니다. 가장 가까운 이웃 알고리즘은 각 점에 대해 미리 정의된 가장 가까운 점의 거리를 찾는 데 사용됩니다. 이 사전 정의된 이웃 수는 최소입니다. 우리는 방금 빼기 1을 선택한 포인트입니다. 따라서 우리의 경우 알고리즘은 데이터의 각 포인트에 대해 5-1 또는 4개의 가장 가까운 포인트를 찾습니다. 그것들은 k-이웃 & k 4과 같습니다.

$$
text{k-이웃} = text{min. 포인트} – 1
$$

이웃을 찾은 후 가장 큰 것부터 가장 작은 것까지의 거리를 정렬하고 y축의 거리와 x축의 점을 플로팅합니다. 플롯을 보면 팔꿈치의 굽힘과 유사한 위치와 팔꿈치 굽힘을 설명하는 y축 점이 제안된 ε 값임을 알 수 있습니다.

주의 사항: ε 값을 찾기 위한 그래프에 크거나 작은 하나 이상의 "팔꿈치 굽힘"이 있을 수 있습니다. 그럴 때 값을 찾고 테스트하고 클러스터를 가장 잘 설명하는 결과가 있는 값을 선택할 수 있습니다. 플롯의 메트릭을 살펴봄으로써.

이러한 단계를 수행하기 위해 알고리즘을 가져와서 데이터에 맞춘 다음 다음을 사용하여 각 점의 거리와 인덱스를 추출할 수 있습니다. kneighbors() 방법:

from sklearn.neighbors import NearestNeighbors
import numpy as np nn = NearestNeighbors(n_neighbors=4) nbrs = nn.fit(scaled_customer_data)
distances, indices = nbrs.kneighbors(scaled_customer_data)

거리를 찾은 후 가장 큰 것부터 가장 작은 것까지 정렬할 수 있습니다. distances 배열의 첫 번째 열은 자신에 대한 점(모두 0임을 의미)이고 두 번째 열은 가장 작은 거리를 포함하고 두 번째 열보다 거리가 더 큰 세 번째 열이 이어지는 식으로 다음 열만 선택할 수 있습니다. 두 번째 열의 값을 다음 위치에 저장합니다. distances 변하기 쉬운:

distances = np.sort(distances, axis=0)
distances = distances[:,1] 

이제 가장 작은 거리를 정렬했으므로 가져올 수 있습니다. matplotlib, 거리를 플롯하고 "팔꿈치 굽힘"이 있는 위치에 빨간색 선을 그립니다.

import matplotlib.pyplot as plt plt.figure(figsize=(6,3))
plt.plot(distances)
plt.axhline(y=0.24, color='r', linestyle='--', alpha=0.4) plt.title('Kneighbors distance graph')
plt.xlabel('Data points')
plt.ylabel('Epsilon value')
plt.show();

결과는 다음과 같습니다.

선을 그릴 때 ε 값을 알 수 있습니다. 이 경우에는 0.24.

마침내 최소 포인트와 ε을 얻었습니다. 두 변수를 모두 사용하여 DBSCAN 모델을 생성하고 실행할 수 있습니다.

DBSCAN 모델 생성

모델을 생성하기 위해 Scikit-Learn에서 가져와서 모델과 동일한 ε으로 생성할 수 있습니다. eps 인수 및 최소 포인트는 mean_samples 논쟁. 그런 다음 변수에 저장할 수 있습니다. dbs 스케일링된 데이터에 맞춥니다.

from sklearn.cluster import DBSCAN dbs = DBSCAN(eps=0.24, min_samples=5)
dbs.fit(scaled_customer_data)

그렇게 DBSCAN 모델이 생성되고 데이터에 대해 훈련되었습니다! 결과를 추출하기 위해 우리는 labels_ 재산. 우리는 또한 새로운 labelsscaled_customer_data 데이터 프레임을 만들고 예측 레이블로 채웁니다.

labels = dbs.labels_ scaled_customer_data['labels'] = labels
scaled_customer_data.head()

최종 결과는 다음과 같습니다.

 Annual Income (k$) Spending Score (1-100) labels
0 -1.738999 -0.434801 -1
1 -1.738999 1.195704 0
2 -1.700830 -1.715913 -1
3 -1.700830 1.040418 0
4 -1.662660 -0.395980 -1

다음과 같은 레이블이 있음을 관찰하십시오. -1 값; 이들은 노이즈 포인트, 어떤 클러스터에도 속하지 않는 것들. 알고리즘이 찾은 노이즈 포인트 수를 알기 위해 레이블 목록에 값 -1이 몇 번 나타나는지 계산할 수 있습니다.

labels_list = list(scaled_customer_data['labels'])
n_noise = labels_list.count(-1)
print("Number of noise points:", n_noise)

이 결과는 다음과 같습니다.

Number of noise points: 62

우리는 이미 62포인트의 원래 데이터 중 200포인트가 노이즈로 간주되었음을 알고 있습니다. 이는 잡음이 많기 때문에 DBSCAN 클러스터링이 클러스터의 일부로 많은 포인트를 고려하지 않았을 수 있음을 나타냅니다. 데이터를 플롯하면 곧 무슨 일이 일어났는지 이해하게 될 것입니다.

처음에 데이터를 관찰했을 때 5개의 포인트 클러스터가 있는 것 같았습니다. DBSCAN이 얼마나 많은 클러스터를 형성했는지 알기 위해 -1이 아닌 레이블 수를 셀 수 있습니다. 해당 코드를 작성하는 방법에는 여러 가지가 있습니다. 여기에서 DBSCAN이 많은 클러스터를 찾은 데이터에 대해서도 작동하는 for 루프를 작성했습니다.

total_labels = np.unique(labels) n_labels = 0
for n in total_labels: if n != -1: n_labels += 1
print("Number of clusters:", n_labels)

이 결과는 다음과 같습니다.

Number of clusters: 6

알고리즘이 데이터에 많은 노이즈 포인트가 있는 6개의 클러스터가 있다고 예측했음을 알 수 있습니다. seaborn's로 플로팅하여 시각화해 봅시다. scatterplot:

sns.scatterplot(data=scaled_customer_data, x='Annual Income (k$)', y='Spending Score (1-100)', hue='labels', palette='muted').set_title('DBSCAN found clusters');

결과 :

플롯을 보면 DBSCAN이 더 조밀하게 연결된 포인트를 캡처했으며 동일한 클러스터의 일부로 간주될 수 있는 포인트가 노이즈이거나 다른 작은 클러스터를 형성하는 것으로 간주되었음을 알 수 있습니다.

클러스터를 강조 표시하면 DBSCAN이 포인트 사이의 공간이 적은 클러스터인 클러스터 1을 완전히 가져오는 방법을 알 수 있습니다. 그런 다음 더 많은 간격을 노이즈로 간주하여 포인트가 밀접하게 함께 있는 클러스터 0과 3의 일부를 가져옵니다. 또한 왼쪽 하단 절반에 있는 점을 노이즈로 간주하고 오른쪽 하단에 있는 점을 3개의 클러스터로 분할하여 다시 한 번 포인트가 더 가까운 클러스터 4, 2 및 5를 캡처합니다.

우리는 DBSCAN이 클러스터의 밀집된 영역을 캡처하는 데는 훌륭하지만 데이터의 더 큰 체계인 5개 클러스터의 구분을 식별하는 데는 그리 많지 않다는 결론에 도달하기 시작할 수 있습니다. 데이터로 더 많은 클러스터링 알고리즘을 테스트하는 것이 흥미로울 것입니다. 측정항목이 이 가설을 뒷받침하는지 살펴보겠습니다.

알고리즘 평가

DBSCAN을 평가하기 위해 다음을 사용합니다. 실루엣 점수 동일한 군집의 점 사이의 거리와 군집 사이의 거리를 고려합니다.

참고 : 현재 대부분의 클러스터링 메트릭은 밀도를 기반으로 하지 않기 때문에 DBSCAN을 평가하는 데 사용하기에 적합하지 않습니다. 여기서 실루엣 점수는 이미 Scikit-learn에 구현되어 있고 클러스터 모양을 보려고 하기 때문에 사용합니다.

보다 적합한 평가를 받으려면 다음과 함께 사용하거나 결합할 수 있습니다. 밀도 기반 클러스터링 검증 (DBCV) 메트릭은 밀도 기반 클러스터링을 위해 특별히 설계되었습니다. 이것에서 사용 가능한 DBCV에 대한 구현이 있습니다. GitHub의.

먼저 가져올 수 있습니다. silhouette_score 그런 다음 Scikit-Learn에서 열과 레이블을 전달합니다.

from sklearn.metrics import silhouette_score s_score = silhouette_score(scaled_customer_data, labels)
print(f"Silhouette coefficient: {s_score:.3f}")

이 결과는 다음과 같습니다.

Silhouette coefficient: 0.506

이 점수에 따르면 DBSCAN은 데이터의 약 50%를 캡처할 수 있는 것으로 보입니다.

결론

DBSCAN 장점 및 단점

DBSCAN은 매우 독특한 클러스터링 알고리즘 또는 모델입니다.

장점을 보자면 데이터의 밀집된 부분과 남들과 거리가 먼 포인트를 잘 뽑는다. 이는 데이터가 특정 모양을 가질 필요가 없으며 밀도가 높으면 다른 점으로 둘러싸일 수 있음을 의미합니다.

최소 포인트와 ε을 지정해야 하지만 예를 들어 K-Means와 같이 미리 클러스터 수를 지정할 필요가 없습니다. 고차원 데이터용으로 설계되었기 때문에 매우 큰 데이터베이스에서도 사용할 수 있습니다.

단점으로는 동일한 클러스터에서 서로 다른 밀도를 캡처할 수 없기 때문에 밀도 차이가 커서 어려움을 겪는 것을 보았습니다. 또한 점의 거리 메트릭 및 배율에 따라 달라집니다. 즉, 데이터가 잘 이해되지 않고 규모의 차이와 이해가 되지 않는 거리 메트릭이 있는 경우 데이터를 이해하지 못할 수 있습니다.

DBSCAN 확장

다음과 같은 다른 알고리즘이 있습니다. 계층적 DBSCAN(HDBSCAN)클러스터링 구조를 식별하기 위한 주문 포인트(OPTICS), DBSCAN의 확장으로 간주됩니다.

HDBSCAN과 OPTICS는 일반적으로 데이터에 다양한 밀도의 클러스터가 있을 때 더 잘 수행할 수 있으며 선택 또는 초기 최소값에 덜 민감합니다. 포인트 및 ε 매개변수.

spot_img

최신 인텔리전스

spot_img