1. 程式人生 > >機器學習【三】無監督學習-聚類演算法-Kmeans

機器學習【三】無監督學習-聚類演算法-Kmeans

1.K-meansK-means,屬於無監督學習。即輸入資料沒有標籤y,經過一些演算法後,找到標籤y。聚類的目的就是找到每個樣本潛在的標籤y,並將同類別的樣本放到一起。k-means聚類:就是把n個點(可以是樣本的一次觀察或一個例項)劃分到k個聚類中,使得每個點都屬於離他最近的均值(此即聚類中心)對應的聚類,以之作為聚類的標準。每一個樣本有多個特徵,下圖表示的是兩個特徵的情況下
2.優化目標
3.演算法
輸入無x0,且沒有y,也就是無標記

這裡引用一篇知名博主程sir的解釋

  • 首先輸入k的值,即我們希望將資料集經過聚類得到k個分組。
  • 從資料集中隨機選擇k個數據點作為初始大哥(質心,Centroid)
  • 對集合中每一個小弟,計算與每一個大哥的距離(距離的含義後面會講),離哪個大哥距離近,就跟定哪個大哥。
  • 這時每一個大哥手下都聚集了一票小弟,這時候召開人民代表大會,每一群選出新的大哥(其實是通過演算法選出新的質心)。
  • 如果新大哥和老大哥之間的距離小於某一個設定的閾值(表示重新計算的質心的位置變化不大,趨於穩定,或者說收斂),可以認為我們進行的聚類已經達到期望的結果,演算法終止。
  • 如果新大哥和老大哥距離變化很大,需要迭代3~5步驟。

4.隨機初始化
可能會卡在區域性最優
多次隨機初始化演算法
5.選擇聚類數目使用下圖左邊的肘部法則,但是很多情況,都會出現右側的情況,所以不是很實用

6.程式碼例項

cousera上有matlab實現此演算法的程式碼,很好,我也動手嘗試了,要求完整實現程式碼邏輯。這裡用其它教程使用sklearn包來一個函式解決

1.資料例項


2.資料檔案 city.txt

北京,2959.19,730.79,749.41,513.34,467.87,1141.82,478.42,457.64
天津,2459.77,495.47,697.33,302.87,284.19,735.97,570.84,305.08
河北,1495.63,515.90,362.37,285.32,272.95,540.58,364.91,188.63
山西,1406.33,477.77,290.15,208.57,201.50,414.72,281.84,212.10
內蒙古,1303.97,524.29,254.83,192.17,249.81,463.09,287.87,192.96
遼寧,1730.84,553.90,246.91,279.81,239.18,445.20,330.24,163.86
吉林,1561.86,492.42,200.49,218.36,220.69,459.62,360.48,147.76
黑龍江,1410.11,510.71,211.88,277.11,224.65,376.82,317.61,152.85
上海,3712.31,550.74,893.37,346.93,527.00,1034.98,720.33,462.03
江蘇,2207.58,449.37,572.40,211.92,302.09,585.23,429.77,252.54
浙江,2629.16,557.32,689.73,435.69,514.66,795.87,575.76,323.36
安徽,1844.78,430.29,271.28,126.33,250.56,513.18,314.00,151.39
福建,2709.46,428.11,334.12,160.77,405.14,461.67,535.13,232.29
江西,1563.78,303.65,233.81,107.90,209.70,393.99,509.39,160.12
山東,1675.75,613.32,550.71,219.79,272.59,599.43,371.62,211.84
河南,1427.65,431.79,288.55,208.14,217.00,337.76,421.31,165.32
湖南,1942.23,512.27,401.39,206.06,321.29,697.22,492.60,226.45
湖北,1783.43,511.88,282.84,201.01,237.60,617.74,523.52,182.52
廣東,3055.17,353.23,564.56,356.27,811.88,873.06,1082.82,420.81
廣西,2033.87,300.82,338.65,157.78,329.06,621.74,587.02,218.27
海南,2057.86,186.44,202.72,171.79,329.65,477.17,312.93,279.19
重慶,2303.29,589.99,516.21,236.55,403.92,730.05,438.41,225.80
四川,1974.28,507.76,344.79,203.21,240.24,575.10,430.36,223.46
貴州,1673.82,437.75,461.61,153.32,254.66,445.59,346.11,191.48
雲南,2194.25,537.01,369.07,249.54,290.84,561.91,407.70,330.95
西藏,2646.61,839.70,204.44,209.11,379.30,371.04,269.59,389.33
陝西,1472.95,390.89,447.95,259.51,230.61,490.90,469.10,191.34
甘肅,1525.57,472.98,328.90,219.86,206.65,449.69,249.66,228.19
青海,1654.69,437.77,258.78,303.00,244.93,479.53,288.56,236.51
寧夏,1375.46,480.89,273.84,317.32,251.08,424.75,228.73,195.93
新疆,1608.82,536.05,432.46,235.82,250.28,541.30,344.85,214.40

3.程式碼

import numpy as np
from sklearn.cluster import KMeans

def loadData(filePath):
    fr = open(filePath,'r+',encoding='utf8')
    lines = fr.readlines()
    reData = [] #用來儲存城市的各項消費資訊
    reCityName = [] #用來儲存城市名稱
    for line in lines:
        items = line.strip().split(",")
        reCityName.append(items[0])
        reData.append([float(items[i]) for i in range(1,len(items))])
    return reData,reCityName

if __name__ == '__main__':
    data,cityName = loadData('city.txt')
    km = KMeans(n_clusters=4) #分為4類
    label = km.fit_predict(data)  # 計算簇中心以及為簇分配序號,label為每行資料對應分配到的序列
    print('label\n', label)
    #求得的label就是一個列表,裡面就是結果,結果是每個樣本屬於哪一個分類
    
    expenses = np.sum(km.cluster_centers_, axis=1)  # 按行求和
    print('km.cluster_centers_\n', km.cluster_centers_) #四個類別,每個類別的中心座標
    print('expenses\n', expenses, '\n\n') #將四個類別每個類別的所有特徵求和
    
    CityCluster = [[], [], [], []]
    # 將在同一個簇的城市儲存在同一個list中
    for i in range(len(cityName)):
        CityCluster[label[i]].append(cityName[i])
    # 輸出各個簇的平均消費數和對應的城市名稱
    for i in range(len(CityCluster)):
        print("Expenses:%.2f" % expenses[i])
        print(CityCluster[i])

4.執行結果

label
 [3 1 0 0 0 0 0 0 3 2 1 2 1 0 0 0 2 2 3 2 2 1 2 0 2 1 0 0 0 0 0]
km.cluster_centers_
 [[1525.81533333  478.672       322.88266667  232.4         236.41866667
   457.53133333  344.81866667  190.21933333]
 [2549.658       582.118       488.366       268.998       397.442
   618.92        477.946       295.172     ]
 [2004.785       429.48        347.8925      190.955       287.66625
   581.16125     437.2375      233.09625   ]
 [3242.22333333  544.92        735.78        405.51333333  602.25
  1016.62        760.52333333  446.82666667]]
expenses
 [3788.758      5678.62       4512.27375    7754.65666667] 


Expenses:3788.76
['河北', '山西', '內蒙古', '遼寧', '吉林', '黑龍江', '江西', '山東', '河南', '貴州', '陝西', '甘肅', '青海', '寧夏', '新疆']
Expenses:5678.62
['天津', '浙江', '福建', '重慶', '西藏']
Expenses:4512.27
['江蘇', '安徽', '湖南', '湖北', '廣西', '海南', '四川', '雲南']
Expenses:7754.66
['北京', '上海', '廣東']