[Python] DBSCAN 클러스터(Clustering) 구현하기

    이번 포스팅은 DBSCAN 클러스터링을 구현하는 내용이며, DBSCAN에 대해서 이해를 하고 싶을 경우 이전에 작성한 포스팅을 참고하면 좋을 것 같다.

     

     

     

    DBSCAN clustering 이해하기

    DBSCAN의 개념 DBSCAN은 Density-Based Spatial Clustering of Applications with Noise의 약자로, 한국말로 풀이하면 노이즈를 적용한 밀도 기반 공간 클러스터링이라고 해석할 수 있다. 한마디로 Density-Based..

    needjarvis.tistory.com

     

    본 포스팅에 있는 코드는 IBM의 코세라(coursera) 강의 내용과 사이킷런의 데모 페이지의 코드를 섞어서 만든 예제이다.

     

    DBSCAN 클러스터링 예제

    라이브러리

    import numpy as np
    from sklearn.cluster import DBSCAN
    from sklearn import metrics
    from sklearn.datasets import make_blobs
    from sklearn.preprocessing import StandardScaler
    import matplotlib.pyplot as plt

    라이브러리는 make_blobs을 사용하여, 좌표 샘플들을 만들어 내고 전처리 과정에 스케일러를 사용하였다. 그리고 클러스터링의 성능을 측정하기 위해 metrics를 라이브러리에 추가하였다.

     

    샘플생성

    # Generate sample
    centers = [[1, 1], [-1, -1], [1, -1]]
    X, y = make_blobs(
        n_samples=750, centers=centers, cluster_std=0.4, random_state=0
    )
    
    X = StandardScaler().fit_transform(X)

     

    학습 수행

    epsilon = 0.3   # R와 역할, 반지름 지정
    minimumSamples = 7  # 최소 7개 요소
    db = DBSCAN(eps=epsilon, min_samples=minimumSamples).fit(X)
    labels = db.labels_

    반지름 역할 즉, Radius를 설정하는 epsilon과 core point의 기준이 되는 minimumSamples을 지정한다.

     

    eps는 float으로 설정해야 하며, default 값은 0.5이다.
    min_samples의 경우 default값은 5이다. 

     

     

    레이블의 값을 bool 배열로 변경

    # db의 레이블을 사용하여 bool 배열을 생성, outlier는 False로 변경
    core_samples_mask = np.zeros_like(db.labels_, dtype=bool)
    core_samples_mask[db.core_sample_indices_] = True

    K-means와 다르게 outlier를 찾아내기 때문에, bool 배열로 변경하는 과정이 존재한다.

     

    DBSCAN 성능 평가

    # 레이블에 있는 클러스터 수, 노이즈가 있을 경우 무시
    n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0)
    n_noise = list(labels).count(-1)
    print('n_clusters_->', n_clusters_)
    print('noise count->', n_noise)
    print('Homogeneity-> %0.3f' % metrics.homogeneity_score(y, labels))   # 동질성
    print("Completeness: %0.3f" % metrics.completeness_score(y, labels))  # 완전성

    DBSCAN의 분류 성능을 검증하기 위해 클러스터 개수와 노이즈 개수 그리고 metrics를 호출하여 검증을 해봤다.

     

    성능 평가 실행결과

    n_clusters_-> 3
    noise count-> 13
    Homogeneity-> 0.948
    Completeness: 0.892

     

    시각화(Visualization)

    # 레이블 반복을 set으로 변환후 제거
    unique_labels = set(labels)
    
    # 클러스터들의 색상 부여
    colors = plt.cm.Spectral(np.linspace(0, 1, len(unique_labels)))
    
    # DB스캔 Visualization
    for k, col in zip(unique_labels, colors):
        if k == -1:
            # Black used for noise.
            col = 'k'
    
        class_member_mask = (labels == k)
    
        # 클러스터들의 데이터를 화면에 그린다.
        xy = X[class_member_mask & core_samples_mask]
        plt.scatter(xy[:, 0], xy[:, 1], s=50, c=[col], marker=u'o', alpha=0.5)
    
        # Outlier를 그린다.
        xy = X[class_member_mask & ~core_samples_mask]
        plt.scatter(xy[:, 0], xy[:, 1], s=50, c=[col], marker=u'o', alpha=0.5)
    
    plt.show()

     

    시각화 결과

    DBSCAN의 실행 결과

     

    위 시각화 결과를 보면 클러스터에 멀어진 검정색 noise point들이 보일 것이다. 예를 들어, 노란색 클러스터와 초록색 클러스터 사이에 있는 point는 어느 클러스터에 속해야 할지 애매해 질 수 있는데 이럴 땐 noise point=outlier로 처리하는 것이 어떻게든 클러스터로 만드는 다른 클러스터(ex: K-means) 알고리즘과는 다른 점이다.

     

     

    최종소스

    import numpy as np
    from sklearn.cluster import DBSCAN
    from sklearn import metrics
    from sklearn.datasets import make_blobs
    from sklearn.preprocessing import StandardScaler
    import matplotlib.pyplot as plt
    
    
    # Generate sample
    centers = [[1, 1], [-1, -1], [1, -1]]
    X, y = make_blobs(
        n_samples=750, centers=centers, cluster_std=0.4, random_state=0
    )
    
    X = StandardScaler().fit_transform(X)
    
    epsilon = 0.3   # R와 역할, 반지름 지정
    minimumSamples = 7  # 최소 7개 요소
    db = DBSCAN(eps=epsilon, min_samples=minimumSamples).fit(X)
    labels = db.labels_
    
    # 클러스터 레이블값
    print('labels->', labels)
    
    
    # db의 레이블을 사용하여 bool 배열을 생성, outlier는 False로 변경
    core_samples_mask = np.zeros_like(db.labels_, dtype=bool)
    core_samples_mask[db.core_sample_indices_] = True
    print('core_samples_mask->', core_samples_mask)
    
    # 레이블에 있는 클러스터 수, 노이즈가 있을 경우 무시
    n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0)
    n_noise = list(labels).count(-1)
    print('n_clusters_->', n_clusters_)
    print('noise count->', n_noise)
    print('Homogeneity-> %0.3f' % metrics.homogeneity_score(y, labels))   # 동질성
    print("Completeness: %0.3f" % metrics.completeness_score(y, labels))  # 완전성
    
    
    # 레이블 반복을 set으로 변환후 제거
    unique_labels = set(labels)
    
    # 클러스터들의 색상 부여
    colors = plt.cm.Spectral(np.linspace(0, 1, len(unique_labels)))
    
    # DB스캔 Visualization
    for k, col in zip(unique_labels, colors):
        if k == -1:
            # Black used for noise.
            col = 'k'
    
        class_member_mask = (labels == k)
    
        # 클러스터들의 데이터를 화면에 그린다.
        xy = X[class_member_mask & core_samples_mask]
        plt.scatter(xy[:, 0], xy[:, 1], s=50, c=[col], marker=u'o', alpha=0.5)
    
        # Outlier를 그린다.
        xy = X[class_member_mask & ~core_samples_mask]
        plt.scatter(xy[:, 0], xy[:, 1], s=50, c=[col], marker=u'o', alpha=0.5)
    
    plt.show()

     

    연관포스팅

    DBSCAN clustering 이해하기

    K-means clustering 구현하기

    KNN(k최근접) 알고리즘 설명 및 구현하기

    References

    [1] sklearn - DBSCAN, https://scikit-learn.org/stable/modules/generated/sklearn.cluster.DBSCAN.html

    [2] coursera - Machine Learning with Python

    댓글

    Designed by JB FACTORY