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