kmeans原理


一、kmeans概述

K-means聚類算法也稱k均值聚類算法,屬於無監督學習的一種,k-means聚類無需給定Y變量,只有特征X。

K-means聚類算法是一種迭代求解的聚類分析算法,其步驟是隨機選取K個對象作為初始的聚類中心,然后計算每個對象與各個種子聚類中心之間的距離,把每個對象分配給距離它最近的聚類中心。聚類中心以及分配給它們的對象就代表一個聚類。每分配一個樣本,聚類的聚類中心會根據聚類中現有的對象被重新計算。這個過程將不斷重復直到滿足某個終止條件。終止條件可以是沒有(或最小數目)對象被重新分配給不同的聚類,沒有(或最小數目)聚類中心再發生變化,誤差平方和局部最小

在聚類問題中,給我們的訓練樣本是clip_image004,每個clip_image006,沒有了y

具體算法描述如下:

1、 隨機選取k個聚類質心點(cluster centroids)為clip_image008[6]

2、 重復下面過程直到收斂 {

               對於每一個樣例i,計算其應該屬於的類

               clip_image009

               對於每一個類j,重新計算該類的質心

               clip_image010[6]}

K是我們事先給定的聚類數,clip_image012[6]代表樣例i與k個類中距離最近的那個類,clip_image012[7]的值是1到k中的一個。質心clip_image014[6]代表我們對屬於同一個類的樣本中心點的猜測,拿星團模型來解釋就是要將所有的星星聚成k個星團,首先隨機選取k個宇宙中的點(或者k個星星)作為k個星團的質心,然后第一步對於每一個星星計算其到k個質心中每一個的距離,然后選取距離最近的那個星團作為clip_image012[8],這樣經過第一步每一個星星都有了所屬的星團;第二步對於每一個星團,重新計算它的質心clip_image014[7](對里面所有的星星坐標求平均)。重復迭代第一步和第二步直到質心不變或者變化很小。

K-means面對的第一個問題是如何保證收斂,前面的算法中強調結束條件就是收斂,可以證明的是K-means完全可以保證收斂性。下面我們定性的描述一下收斂性,我們定義畸變函數(distortion function)如下:

     clip_image016[6]

     J函數表示每個樣本點到其質心的距離平方和。K-means是要將J調整到最小。假設當前J沒有達到最小值,那么首先可以固定每個類的質心clip_image014[8],調整每個樣例的所屬的類別clip_image012[9]來讓J函數減少,同樣,固定clip_image012[10],調整每個類的質心clip_image014[9]也可以使J減小。這兩個過程就是內循環中使J單調遞減的過程。當J遞減到最小時,clip_image018[6]和c也同時收斂。(在理論上,可以有多組不同的clip_image018[7]和c值能夠使得J取得最小值,但這種現象實際上很少見)。

     由於畸變函數J是非凸函數,意味着我們不能保證取得的最小值是全局最小值,也就是說k-means對質心初始位置的選取比較感冒,但一般情況下k-means達到的局部最優已經滿足需求。但如果你怕陷入局部最優,那么可以選取不同的初始值跑多遍k-means,然后取其中最小的J對應的clip_image018[8]和c輸出

二、kmeans的損失函數

和其他機器學習算法一樣,K-Means 也要評估並且最小化聚類代價,在引入 K-Means 的代價函數之前,先引入如下定義:

 

 引入代價函數:

 三、kmeans的優缺點

優點:
1)原理比較簡單,實現也是很容易,收斂速度快。
2)聚類效果較優。
3)算法的可解釋度比較強。
4)主要需要調參的參數僅僅是簇數k。

缺點:
1)K值的選取不好把握
2)對於不是凸的數據集比較難收斂
3)如果各隱含類別的數據不平衡,比如各隱含類別的數據量嚴重失衡,或者各隱含類別的方差不同,則聚類效果不佳。
4) 采用迭代方法,得到的結果只是局部最優

四、kmeans參數

sklearn.cluster.KMeans

class sklearn.cluster.KMeans(n_clusters=8, *, init='k-means++', n_init=10, max_iter=300, tol=0.0001, 
precompute_distances='deprecated', verbose=0, random_state=None, copy_x=True, n_jobs='deprecated', algorithm='auto')
  • n_clusters:int, default=8,簇的個數,即你想聚成幾類
  • init:{'k-means++', 'random', ndarray, callable}, default=’k-means++’,初始簇中心的獲取方法,'k-means ++':以一種聰明的方式為k-mean聚類選擇初始聚類中心,以加快收斂速度​​。有關更多詳細信息,請參見k_init中的注釋部分。'random':n_clusters從初始質心的數據中隨機選擇觀察(行)。如果傳遞了ndarray,則其形狀應為(n_clusters,n_features),並給出初始中心。如果傳遞了callable,則應使用參數X,n_clusters和隨機狀態並返回初始化
  • n_init:int, default=10,獲取初始簇中心的更迭次數,k均值算法將在不同質心種子下運行的次數
  • max_iter:int, default=300,最大迭代次數(因為kmeans算法的實現需要迭代),單次運行的k均值算法的最大迭代次數
  • tol:float, default=1e-4,容忍度,即kmeans運行准則收斂的條件,關於Frobenius范數的相對容差,該范數表示兩個連續迭代的聚類中心的差異,以聲明收斂
  • precompute_distances:{'auto', True, False}, default='auto',是否需要提前計算距離,這個參數會在空間和時間之間做權衡,如果是True 會把整個距離矩陣都放到內存中,auto 會默認在數據樣本大於featurs*samples 的數量大於12e6 的時候False,False 時核心實現的方法是利用Cpython 來實現的
  • verbose:int, default=0,冗長模式(不太懂是啥意思,反正一般不去改默認值)
  • random_state:int, RandomState instance, default=None,確定質心初始化的隨機數生成。使用整數使隨機性具有確定性
  • copy_x:bool, default=True, 對是否修改數據的一個標記,如果True,即復制了就不會修改數據。bool 在scikit-learn 很多接口中都會有這個參數的,就是是否對輸入數據繼續copy 操作,以便不修改用戶的輸入數據。這個要理解Python 的內存機制才會比較清楚
  • n_job:sint, default=None,並行設置
  • algorithm:{'auto', 'full', 'elkan'}, default='auto',kmeans的實現算法,經典的EM風格算法是'full'的。通過使用三角形不等式,'elkan'變異對於定義良好的聚類的數據更有效。但是,由於分配了額外的形狀數組(n_samples,n_clusters),因此需要更多的內存。目前,'auto'(保持向后兼容性)選擇'elkan',但為了更好的啟發式,將來可能會更改

屬性

  • cluster_centers_:ndarray(n_clusters, n_features),集群中心的坐標
  • labels_:ndarray(n_samples,),每個點的標簽
  • inertia_:float,樣本到其最近的聚類中心的平方距離的總和
  • n_iter_:int,運行的迭代次數

方法

  • fit(X[, y, sample_weight]):擬合,計算k均值聚類
  • fit_predict(X[, y, sample_weight]):計算聚類中心並預測每個樣本的聚類索引
  • fit_transform(X[, y, sample_weight]):計算聚類並將X轉換為聚類距離空間
  • get_params([deep]):獲取此估計量的參數
  • predict(X[, sample_weight]):預測X中每個樣本所屬的最近簇
  • score(X[, y, sample_weight]):與K均值目標上X的值相反
  • set_params(**params):設置此估算器的參數
  • transform(X):將X轉換為群集距離空間

也可以看看
MiniBatchKMeans
替代性在線實施,使用微型批次對中心位置進行增量更新。對於大規模學習(例如n_samples> 10k),MiniBatchKMeans可能比默認的批處理實現要快得多。

sklearn.cluster.k_means

sklearn.cluster.k_means(X, n_clusters, *, sample_weight=None, init='k-means++', precompute_distances='deprecated', n_init=10,
max_iter=300, verbose=False, tol=0.0001, random_state=None, copy_x=True, n_jobs='deprecated', algorithm='auto', return_n_iter=False)
  • X:{array-like, sparse} matrix of shape (n_samples, n_features),數組,矩陣,稀疏矩陣
  • n_clusters:int
  • sample_weight:array-like of shape (n_samples,), default=None,X中每個觀測值的權重。如果為None,則為所有觀測值分配相等的權重
  • init:{'k-means++', 'random', ndarray, callable}, default='k-means++'
  • precompute_distances:{'auto', True, False}
  • n_init:int, default=10
  • max_iter:int, default=300
  • verbose:bool, default=False
  • tol:float, default=1e-4
  • random_state:int, RandomState instance, default=None
  • copy_x:bool, default=True
  • n_jobs:int, default=None
  • algorithm:{'auto', 'full', 'elkan'}, default='auto'
  • return_n_iter:bool, default=False

屬性

  • centroid
  • label
  • inertia
  • best_n_iter

k_means這個是先寫的,他們兩的參數就相差一個數據集,不過還是建議用KMeans

五、kmeans可視化

使用iris數據做簡單的聚類,並且畫出聚類后的圖片

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.datasets import load_iris
from sklearn.cluster import KMeans

X=load_iris().data
kmeans = KMeans(n_clusters=3,random_state=0)
kmeans.fit(X)

labels = kmeans.labels_
labels = pd.DataFrame(labels,columns=['labels'])
X=pd.DataFrame(X)
X.insert(4,'labels',labels)

from sklearn.manifold import TSNE
tsne = TSNE()
a = tsne.fit_transform(X)
liris = pd.DataFrame(a,index=X.index)

d1 = liris[X['labels']==0]
#plt.plot(d1[0],d1[1],'r.')
d2 = liris[X['labels']==1]
#plt.plot(d2[0],d2[1],'go')
d3 = liris[X['labels']==2]
#plt.plot(d3[0],d3[1],'b*')
plt.plot(d1[0],d1[1],'r.',d2[0],d2[1],'go',d3[0],d3[1],'b*')

 

 值得注意的是,上面的可視化是將特征縮成一個值,然后在和label畫圖

還有其他的可視化方法

 

# 導入可視化工具包
import matplotlib.pyplot as plt
%matplotlib inline
from sklearn.datasets import load_iris
from sklearn.cluster import KMeans
import numpy as np
import pandas as pd

X=load_iris().data
clf = KMeans(n_clusters=3,random_state=0)
clf.fit(X)
label = clf.predict(X)

# 顏色和標簽列表
colors_list = ['red', 'blue', 'green']
labels_list = ['1','2','3']
x=X
for i in range(3):
    plt.scatter(x[label==i,0], x[label== i,1], s=100,c=colors_list[i],label=labels_list[i])
    
# 聚類中心點
plt.scatter(clf.cluster_centers_[:,0],clf.cluster_centers_[:,1], s=300,c='black',label='Centroids')

plt.legend()
plt.xlabel('Annual Income (k$)')
plt.ylabel('Spending Score (1-100)')
plt.show()

 六、獲取kmeans特征權重,特征貢獻度

有時候我們需要看一下,哪個特征對kmeans貢獻最大,但是如果是使用pca之后的數據做模型,那么就有點難計算,但是pca也是根據變量方差去選擇,也即是說第一主成分的選擇是根據最大方差去選擇,了解這個或許還可以計算出來,

但是我們主要說非pca之后的:

#驗證過,該屬性確實可以計算出來
estimator=KMeans()
estimator.fit(X)
res=estimator.__dict__
print res['cluster_centers_']

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM