1. 程式人生 > >機器學習之DBSCAN聚類

機器學習之DBSCAN聚類

  • 機器學習之DBSCAN聚類
# -*- coding: utf-8 -*-
"""
Created on Wed Nov 28 18:50:57 2018

@author: muli
"""

import numpy as np
from sklearn.datasets.samples_generator import make_blobs
from sklearn import  cluster
from sklearn.metrics import adjusted_rand_score
import matplotlib.pyplot as plt


def create_data(centers,num=100,std=0.7):
    '''
    生成用於聚類的資料集

    :param centers: 聚類的中心點組成的陣列。如果中心點是二維的,則產生的每個樣本都是二維的。
    :param num: 樣本數
    :param std: 每個簇中樣本的標準差
    :return: 用於聚類的資料集。是一個元組,第一個元素為樣本集,第二個元素為樣本集的真實簇分類標記
    '''
    X, labels_true = make_blobs(n_samples=num, centers=centers, cluster_std=std)
    return  X,labels_true


def test_DBSCAN(*data):
    '''
    測試 DBSCAN 的用法

    :param data:  可變引數。
    它是一個元組。元組元素依次為:第一個元素為樣本集,第二個元素為樣本集的真實簇分類標記
    :return: None
    '''
    X,labels_true=data
    print(X)
    print("*")
    print(len(labels_true))
    print("--------------------------")
    clst=cluster.DBSCAN()
    # 訓練模型並預測每個樣本所屬的簇標記
    predicted_labels=clst.fit_predict(X)
    # ARI 指數
    print("ARI:%s"% adjusted_rand_score(labels_true,predicted_labels))
    # 核心樣本在原始訓練集中的位置
    print(clst.core_sample_indices_)
    print("--------------------------")
    # 將原始資料集劃分為 len(X) 個 簇
    print("Core sample num:%d"%len(clst.core_sample_indices_))
    

def test_DBSCAN_epsilon(*data):
    '''
    測試 DBSCAN 的聚類結果隨  eps 引數的影響

    :param data:  可變引數。它是一個元組。元組元素依次為:第一個元素為樣本集,第二個元素為樣本集的真實簇分類標記
    :return: None
    '''
    X,labels_true=data
    epsilons=np.logspace(-1,1.5)
    ARIs=[]
    Core_nums=[]
    for epsilon in epsilons:
        clst=cluster.DBSCAN(eps=epsilon)
        predicted_labels=clst.fit_predict(X)
        ARIs.append( adjusted_rand_score(labels_true,predicted_labels))
        Core_nums.append(len(clst.core_sample_indices_))

    ## 繪圖
    fig=plt.figure()
    ax=fig.add_subplot(1,2,1)
    ax.plot(epsilons,ARIs,marker='+')
    ax.set_xscale('log')
    ax.set_xlabel(r"$\epsilon$")
    ax.set_ylim(0,1)
    ax.set_ylabel('ARI')

    ax=fig.add_subplot(1,2,2)
    ax.plot(epsilons,Core_nums,marker='o')
    ax.set_xscale('log')
    ax.set_xlabel(r"$\epsilon$")
    ax.set_ylabel('Core_Nums')

    fig.suptitle("DBSCAN")
    plt.show()


def test_DBSCAN_min_samples(*data):
    '''
    測試 DBSCAN 的聚類結果隨  min_samples 引數的影響

    :param data:  可變引數。它是一個元組。元組元素依次為:第一個元素為樣本集,第二個元素為樣本集的真實簇分類標記
    :return:  None
    '''
    X,labels_true=data
    min_samples=range(1,100)
    ARIs=[]
    Core_nums=[]
    for num in min_samples:
        clst=cluster.DBSCAN(min_samples=num)
        predicted_labels=clst.fit_predict(X)
        ARIs.append( adjusted_rand_score(labels_true,predicted_labels))
        Core_nums.append(len(clst.core_sample_indices_))

    ## 繪圖
    fig=plt.figure()
    ax=fig.add_subplot(1,2,1)
    ax.plot(min_samples,ARIs,marker='+')
    ax.set_xlabel( "min_samples")
    ax.set_ylim(0,1)
    ax.set_ylabel('ARI')

    ax=fig.add_subplot(1,2,2)
    ax.plot(min_samples,Core_nums,marker='*')
    ax.set_xlabel( "min_samples")
    ax.set_ylabel('Core_Nums')

    fig.suptitle("DBSCAN")
    plt.show()


if __name__=='__main__':
    centers=[[1,1],[2,2],[1,2],[10,20]] # 用於產生聚類的中心點
    X,labels_true=create_data(centers,1000,0.5) # 產生用於聚類的資料集
#    test_DBSCAN(X,labels_true) #  呼叫 test_DBSCAN 函式
#    test_DBSCAN_epsilon(X,labels_true) #  呼叫 test_DBSCAN_epsilon 函式
    test_DBSCAN_min_samples(X,labels_true) #  呼叫 test_DBSCAN_min_samples 函式