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

機器學習之kMeans聚類

  • 機器學習之kMeans聚類
# -*- coding: utf-8 -*-
"""
Created on Wed Nov 28 16:23:36 2018

@author: muli
"""

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_Kmeans(*data):
    '''
    測試 KMeans 的用法

    :param data: 可變引數。它是一個元組。元組元素依次為:第一個元素為樣本集,第二個元素為樣本集的真實簇分類標記
    :return: None
    '''
    X,labels_true=data
    clst=cluster.KMeans()
    # 訓練模型
    clst.fit(X)
    predicted_labels=clst.predict(X)
    # ARI指數
    print("ARI:%s"% adjusted_rand_score(labels_true,predicted_labels))
    # 所有樣本距離各簇中心點的距離之後
    print("Sum center distance %s"%clst.inertia_)


def test_Kmeans_nclusters(*data):
    '''
    測試 KMeans 的聚類結果隨 n_clusters 引數的影響

    :param data: 可變引數。它是一個元組。元組元素依次為:第一個元素為樣本集,第二個元素為樣本集的真實簇分類標記
    :return: None
    '''
    X,labels_true=data
    # 聚類中心的個數
    nums=range(1,50)
    ARIs=[]
    Distances=[]
    for num in nums:
        clst=cluster.KMeans(n_clusters=num)
        clst.fit(X)
        predicted_labels=clst.predict(X)
        ARIs.append(adjusted_rand_score(labels_true,predicted_labels))
        Distances.append(clst.inertia_)

    ## 繪圖
    fig=plt.figure()
    ax=fig.add_subplot(1,2,1)
    ax.plot(nums,ARIs,marker="+")
    ax.set_xlabel("n_clusters")
    ax.set_ylabel("ARI")
    
    ax=fig.add_subplot(1,2,2)
    ax.plot(nums,Distances,marker='o')
    ax.set_xlabel("n_clusters")
    ax.set_ylabel("inertia_")
    fig.suptitle("KMeans")
    plt.show()


def test_Kmeans_n_init(*data):
    '''
    測試 KMeans 的聚類結果隨 n_init 和 init  引數的影響

    :param data: 可變引數。它是一個元組。元組元素依次為:第一個元素為樣本集,第二個元素為樣本集的真實簇分類標記
    :return: None
    '''
    X,labels_true=data
    # 執行的次數
    nums=range(1,50)
    ## 繪圖
    fig=plt.figure()

    ARIs_k=[]
    Distances_k=[]
    ARIs_r=[]
    Distances_r=[]
    # 考慮 初始中心向量 和 執行次數 的影響
    for num in nums:
            clst=cluster.KMeans(n_init=num,init='k-means++')
            clst.fit(X)
            predicted_labels=clst.predict(X)
            ARIs_k.append(adjusted_rand_score(labels_true,predicted_labels))
            Distances_k.append(clst.inertia_)

            clst=cluster.KMeans(n_init=num,init='random')
            clst.fit(X)
            predicted_labels=clst.predict(X)
            ARIs_r.append(adjusted_rand_score(labels_true,predicted_labels))
            Distances_r.append(clst.inertia_)

    ax=fig.add_subplot(1,2,1)
    # 同一張圖中 作對比
    ax.plot(nums,ARIs_k,marker="+",label="k-means++")
    ax.plot(nums,ARIs_r,marker="+",label="random")
    ax.set_xlabel("n_init")
    ax.set_ylabel("ARI")
    ax.set_ylim(0,1)
    ax.legend(loc='best')
    ax=fig.add_subplot(1,2,2)
    # 同一張圖中 作對比
    ax.plot(nums,Distances_k,marker='o',label="k-means++")
    ax.plot(nums,Distances_r,marker='o',label="random")
    ax.set_xlabel("n_init")
    ax.set_ylabel("inertia_")
    ax.legend(loc='best')

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


if __name__=='__main__':
    # 用於產生聚類的中心點
    # 聚類中心是幾維,則特徵向量是幾維的
    centers=[[1,1],[2,2],[1,2],[10,20]] 
    # 產生用於聚類的資料集
    X,labels_true=create_data(centers,1000,0.5) 
    # plot_data(X,labels_true) # 繪製用於聚類的資料集
#    test_Kmeans(X,labels_true) #  呼叫 test_Kmeans 函式
#    test_Kmeans_nclusters(X,labels_true) #  呼叫 test_Kmeans_nclusters 函式
    test_Kmeans_n_init(X,labels_true) #  呼叫 test_Kmeans_n_init 函式