5.聚類算法k-means

聚類與分類的區別在於,是在沒有給定劃分類別的狀況下,更具數據類似度進行樣本分組的一種辦法,是一種非監督的學習算法,聚類的輸入時一組未被標記的樣本,聚類更具數據自身的距離或者類似度將其劃分爲若干組,劃分的原則是組內距離最小化,而組間(外部)距離最大化。python

聚類中的k-means算法算法

1. k-means工做過程:數組

  下述圖片均來自網絡網絡

  

  

 

  (a)表示兩類點dom

  (b)表示隨機選取兩個點做爲中心點函數

  (c)表示測點上述兩類點到咱們在(b)中隨機選定的紅色×和藍色×之間的距離,離哪一個中心點近就歸爲相應的類別,在(c)中咱們就已經將上述兩類點進行分爲兩類學習

  (d)在上述c的基礎上利用紅色圓點從新計算紅色類的中心點,藍色同理就會獲得如(d)圖所示的紅×與藍×,此時中心點即獲得了一次更新測試

  (e)以(d)中肯定的中心點再次計算全部樣本點到(d)中心點的距離,離哪一個中性點近就歸爲相應類別即獲得了(e)中的分類效果spa

  (f)和(d)一樣的方式再次利用新的類別的樣本點更新中心點3d

  如上述步驟:不斷迭代直至聚類的中心點不在發生變化,或者每一個樣本到對應聚類中心的距離之和再也不有很大變化便可中止,聚類任務結束

  

2. k-means算法注意點

  2.1 咱們在初始化聚類中心時,有以下兩種辦法:

  (1)隨機初始化k個和樣本點維度相同的向量

  (2)隨機在選擇k個不一樣的樣本點做爲初始的聚類中心

  咱們所選定的初始聚類中心會對咱們模型最終的聚類結果有必定的影響,咱們能夠經過下述方法,將初始聚類中心對聚類結果的影響程度最小

  (1)屢次初始化,最終參考屢次運行的結果取平均

  (2)在樣本點中選擇初始聚類中心時,使得所選擇的聚類中心之間離的儘可能遠

  2.2 在面對一些問題的時候,咱們並不知道它們的類別,因此k值的肯定相當重要

    

  如上圖,能夠知道k值選擇不合適,聚類的結果每每是沒有意義的,故咱們要選擇不一樣的k值進行測試

  2.3 k-means聚類的侷限性

  以下圖所示,此類樣本點,k-means沒法完成準確聚類,此類樣本分佈規律,咱們能夠用DBSCAN算法(即基於高密度鏈接區域)進行聚類

  

3. k-means原理的python代碼實現過程以下:

import numpy as np
import matplotlib.pyplot as plt

from sklearn.datasets.samples_generator import make_blobs
'''
利用sklearn隨機生成數據,這裏注意利用make_blobs生成的本來爲分類問題,在此處咱們忽略標記y,只考慮X
即爲一個聚類問題
'''
X,y = make_blobs(n_samples=50,centers=2,random_state=0,cluster_std=0.5)
# 經過觀察散點圖,上下各爲一個類別
plt.scatter(X[:,0],X[:,1])

# 聚類前樣本點的散點圖
# 測量歐式距離,對樣本點依據中心點分類
def sample_classify(sample_data,centerPoint):
    '''
    sample_classify:計算全部樣本點到中心點的距離,並對樣本點進行分類
    參數:sample_data:某同樣本點數據
         centerpoint:k-means算法中心點     
    '''
    # 計算樣本數據到第一個中心點的歐氏距離
    mindist = np.linalg.norm(sample_data-centerPoint[0,:-1])
    # n 表示中心點的個數
    n = centerPoint.shape[0]
    # lagel表示中心點所表明的類別
    label = centerPoint[0,-1]
    for i in range(1,n):
        # 計算樣本點到剩餘中心點的歐式距離
        dist = np.linalg.norm(sample_data-centerPoint[i,:-1])
        # 比較剩餘中心點到樣本距離與第一個中心點到樣本點的距離
        if dist < mindist:
            mindist = dist
            label = centerPoint[i,-1]
    # 返回類別
    return label    

# 定義模型中止策略
def interation_stop(iterations,centerPoint,oldcenterPoint,maxIt):
    '''
    interation_stop:定義中止策略,1.迭代次數到達設定值,2.中心點不在移動
    參數:iterations:迭代次數
         centerPoint:本次中心點
         oldcenterPoint:上次中心點
         maxIt:預設的迭代次數
    '''
    # 當迭代次數大於或者等於咱們預設的迭代次數時中止
    if iterations >= maxIt:
        print('-------------')
        return True
    # 判斷兩次中心點是否相等
    return np.array_equal(oldcenterPoint, centerPoint)  

# 更新中心點
def get_centerPoint(dataSet,k):
    '''
    get_centerPoint:更新中心點,當數據被分好類之後,根據已經分好類的數據從新計算中心點,而後再次重複以上的步驟對數據進行
    參數:dataSet:已經通過聚類的數據集
         k:類別個數
    '''
    #初始化一個k行,數據維度列的一個array
    result = np.zeros((k,dataSet.shape[1]))
    for i in range(1,k+1):
        # 找出同一類別的數據
        oneCluster = dataSet[dataSet[:,-1]==i,:-1]
        # 計算同一類別數據各個維度的均值,即計算出新的中心點
        result[i-1,:-1] = np.mean(oneCluster,axis=0)
        # 給定類別
        result[i-1,-1] = i
    return result    

def main():
    #orig_data = np.array([[1,1],[2,1],[4,3],[5,4]])
    # 初始化數據
    orig_data = X
    # 將數據形式又array轉化成matrix
    data = np.mat(orig_data)
    # 初始化k值即類別
    k = 2
    # num表示樣本個數,dim表示每個樣本的維度
    num,dim = data.shape
    # 初始化一個新的數組用於存放原數據與對應類別
    dataSet = np.zeros((num,dim+1))
    # 將原始數據填入新的數據
    dataSet[:,:-1] = data
    # 隨機選取的中心點
    centerPoint = dataSet[np.random.randint(num,size=k),:]
    centerPoint[:,-1] = range(1,k+1)
    oldcenterPoint = None
    iterations = 0
    # 指定迭代次數
    maxIt = 1000
    # 中止策略未false時循環
    while not interation_stop(iterations,centerPoint,oldcenterPoint,maxIt):
        for i in range(num):
            # 取出樣本點
            sample_data = dataSet[i,:-1]
            # 利用以前定義好的函數計算每個樣本點到中心點距離,並對樣本點進行分類
            dataSet[i,-1] = sample_classify(sample_data,centerPoint)
        # 記錄這次計算的中心點
        oldcenterPoint = np.copy(centerPoint)
        # 更新中心點
        centerPoint = get_centerPoint(dataSet,k)
        # 記錄迭代次數
        iterations += 1 
    #print(dataSet)
    # y表示已經肯定好的類別
    y = dataSet[:,2]
    # 畫出散點圖,觀察聚類效果
    plt.scatter(dataSet[:,0],dataSet[:,1],c=y,s=50,cmap='autumn')

if __name__ == '__main__':
    main()
# 聚類後樣本點的散點圖
相關文章
相關標籤/搜索