機(jī)器學(xué)習(xí)K-means算法在Python中的實(shí)現(xiàn)
K-means算法簡介
K-means是機(jī)器學(xué)習(xí)中一個(gè)比較常用的算法,屬于無監(jiān)督學(xué)習(xí)算法,其常被用于數(shù)據(jù)的聚類,只需為它指定簇的數(shù)量即可自動(dòng)將數(shù)據(jù)聚合到多類中,相同簇中的數(shù)據(jù)相似度較高,不同簇中數(shù)據(jù)相似度較低。
K-menas的優(yōu)缺點(diǎn):
優(yōu)點(diǎn):
- 原理簡單
- 速度快
- 對大數(shù)據(jù)集有比較好的伸縮性
缺點(diǎn):
- 需要指定聚類 數(shù)量K
- 對異常值敏感
- 對初始值敏感
K-means的聚類過程
其聚類過程類似于梯度下降算法,建立代價(jià)函數(shù)并通過迭代使得代價(jià)函數(shù)值越來越小
- 適當(dāng)選擇c個(gè)類的初始中心;
- 在第k次迭代中,對任意一個(gè)樣本,求其到c個(gè)中心的距離,將該樣本歸到距離最短的中心所在的類;
- 利用均值等方法更新該類的中心值;
- 對于所有的c個(gè)聚類中心,如果利用(2)(3)的迭代法更新后,值保持不變,則迭代結(jié)束,否則繼續(xù)迭代。
該算法的***優(yōu)勢在于簡潔和快速。算法的關(guān)鍵在于初始中心的選擇和距離公式。
K-means 實(shí)例展示
python中km的一些參數(shù):
- sklearn.cluster.KMeans(
- n_clusters=8,
- init='k-means++',
- n_init=10,
- max_iter=300,
- tol=0.0001,
- precompute_distances='auto',
- verbose=0,
- random_state=None,
- copy_x=True,
- n_jobs=1,
- algorithm='auto'
- )
- n_clusters: 簇的個(gè)數(shù),即你想聚成幾類
- init: 初始簇中心的獲取方法
- n_init: 獲取初始簇中心的更迭次數(shù),為了彌補(bǔ)初始質(zhì)心的影響,算法默認(rèn)會初始10個(gè)質(zhì)心,實(shí)現(xiàn)算法,然后返回***的結(jié)果。
- max_iter: ***迭代次數(shù)(因?yàn)閗means算法的實(shí)現(xiàn)需要迭代)
- tol: 容忍度,即kmeans運(yùn)行準(zhǔn)則收斂的條件
- precompute_distances:是否需要提前計(jì)算距離,這個(gè)參數(shù)會在空間和時(shí)間之間做權(quán)衡,如果是True 會把整個(gè)距離矩陣都放到內(nèi)存中,auto 會默認(rèn)在數(shù)據(jù)樣本大于featurs*samples 的數(shù)量大于12e6 的時(shí)候False,False 時(shí)核心實(shí)現(xiàn)的方法是利用Cpython 來實(shí)現(xiàn)的
- verbose: 冗長模式(不太懂是啥意思,反正一般不去改默認(rèn)值)
- random_state: 隨機(jī)生成簇中心的狀態(tài)條件。
- copy_x: 對是否修改數(shù)據(jù)的一個(gè)標(biāo)記,如果True,即復(fù)制了就不會修改數(shù)據(jù)。bool 在scikit-learn 很多接口中都會有這個(gè)參數(shù)的,就是是否對輸入數(shù)據(jù)繼續(xù)copy 操作,以便不修改用戶的輸入數(shù)據(jù)。這個(gè)要理解Python 的內(nèi)存機(jī)制才會比較清楚。
- n_jobs: 并行設(shè)置
- algorithm: kmeans的實(shí)現(xiàn)算法,有:’auto’, ‘full’, ‘elkan’, 其中 ‘full’表示用EM方式實(shí)現(xiàn)
雖然有很多參數(shù),但是都已經(jīng)給出了默認(rèn)值。所以我們一般不需要去傳入這些參數(shù),參數(shù)的。可以根據(jù)實(shí)際需要來調(diào)用。
下面展示一個(gè)代碼例子
- from sklearn.cluster import KMeans
- from sklearn.externals import joblib
- from sklearn import cluster
- import numpy as np
- # 生成10*3的矩陣
- data = np.random.rand(10,3)
- print data
- # 聚類為4類
- estimator=KMeans(n_clusters=4)
- # fit_predict表示擬合+預(yù)測,也可以分開寫
- res=estimator.fit_predict(data)
- # 預(yù)測類別標(biāo)簽結(jié)果
- lable_pred=estimator.labels_
- # 各個(gè)類別的聚類中心值
- centroids=estimator.cluster_centers_
- # 聚類中心均值向量的總和
- inertia=estimator.inertia_
- print lable_pred
- print centroids
- print inertia
- 代碼執(zhí)行結(jié)果
- [0 2 1 0 2 2 0 3 2 0]
- [[ 0.3028348 0.25183096 0.62493622]
- [ 0.88481287 0.70891813 0.79463764]
- [ 0.66821961 0.54817207 0.30197415]
- [ 0.11629904 0.85684903 0.7088385 ]]
- 0.570794546829
為了更直觀的描述,這次在圖上做一個(gè)展示,由于圖像上繪制二維比較直觀,所以數(shù)據(jù)調(diào)整到了二維,選取100個(gè)點(diǎn)繪制,聚類類別為3類
- from sklearn.cluster import KMeans
- from sklearn.externals import joblib
- from sklearn import cluster
- import numpy as np
- import matplotlib.pyplot as plt
- data = np.random.rand(100,2)
- estimator=KMeans(n_clusters=3)
- res=estimator.fit_predict(data)
- lable_pred=estimator.labels_
- centroids=estimator.cluster_centers_
- inertia=estimator.inertia_
- #print res
- print lable_pred
- print centroids
- print inertia
- for i in range(len(data)):
- if int(lable_pred[i])==0:
- plt.scatter(data[i][0],data[i][1],color='red')
- if int(lable_pred[i])==1:
- plt.scatter(data[i][0],data[i][1],color='black')
- if int(lable_pred[i])==2:
- plt.scatter(data[i][0],data[i][1],color='blue')
- plt.show()
可以看到聚類效果還是不錯(cuò)的,對k-means的聚類效率進(jìn)行了一個(gè)測試,將維度擴(kuò)寬到50維
對于***的數(shù)據(jù),擬合時(shí)間還是能夠接受的,可見效率還是不錯(cuò),對模型的保存與其它的機(jī)器學(xué)習(xí)算法模型保存類似
- from sklearn.externals import joblib
- joblib.dump(km,"model/km_model.m")