【机器学习基础】8个知识点,图解K-Means算法
?來源:Python數(shù)據(jù)之道
作者:Peter
整理:Lemon
8個(gè)知識(shí)點(diǎn),圖解K-Means算法
之前,公眾號(hào)分享了關(guān)于 KNN算法 的介紹,今天,我們來學(xué)習(xí)下另一個(gè)經(jīng)典的算法:K-means算法。
圖解超經(jīng)典的KNN算法 - 機(jī)器學(xué)習(xí)算法入門
本文中介紹的是一種常見的無監(jiān)督學(xué)習(xí)算法,名字叫做 K 均值算法:K-Means算法。
K-Means算法在無監(jiān)督學(xué)習(xí),尤其是聚類算法中是最為基礎(chǔ)和重要的一個(gè)算法。它實(shí)現(xiàn)起來非常簡(jiǎn)單。聚類效果也很不錯(cuò)的,因此應(yīng)用非常廣泛。
本文將會(huì)從以下 8 個(gè)方面進(jìn)行詳細(xì)的講解:
算法思想
無監(jiān)督學(xué)習(xí)
在正式介紹 K-Means 算法之前,我們先解釋一下無監(jiān)督學(xué)習(xí)。用一句很通俗的話來解釋:
是否有監(jiān)督(supervised),我們只需要看輸入的數(shù)據(jù)是否有標(biāo)簽
輸入的數(shù)據(jù)如果帶有標(biāo)簽,則是有監(jiān)督學(xué)習(xí),比如 KNN算法(K近鄰)就是監(jiān)督學(xué)習(xí)的典型算法;如果沒有標(biāo)簽,則認(rèn)為是無監(jiān)督學(xué)習(xí),比如本文中即將介紹的 K-Means算法
我們看看無監(jiān)督學(xué)習(xí)聚類算法的應(yīng)用:
市場(chǎng)分割
社交網(wǎng)絡(luò)分析
組織計(jì)算機(jī)集群
星系的形成
算法思想
K-Means 聚類算法是一種迭代求解的聚類分析算法。算法思想是:我們需要隨機(jī)選擇 K 個(gè)對(duì)象作為初始的聚類中心,然后計(jì)算每個(gè)對(duì)象和各個(gè)聚類中心之間的距離,然后將每個(gè)對(duì)象分配給距離它最近的聚類中心。
聚類中心及分配給它們的對(duì)象就代表著一個(gè)聚類。每分配一個(gè)樣本,聚類的中心會(huì)根據(jù)聚類中現(xiàn)有的對(duì)象被重新計(jì)算。此過程將不斷重復(fù),直至滿足設(shè)置的終止條件。
算法步驟
K-Means 算法的具體步驟如下:
首先我們需要確定一個(gè)k值(隨機(jī)),即我們希望數(shù)據(jù)經(jīng)過聚類得到k個(gè)不同的集合;
從給定的數(shù)據(jù)集中隨機(jī)選擇K個(gè)數(shù)據(jù)點(diǎn)作為質(zhì)心;
對(duì)數(shù)據(jù)集中的每個(gè)點(diǎn)計(jì)算其與每一個(gè)質(zhì)心的距離(比如歐式距離);數(shù)據(jù)點(diǎn)離哪個(gè)質(zhì)心近,就劃分到那個(gè)質(zhì)心所屬的集合;
第一輪將所有的數(shù)據(jù)歸號(hào)集合后,一共有K個(gè)集合,然后重新計(jì)算每個(gè)集合的質(zhì)心;
如果新計(jì)算出來的質(zhì)心和原來的質(zhì)心之間的距離小于某一個(gè)設(shè)置的閾值,則表示重新計(jì)算的質(zhì)心的位置變化不大,數(shù)據(jù)整體趨于穩(wěn)定,或者說數(shù)據(jù)已經(jīng)收斂。在這樣的情況下,我們認(rèn)為聚類效果已經(jīng)達(dá)到了期望的結(jié)果,算法可終止;
反之,如果新質(zhì)心和原來質(zhì)心的距離變化很大,需要重復(fù)迭代3-5步驟,直至位置變化不大,達(dá)到收斂狀態(tài)。
圖解K-Means
具體步驟
1、給定需要進(jìn)行聚類劃分的數(shù)據(jù)集
2、隨機(jī)選擇2個(gè)聚類中心(K=2)
3、計(jì)算每個(gè)數(shù)據(jù)點(diǎn)到質(zhì)心的距離,并將數(shù)據(jù)點(diǎn)劃分到離它最近的質(zhì)心的類中
4、計(jì)算2個(gè)數(shù)據(jù)集的各自的質(zhì)心(紅點(diǎn)、藍(lán)點(diǎn)的均值),將聚類中心移動(dòng)到均值處,變成新的聚類中心
img5、找到新的聚類中心。如果
完整過程
在上面的過程中我們假設(shè)k=2。在圖b中我們隨機(jī)選擇了兩個(gè)類所對(duì)應(yīng)的質(zhì)心,也就是圖中藍(lán)色和紅色質(zhì)心;
分別求出樣本中每個(gè)點(diǎn)到這兩個(gè)質(zhì)心的距離,并且將每個(gè)樣本所屬的類別歸到和該樣本距離最小的質(zhì)心的類別,得到圖c,也就是第一輪迭代后的結(jié)果;
我們對(duì)c圖中的當(dāng)前標(biāo)記為紅色和藍(lán)色的點(diǎn)分別求出其新的質(zhì)心,得到了圖d,此時(shí)質(zhì)心的位置發(fā)生了改變;
圖e和圖f重復(fù)了圖c和圖d的過程,即將所有點(diǎn)的類別標(biāo)記為距離最近的質(zhì)心的類別并求新的質(zhì)心;
一般的,K-Means算法需要運(yùn)行多次才能達(dá)到圖f的效果。
注:以上圖形來自吳恩達(dá)老師在機(jī)器學(xué)習(xí)視頻的講解截圖
k值選擇
k值決定了我們將數(shù)據(jù)劃分成多少個(gè)簇類。k個(gè)初始化的質(zhì)心的位置選擇對(duì)最后的聚類結(jié)果和整個(gè)大代碼的運(yùn)行時(shí)間都有非常大的影響。因此需要選擇合適的k個(gè)質(zhì)心
一般k值是通過先驗(yàn)知識(shí)來選取的。如果沒有什么先驗(yàn)知識(shí),我們可以通過交叉驗(yàn)證的方式來選擇一個(gè)合適的k值。
距離問題
在機(jī)器學(xué)習(xí)中,我們常用的距離有以下幾種:
1、兩個(gè)集合之間的 的 距離定義為:
2、當(dāng) p=1 則表示為曼哈頓距離:
3、當(dāng) p=2 則表示為我們常用的歐式距離:
4、當(dāng)p趨于無窮時(shí),表示為切比雪夫距離,它是各個(gè)坐標(biāo)距離的最大值:
在K-Means算法中一般采用的是歐式距離
算法優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
原理很簡(jiǎn)單,實(shí)現(xiàn)起來也是非常容易,算法收斂速度也很快
聚類效果優(yōu),可解釋性強(qiáng)。當(dāng)數(shù)據(jù)最終收斂之后,我們最終能夠很清晰的看到聚類的效果
約束條件少。算法中需要控制的參數(shù)只有簇?cái)?shù)k。通過對(duì)k的不斷調(diào)節(jié)才能得到最好的聚類效果
缺點(diǎn)
k值的選取不好把握,很多情況下K值的估計(jì)是非常困難的,有時(shí)候通過交叉驗(yàn)證來獲取。
迭代的方法得到的結(jié)果只能是局部最優(yōu)解,而不能得到全局最優(yōu)解。
對(duì)噪音和異常點(diǎn)很敏感。異常點(diǎn)對(duì)質(zhì)心的確定影響很大的。可以用來檢測(cè)異常值。
Python實(shí)現(xiàn)K-Means
下面講解一種利用 Python 實(shí)現(xiàn) k-means 算法的代碼:
import?numpy?as?np import?pandas?as?pd import?random??#?隨機(jī)模塊 import?re import?matplotlib.pyplot?as?plt#?導(dǎo)入數(shù)據(jù) def?loadDataSet():dataset?=?np.loadtext("user/skl/cluster/dataset.csv")??#?個(gè)人文件路徑return?dataset???#?返回?cái)?shù)據(jù)集#?繪圖函數(shù) def?show_fig():dataset?=?loadDataSet()???#?導(dǎo)入數(shù)據(jù)fig?=?plt.figure()??#?確定畫布ax?=?fig.add_subplot(111)???#?一個(gè)子圖ax.scatter(dataset[:,0],?dataset[:,1])??#?傳入繪圖數(shù)據(jù)plt.show()#?定義歐式距離公式 #?兩個(gè)向量間的歐式距離公式:[(x_1 - x_2)^2 +?(y_1 - y_2)^2 +?(x_n - y_n)^2] def?calcudistance(vec1,vec2):??#?傳入兩個(gè)向量return?np.sqrt(np.sum(np.square(vec1?-?vec2)))??#?向量相減在平方,最后再求和#?初始化質(zhì)心 def?initCentroids(dataset,?k):#?初始化執(zhí)行;dataset是傳入的數(shù)據(jù)# k:選擇分類簇的個(gè)數(shù)dataset?=?list(dataset)??#?數(shù)據(jù)列表化return?random.sample(dataset,k)???#?隨機(jī)選取k的模塊#?計(jì)算每個(gè)數(shù)據(jù)點(diǎn)和質(zhì)心的距離,并歸屬到距離最小的類別中 def?minDisctance(dataset,?centroidList):??#?傳入數(shù)據(jù)集和選取的質(zhì)心列表clusterDict?=?dict()??#?保存簇類結(jié)果k?=?len(centroidList)??#?質(zhì)心列表的長(zhǎng)度:總共多少個(gè)質(zhì)心表示分成多少類for?item?in?dataset:??#?原始數(shù)據(jù)中的每個(gè)元素vec1?=?item??#?數(shù)據(jù)中的向量flag?=?-1??#?標(biāo)志位minDis?=?float("inf")???#?初始化為無窮大值for?i?in?range(k):vec2?=?centroidList[i]???#?取出第i個(gè)質(zhì)心distcance?=?calcudistance(vec1,?vec2)???#?計(jì)算歐式距離if?distance?<?minDis:???minDis?=?distance??#?如果算出來的實(shí)際距離小于最小值的初始值,則將真實(shí)值distance賦值給最小值(更新最小值)flag?=?i??#?循環(huán)結(jié)束時(shí),flag保存與當(dāng)前item最近的簇標(biāo)記if?flag?not?in?clusterDict.keys():clusterDict.setdefault(flag,[])clusterDict[flag].append(item)??#?加入到相應(yīng)的簇類中return?clusterDict??#?不同的類別#?重新計(jì)算質(zhì)心 def?getcentroids(clusterDict):#?重新計(jì)算k個(gè)質(zhì)心centroidList?=?[]???#?質(zhì)心空列表for?key?in?clusterDict.keys():??#?centroid?=?np.mean(clusterDict[key],?axis=0)??#?現(xiàn)有數(shù)據(jù)點(diǎn)的平均值centroidList.append(centroid)return?centroidList??#?得到新的質(zhì)心#?計(jì)算均方誤差 def?getVar(centroidList,?clusterDict):#?將簇類中各個(gè)向量和質(zhì)心的距離累加求和sum?=?0.0??#?初始值for?key?in?clusterDict.keys():???#?簇類中的鍵vec1?=?centroidList[key]???#?取出某個(gè)質(zhì)心distance?=?0.0??#?距離初始化值for?item?in?clusterDict[key]:??#?簇類的鍵vec2?=?itemdistance?+=?calcudistance(vec1,?vec2)??#?求距離sum?+=?distance??#?累加return?sum#?顯示簇類 def?showCluster(centroidList,?clusterDict):#?顯示簇類結(jié)果color_mark?=?["or","ob","og","ok","oy","ow"]centroid_mark?=?["dr","db","dg","dk","dy","dw"]for?key?in?clusterDict.keys():plt.plot(centroidList[key][0],?centroidList[key][1],?centroidMark[key],markersize=12)??#?質(zhì)心點(diǎn)for?item?in?clusterDict[key]:plt.plot(item[0],item[1],colorMark[key])plt.show()#?主函數(shù) def?main():dataset?=?loadDataSet()??#?導(dǎo)入數(shù)據(jù)centroidList?=?initCentroids(dataset,4)???#?質(zhì)心列表clusterDict?=?minDistance(dataset,?centroidList)???#?簇類的字典數(shù)據(jù)newVar?=?getVar(centroidList,?clusterDict)???#?質(zhì)心和簇類中數(shù)據(jù)得到新的誤差oldVar?=?1??#?當(dāng)兩次聚類的誤差小于某個(gè)值時(shí),說明質(zhì)心基本穩(wěn)定times?=?2while?abs(newVar?-?oldVar)?>=?0.00001:???#?當(dāng)新舊誤差的絕對(duì)值小于某個(gè)很小的值centroidList?=?getCentroids(clusterDict)???#?得到質(zhì)心列表oldVar?=?newVar??#?將新的誤差賦值給舊誤差newVar?=?getVar(centroidList,?clusterDict)???#?新誤差times?+=?1showCluster(centroidList,?clusterDict)??#?顯示聚類結(jié)果if?__name__?==?"__main__":show_fig()main()延伸學(xué)習(xí)
傳統(tǒng)的 K-Means 算法存在一些缺陷,比如K值的選取不是很好把握、對(duì)異常數(shù)據(jù)敏感等,于是提出了很多在其基礎(chǔ)上改進(jìn)的聚類算法:
1、K-Means++(初始化優(yōu)化)
針對(duì)K-Means算法中隨機(jī)初始化質(zhì)心的方法進(jìn)行了優(yōu)化
2、elkan K-Means(距離優(yōu)化)
在傳統(tǒng)的 K-Means 算法中,在每輪迭代中我們都需要計(jì)算所有的樣本點(diǎn)到質(zhì)心的距離,這樣是非常耗時(shí)的。
elkan K-Means算法利用:兩邊之和大于等于第三邊,以及兩邊之差小于第三邊的三角形性質(zhì),來減少距離的計(jì)算。
3、Mini Batch K-Means算法(大樣本優(yōu)化)
在傳統(tǒng)的K-Means算法中,要計(jì)算所有的樣本點(diǎn)到所有的質(zhì)心的距離。現(xiàn)在大數(shù)據(jù)時(shí)代,如果樣本量非常大,傳統(tǒng)的算法將會(huì)非常耗時(shí)。
Mini Batch K-Means 就是從原始的樣本集中隨機(jī)選擇一部分樣本做傳統(tǒng)的 K-Means 。這樣可以避免樣本量太大的計(jì)算難題,同時(shí)也加速算法的收斂。當(dāng)然,此時(shí)的代價(jià)就是我們最終聚類的精度會(huì)降低一些。
為了增加算法的準(zhǔn)確性,我們一般會(huì)多跑幾次 Mini Batch K-Means 算法,用得到不同的隨機(jī)樣本集來得到聚類簇,選擇其中最優(yōu)的聚類簇。
參考資料
1、李航老師—《統(tǒng)計(jì)學(xué)習(xí)方法》一書
2、吳恩達(dá)老師—《機(jī)器學(xué)習(xí)》視頻
3、劉建平老師—博客:https://www.cnblogs.com/pinard/
作者簡(jiǎn)介
Peter,碩士畢業(yè)僧一枚,從電子專業(yè)自學(xué)Python入門數(shù)據(jù)行業(yè),擅長(zhǎng)數(shù)據(jù)分析及可視化。喜歡數(shù)據(jù),堅(jiān)持跑步,熱愛閱讀,樂觀生活。個(gè)人格言:不浮于世,不負(fù)于己
個(gè)人站點(diǎn):www.renpeter.cn,歡迎常來小屋逛逛
往期精彩回顧適合初學(xué)者入門人工智能的路線及資料下載機(jī)器學(xué)習(xí)及深度學(xué)習(xí)筆記等資料打印機(jī)器學(xué)習(xí)在線手冊(cè)深度學(xué)習(xí)筆記專輯《統(tǒng)計(jì)學(xué)習(xí)方法》的代碼復(fù)現(xiàn)專輯 AI基礎(chǔ)下載機(jī)器學(xué)習(xí)的數(shù)學(xué)基礎(chǔ)專輯 獲取本站知識(shí)星球優(yōu)惠券,復(fù)制鏈接直接打開: https://t.zsxq.com/qFiUFMV 本站qq群704220115。加入微信群請(qǐng)掃碼:總結(jié)
以上是生活随笔為你收集整理的【机器学习基础】8个知识点,图解K-Means算法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: qq浏览器私密空间在哪 具体操作步骤
- 下一篇: 谷歌Chrome:将逐步阻止浏览器不安全