博客專欄

        EEPW首頁 > 博客 > 原創 | 一文讀懂K均值(K-Means)聚類算法

        原創 | 一文讀懂K均值(K-Means)聚類算法

        發布人:數據派THU 時間:2022-10-20 來源:工程師 發布文章
        概述


        眾所周知,機器學習算法可分為監督學習(Supervised learning)和無監督學習(Unsupervised learning)。
        監督學習常用于分類和預測。是讓計算機去學習已經創建好的分類模型,使分類(預測)結果更好的接近所給目標值,從而對未來數據進行更好的分類和預測。因此,數據集中的所有變量被分為特征和目標,對應模型的輸入和輸出;數據集被分為訓練集和測試集,分別用于訓練模型和模型測試與評估。常見的監督學習算法有Regression(回歸)、KNN和SVM(分類)。
        無監督學習常用于聚類。輸入數據沒有標記,也沒有確定的結果,而是通過樣本間的相似性對數據集進行聚類,使類內差距最小化,類間差距最大化。無監督學習的目標不是告訴計算機怎么做,而是讓它自己去學習怎樣做事情,去分析數據集本身。常用的無監督學習算法有K-means、 PCA(Principle Component Analysis)。
        聚類算法又叫做“無監督分類”,其目的是將數據劃分成有意義或有用的組(或簇)。這種劃分可以基于業務需求或建模需求來完成,也可以單純地幫助我們探索數據的自然結構和分布。比如在商業中,如果手頭有大量的當前和潛在客戶的信息,可以使用聚類將客戶劃分為若干組,以便進一步分析和開展營銷活動。再比如,聚類可以用于降維和矢量量化,可以將高維特征壓縮到一列當中,常常用于圖像、聲音和視頻等非結構化數據,可以大幅度壓縮數據量。
        聚類算法與分類算法的比較:


        聚類分類
        核心將數據分成多個組,探索各個組的數據是否有關聯從已經分組的數據中去學習,把新數據放到已經分好的組中去
        學習類型無監督學習算法,不需要標簽進行訓練有監督學習算法,需要標簽進行訓練
        典型算法K-Means、DBSCAN、層次聚類等K近鄰(KNN)、決策樹、樸素貝葉斯、邏輯回歸、支持向量機、隨機森林等
        算法輸出無需預設類別,類別數不確定,類別在學習中生成預設類別,類別數不變,適合類別或分類體系已經確定的場合


        K-Means詳解
        1. K-Means的工作原理
        作為聚類算法的典型代表,K-Means可以說是最簡單的聚類算法,那它的聚類工作原理是什么呢?

        概念1:簇與質心
        K-Means算法是將一組N個樣本的特征矩陣X劃分為K個無交集的簇,直觀上來看是簇是一組一組聚集在一起的數據,在一個簇中的數據就認為是同一類。簇就是聚類的結果表現。簇中所有數據的均值通常被稱為這個簇的“質心”(Centroids)。在一個二維平面中,一簇數據點的質心的橫坐標就是這一簇數據點的橫坐標的均值,質心的縱坐標就是這一簇數據點的縱坐標的均值。同理可推廣至高維空間。


        在K-Means算法中,簇的個數K是一個超參數,需要人為輸入來確定。K-Means的核心任務就是根據設定好的K,找出K個最優的質心,并將離這些質心最近的數據分別分配到這些質心代表的簇中去。具體過程可以總結如下:
        a.首先隨機選取樣本中的K個點作為聚類中心;b.分別算出樣本中其他樣本距離這K個聚類中心的距離,并把這些樣本分別作為自己最近的那個聚類中心的類別;c.對上述分類完的樣本再進行每個類別求平均值,求解出新的聚類質心;d.與前一次計算得到的K個聚類質心比較,如果聚類質心發生變化,轉過程b,否則轉過程e;e.當質心不發生變化時(當我們找到一個質心,在每次迭代中被分配到這個質心上的樣本都是一致的,即每次新生成的簇都是一致的,所有的樣本點都不會再從一個簇轉移到另一個簇,質心就不會變化了),停止并輸出聚類結果。K-Means算法計算過程如圖1 所示:

        圖片

        圖1  K-Means算法計算過程
        圖片
        圖2  K-Means迭代示意圖
        例題:
        1. 對于以下數據點,請采用k-means方法進行聚類(手工計算)。假設聚類簇數k=3,初始聚類簇中心分別為數據點2、數據點3、數據點5。

        數據點1-5.379713-3.362104
        數據點2-3.487105-1.724432
        數據點30.450614-3.302219
        數據點4-0.392370-3.963704
        數據點5-3.4536873.424321


        解:


















































        正在進行第1次迭代初始質心為B、C、EAB = 2.502785AC = 5.830635AE = 7.054443DB = 3.819911DC = 1.071534DE = 7.997158因此,第一簇:{A,B};第二簇:{C,D};第三簇:{E}即[array([-5.379713, -3.362104]), array([-3.487105, -1.724432])][array([ 0.450614, -3.302219]), array([-0.39237, -3.963704])][array([-3.45368, 3.424321])]所以第一簇的質心為F:[-4.433409 -2.543268]第二簇的質心為G:[ 0.029122 -3.6329615]第三簇的質心為H:[-3.45368 3.424321]###########################################################正在進行第2次迭代AF = 1.251393AG = 5.415613AH = 7.054443BF = 1.251393BG = 4.000792BH = 5.148861CF = 4.942640CG = 0.535767CH = 7.777522DF = 4.283414DG = 0.535767DH = 7.997158EF = 6.047478EG = 7.869889EH = 0.000000因此,第一簇:{A,B};第二簇:{C,D};第三簇:{E}即[array([-5.379713, -3.362104]), array([-3.487105, -1.724432])][array([ 0.450614, -3.302219]), array([-0.39237, -3.963704])][array([-3.45368, 3.424321])]所以第一簇的質心為:[-4.433409 -2.543268]第二簇的質心為:[ 0.029122 -3.6329615]第三簇的質心為:[-3.45368 3.424321]###########################################################由于三個簇的成員保持不變,聚類結束

        綜上所述:第一簇:{A,B};第二簇:{C,D};第三簇:{E}
        2. 簇內誤差平方和的定義
        聚類算法聚出的類有什么含義呢?這些類有什么樣的性質?
        我們認為,被分在同一個簇中的數據是有相似性的,而不同簇中的數據是不同的,當聚類完畢之后,接下來需要分別研究每個簇中的樣本都有什么樣的性質,從而根據業務需求制定不同的商業或者科技策略。聚類算法追求“簇內差異小,簇外差異大”。而這個 “差異”便是通過樣本點到其簇質心的距離來衡量。
        對于一個簇來說,所有樣本點到質心的距離之和越小,便認為這個簇中的樣本越相似,簇內差異越小。而距離的衡量方法有多種,令x表示簇中的一個樣本點,μ表示該簇中的質心,n表示每個樣本點中的特征數目,i表示組成點x的每個特征,則該樣本點到質心的距離可以由以下距離來度量:
        圖片
        如采用歐幾里得距離,則一個簇中所有樣本點到質心的距離的平方和為:
        圖片
        其中,m為一個簇中樣本的個數,j是每個樣本的編號。這個公式被稱為簇內平方和(Cluster Sum of Square),又叫做Inertia。而將一個數據集中的所有簇的簇內平方和相加,就得到了整體平方和(Total Cluster Sum of Square),又叫做Total Inertia。Total Inertia越小,代表著每個簇內樣本越相似,聚類的效果就越好。因此K-Means追求的是:求解能夠讓Inertia最小化的質心。實際上,在質心不斷變化不斷迭代的過程中,總體平方和是越來越小的。我們可以通過數學來證明,當整體平方和達到最小值的時候,質心就不再發生變化了。如此,K-Means的求解過程,就變成了一個最優化問題。
        在K-Means中,在一個固定的簇數K條件下,最小化總體平方和來求解最佳質心,并基于質心的存在去進行聚類。兩個過程十分相似,并且整體距離平方和的最小值其實可以使用梯度下降來求解。
        大家可以發現, Inertia是基于歐幾里得距離的計算公式得來的。實際上,也可以使用其他距離,每個距離都有自己對應的Inertia。在過去的經驗中,已經總結出不同距離所對應的質心選擇方法和Inertia,在K-Means中,只要使用了正確的質心和距離組合,無論使用什么距離,都可以達到不錯的聚類效果。

        距離度量質心Inertial
        歐幾里得距離均值最小化每個樣本點到質心的歐式距離之和
        曼哈頓距離中位數最小化每個樣本點到質心的曼哈頓距離之和
        余弦距離均值最小化每個樣本點到質心的余弦距離之和


        3. K-Means算法的時間復雜度
        眾所周知,算法的復雜度分為時間復雜度和空間復雜度,時間復雜度是指執行算法所需要的計算工作量,常用大O符號表述;而空間復雜度是指執行這個算法所需要的內存空間。如果一個算法的效果很好,但需要的時間復雜度和空間復雜度都很大,那將會在算法的效果和所需的計算成本之間進行權衡。
        K-Means算法是一個計算成本很大的算法。K-Means算法的平均復雜度是O(k*n*T),其中k是超參數,即所需要輸入的簇數,n是整個數據集中的樣本量,T是所需要的迭代次數。在最壞的情況下,KMeans的復雜度可以寫作O(n(k+2)/p),其中n是整個數據集中的樣本量,p是特征總數。
        4. 聚類算法的模型評估指標
        不同于分類模型和回歸,聚類算法的模型評估不是一件簡單的事。在分類中,有直接結果(標簽)的輸出,并且分類的結果有正誤之分,所以需要通過使用預測的準確度、混淆矩陣、ROC曲線等指標來進行評估,但無論如何評估,都是在評估“模型找到正確答案”的能力。而在回歸中,由于要擬合數據,可以通過SSE均方誤差、損失函數來衡量模型的擬合程度。但這些衡量指標都不能夠用于聚類。
        聚類模型的結果不是某種標簽輸出,并且聚類的結果是不確定的,其優劣由業務需求或者算法需求來決定,并且沒有永遠的正確答案。那如何衡量聚類的效果呢?K-Means的目標是確保“簇內差異小,簇外差異大”,所以可以通過衡量簇內差異來衡量聚類的效果。前面講過,Inertia是用距離來衡量簇內差異的指標,因此,是否可以使用Inertia來作為聚類的衡量指標呢?
        「肘部法(手肘法)認為圖3的拐點就是k的最佳值」

        手肘法核心思想:隨著聚類數k的增大,樣本劃分會更加精細,每個簇的聚合程度會逐漸提高,那么Inertia自然會逐漸變小。當k小于真實聚類數時,由于k的增大會大幅增加每個簇的聚合程度,故Inertia的下降幅度會很大,而當k到達真實聚類數時,再增加k所得到的聚合程度回報會迅速變小,所以Inertia的下降幅度會驟減,然后隨著k值的繼續增大而趨于平緩,也就是說Inertia和k的關系圖是一個手肘的形狀,而這個肘部對應的k值就是數據的真實聚類數。例如下圖,肘部對于的k值為3(曲率最高),故對于這個數據集的聚類而言,最佳聚類數應該選3。

        圖片圖3  手肘法
        那就引出一個問題:Inertia越小模型越好嗎?答案是可以的,但是Inertia這個指標又有其缺點和極限:
        a.它的計算太容易受到特征數目的影響。b.它不是有界的,Inertia是越小越好,但并不知道何時達到模型的極限,能否繼續提高。c.它會受到超參數K的影響,隨著K越大,Inertia必定會越來越小,但并不代表模型效果越來越好。d.Inertia 對數據的分布有假設,它假設數據滿足凸分布,并且它假設數據是各向同性的,所以使用Inertia作為評估指標,會讓聚類算法在一些細長簇、環形簇或者不規則形狀的流形時表現不佳。
        那又可以使用什么指標來衡量模型效果呢?
        (1)輪廓系數
        在99%的情況下,是對沒有真實標簽的數據進行探索,也就是對不知道真正答案的數據進行聚類。這樣的聚類,是完全依賴于評價簇內的稠密程度(簇內差異小)和簇間的離散程度(簇外差異大)來評估聚類的效果。其中輪廓系數是最常用的聚類算法的評價指標。它是對每個樣本來定義的,它能夠同時衡量:
        a)樣本與其自身所在的簇中的其他樣本的相似度a,等于樣本與同一簇中所有其他點之間的平均距離。b)樣本與其他簇中的樣本的相似度b,等于樣本與下一個最近的簇中的所有點之間的平均距離。根據聚類“簇內差異小,簇外差異大”的原則,我們希望b永遠大于a,并且大得越多越好。單個樣本的輪廓系數計算為:
        圖片
        公式進行展開為:
        圖片
        很容易理解輪廓系數范圍是(-1,1),其中值越接近1表示樣本與自己所在的簇中的樣本很相似,并且與其他簇中的樣本不相似,當樣本點與簇外的樣本更相似的時候,輪廓系數就為負。當輪廓系數為0時,則代表兩個簇中的樣本相似度一致,兩個簇本應該是一個簇。
        如果一個簇中的大多數樣本具有比較高的輪廓系數,簇會有較高的總輪廓系數,則整個數據集的平均輪廓系數越高,表明聚類是合適的;如果許多樣本點具有低輪廓系數甚至負值,則聚類是不合適的,聚類的超參數K可能設定得太大或者太小。
        輪廓系數有很多優點,它在有限空間中取值,使得我們對模型的聚類效果有一個“參考”。并且,輪廓系數對數據的分布沒有限定,因此在很多數據集上都表現良好,它在每個簇的分割比較清晰時表現最好。但輪廓系數也有缺陷,它在凸型的類上表現會虛高,比如基于密度進行的聚類,或通過DBSCAN獲得的聚類結果,如果使用輪廓系數來衡量,則會表現出比真實聚類效果更高的分數。
        (2)卡林斯基-哈拉巴斯指數
        除了最常用的輪廓系數,還有卡林斯基-哈拉巴斯指數(Calinski-Harabaz Index,簡稱CHI,也被稱為方差比標準)、戴維斯-布爾丁指數(Davies-Bouldin)以及權變矩陣(Contingency Matrix)可以使用。在這里不多介紹,感興趣的讀者可以自己學習。
        5. 初始質心的問題
        在K-Means中有一個重要的環節,就是放置初始質心。如果有足夠的時間,K-means一定會收斂,但Inertia可能收斂到局部最小值。是否能夠收斂到真正的最小值很大程度上取決于質心的初始化。
        初始質心放置的位置不同,聚類的結果很可能也會不一樣,一個好的質心選擇可以讓K-Means避免更多的計算,讓算法收斂穩定且更快。在之前講解初始質心的放置時,是采用“隨機”的方法在樣本點中抽取k個樣本作為初始質心,這種方法顯然不符合“穩定且更快”的需求。
        為此,在sklearn中使用random_state參數來實現控制,確保每次生成的初始質心都在相同位置,甚至可以畫學習曲線來確定最優的random_state參數。
        一個random_state對應一個質心隨機初始化的隨機數種子。如果不指定隨機數種子,則sklearn中的K-Means并不會只選擇一個隨機模式扔出結果,而會在每個隨機數種子下運行多次,并使用結果最好的一個隨機數種子來作為初始質心。
        在sklearn中也可以使用參數n_init來選擇(每個隨機數種子下運行的次數),可以增加這個參數n_init的值來增加每個隨機數種子下運行的次數。
        另外,為了優化選擇初始質心的方法,“k-means ++”能夠使得初始質心彼此遠離,以此來引導出比隨機初始化更可靠的結果。在sklearn中,使用參數init =‘k-means ++'來選擇使用k-means++作為質心初始化的方案。
        6. 聚類算法的迭代問題
        大家都知道,當質心不再移動,Kmeans算法就會停下來。在完全收斂之前,sklearn中也可以使用max_iter(最大迭代次數)或者tol兩個參數來讓迭代提前停下來。有時候,當n_clusters選擇不符合數據的自然分布,或者為了業務需求,必須要填入n_clusters數據提前讓迭代停下來時,反而能夠提升模型的表現。
        max_iter:整數,默認300,單次運行的k-means算法的最大迭代次數;tol:浮點數,默認1e-4,兩次迭代間Inertia下降的量,如果兩次迭代之間Inertia下降的值小于tol所設定的值,迭代就會停下。
        7. K-Means算法的優缺點
        (1)K-Means算法的優點

        • 原理比較簡單,實現也是很容易,收斂速度快;
        • 聚類效果較優,算法的可解釋度比較強。


        (2)K-Means算法的缺點

        • K值的選取不好把握;
        • 對于不是凸的數據集比較難收斂;
        • 如果各隱含類別的數據不平衡,比如各隱含類別的數據量嚴重失衡,或者各隱含類別的方差不同,則聚類效果不佳;
        • 采用迭代方法,得到的結果只是局部最優;
        • 對噪音和異常點比較的敏感。


        結論
        K均值(K-Means)聚類算法原理簡單,可解釋強,實現方便,可廣泛應用在數據挖掘、聚類分析、數據聚類、模式識別、金融風控、數據科學、智能營銷和數據運營等多個領域,有著廣泛的應用前景。


        *博客內容為網友個人發布,僅代表博主個人觀點,如有侵權請聯系工作人員刪除。



        關鍵詞: AI

        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 津南区| 改则县| 温泉县| 扶风县| 荥经县| 安顺市| 扶沟县| 南通市| 滦平县| 沾化县| 民乐县| 本溪市| 清新县| 榕江县| 浪卡子县| 肃宁县| 克什克腾旗| 成都市| 新宾| 克拉玛依市| 吴桥县| 株洲市| 平阳县| 仪征市| 手游| 汶上县| 厦门市| 赤城县| 德江县| 定安县| 晋城| 贵港市| 北宁市| 枣阳市| 广河县| 苏尼特左旗| 遂宁市| 错那县| 莫力| 喀喇沁旗| 平乐县|