Python機器學習隨筆之K-Means聚類的實現

  1. K-Means聚類原理

K-means算法是很典型的基于距離的聚類算法椒丧,采用距離作為相似性的評價指標悼瓮,即認為兩個對象的距離越近症昏,其相似度就越大。其基本思想是:以空間中k個點為中心進行聚類过牙,對最靠近他們的對象歸類。通過迭代的方法纺铭,逐次更新各聚類中心的值寇钉,直至得到最好的聚類結果。各聚類本身盡可能的緊湊舶赔,而各聚類之間盡可能的分開扫倡。
算法大致流程為:(1)隨機選取k個點作為種子點(這k個點不一定屬于數據集);(2)分別計算每個數據點到k個種子點的距離竟纳,離哪個種子點最近撵溃,就屬于哪類;(3)重新計算k個種子點的坐標(簡單常用的方法是求坐標值的平均值作為新的坐標值锥累;(4)重復2缘挑、3步,直到種子點坐標不變或者循環(huán)次數完成桶略。

2.數據及其尋找初步的聚類中心
數據為Matlab加載格式(mat)语淘,包含X變量,數據來源為(大家可以去這下載):
https://github.com/jdwittenauer/ipython-notebooks/tree/master/data删性,
X為300*2維變量亏娜,由于是2維,所以基本上就是在平面坐標軸上的一些點中進行聚類蹬挺。

我們首先構建初步尋找聚類中心(centroids维贺,質心)函數,再隨機設置初始質心巴帮,通過歐氏距離初步判斷X的每一個變量屬于哪個質心溯泣。代碼為:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sb
from scipy.io import loadmat

def find_closest_centroids(X, centroids):
    m = X.shape[0]
    k = centroids.shape[0] #要聚類的類別個數
    idx = np.zeros(m)  
    
    for i in range(m):
        min_dist = 1000000  #迭代終止條件
        for j in range(k):
            dist = np.sum((X[i,:] - centroids[j,:]) ** 2) 
            if dist < min_dist:
               # 記錄當前最短距離和其中心的索引值
                min_dist = dist
                idx[i] = j
    
    return idx
data = loadmat('D:\python\Python ml\ex7data2.mat')
X = data['X']
initial_centroids = np.array([[3, 3], [6, 2], [8, 5]])

idx = find_closest_centroids(X, initial_centroids)
idx[0:3]

在這里先生成m(這里為300)個0向量虐秋,即idx,也就是假設X的每個變量均屬于0類垃沦,然后再根據與初始質心的距離計算dist = np.sum((X[i,:] - centroids[j,:]) ** 2)客给,初步判斷每個變量歸屬哪個類,最終替代idx中的0.

3.不斷迭代尋找質心的位置并實現kmeans算法
上述idx得到的300維向量是判斷X中每個變量的歸屬類別肢簿,在此基礎上靶剑,再對初始質心集群位置不斷調整,尋找最優(yōu)質心池充。

def compute_centroids(X, idx, k):
    m, n = X.shape
    centroids = np.zeros((k, n))
    
    for i in range(k):
        indices = np.where(idx == i)
        centroids[i,:] = (np.sum(X[indices,:], axis=1) / len(indices[0])).ravel()
    #這里簡單的將該類中心的所有數值求平均值作為新的類中心
return centroids
compute_centroids(X, idx, 3)

根據上述函數桩引,來構建kmeans函數實現K-means聚類算法。然后根據得到的每個變量歸屬類別與質心坐標收夸,進行可視化坑匠。

def run_k_means(X, initial_centroids, max_iters):
    m, n = X.shape
    k = initial_centroids.shape[0]
    idx = np.zeros(m)
    centroids = initial_centroids
    
    for i in range(max_iters):
        idx = find_closest_centroids(X, centroids)
        centroids = compute_centroids(X, idx, k)
    
    return idx, centroids
idx, centroids = run_k_means(X, initial_centroids, 10)
cluster1 = X[np.where(idx == 0)[0],:] #獲取X中屬于第一個類別的數據集合,即類別1的點
cluster2 = X[np.where(idx == 1)[0],:]
cluster3 = X[np.where(idx == 2)[0],:]

fig, ax = plt.subplots(figsize=(12,8))
ax.scatter(cluster1[:,0], cluster1[:,1], s=30, color='r', label='Cluster 1')
ax.scatter(cluster2[:,0], cluster2[:,1], s=30, color='g', label='Cluster 2')
ax.scatter(cluster3[:,0], cluster3[:,1], s=30, color='b', label='Cluster 3')
ax.legend()
plt.show()

得到圖形如下:
image.png

4.關于初始化質心的設置
我們前邊設置的初始質心:[3, 3], [6, 2], [8, 5]卧惜,是事先設定的厘灼,并由此生成idx(每一變量歸屬類別的向量),這是后邊進行kmeans聚類的基礎咽瓷,實際上對于二維以上數據设凹,由于無法在平面坐標軸展示,很難一開始就設定較好的初始質心忱详,另外围来,初始質心的設定也可能會影響算法的收斂性。所以需要我們再構造個初始化質心設定函數匈睁,來更好地設置初始質心监透。

def init_centroids(X, k):
    m, n = X.shape
    centroids = np.zeros((k, n))  #初始化零矩陣
    idx = np.random.randint(0, m, k)  #返回0-m之間的整數值
    
    for i in range(k):
        centroids[i,:] = X[idx[i],:]
    
return centroids
init_centroids(X, 3)

這里所生成的初始質心位置,其實就是從X的數據中隨機找3個變量作為初始值航唆。在此基礎上胀蛮,令initial_centroids = init_centroids(X, 3),然后代入前邊的code中糯钙,重新運行一遍即可粪狼。

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市任岸,隨后出現的幾起案子再榄,更是在濱河造成了極大的恐慌,老刑警劉巖享潜,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件困鸥,死亡現場離奇詭異,居然都是意外死亡剑按,警方通過查閱死者的電腦和手機疾就,發(fā)現死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進店門澜术,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人猬腰,你說我怎么就攤上這事鸟废。” “怎么了姑荷?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵盒延,是天一觀的道長。 經常有香客問我厢拭,道長兰英,這世上最難降的妖魔是什么撇叁? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任供鸠,我火速辦了婚禮,結果婚禮上陨闹,老公的妹妹穿的比我還像新娘楞捂。我一直安慰自己,他們只是感情好趋厉,可當我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布寨闹。 她就那樣靜靜地躺著,像睡著了一般君账。 火紅的嫁衣襯著肌膚如雪繁堡。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天乡数,我揣著相機與錄音椭蹄,去河邊找鬼。 笑死净赴,一個胖子當著我的面吹牛绳矩,可吹牛的內容都是我干的。 我是一名探鬼主播玖翅,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼翼馆,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了金度?” 一聲冷哼從身側響起应媚,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎猜极,沒想到半個月后中姜,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡魔吐,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年扎筒,在試婚紗的時候發(fā)現自己被綠了莱找。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡嗜桌,死狀恐怖奥溺,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情骨宠,我是刑警寧澤浮定,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站层亿,受9級特大地震影響桦卒,放射性物質發(fā)生泄漏。R本人自食惡果不足惜匿又,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一方灾、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧碌更,春花似錦裕偿、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至旭绒,卻和暖如春鸟妙,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背挥吵。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工重父, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蔫劣。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓坪郭,卻偏偏與公主長得像,于是被迫代替她去往敵國和親脉幢。 傳聞我的和親對象是個殘疾皇子歪沃,可洞房花燭夜當晚...
    茶點故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內容