1. 程式人生 > >【機器學習】K均值演算法

【機器學習】K均值演算法

K均值演算法是最基礎的一種聚類演算法。具體演算法描述就不提了,資料實在太多,這裡說一下它的特點和侷限性。

一、K均值的特點

1、容易陷入區域性最小值

之所以陷入區域性最小值,是因為初始值設定的有問題,即初始的K個base點在屬性空間中的位置直接影響了最終的聚類結果。所以可以隨機多次進行K均值聚類,選取各種不同的初始值,產生不同的聚類結果。選擇一個代價函式(代價函式就是總的距離差的平方和)最小的一個,作為最終的結果。

如果根據計算機自主隨機初始化,雖然根據概率統計有機率遍歷所有可能的聚類結果,但是這樣的代價依然比較大。此時可以採取一些措施減少一些不必要的K均值聚類。我們知道,之所以聚類的結果不同,主要是因為K個base點之間的距離有較大影響,所以我們可以人為地去調整每兩個K樣本之間的距離最小,而另外一些則比較大。因此,一種較好的新增人為初始化,所構造的knn的次數是K(K-1)。如果是純初始化,則次數應當更多

2、計算距離的方法

如果是離散屬性,直接計算屬性差值,如果是連續屬性,則計算歸一化距離,因為在計算距離時應當保證所有屬性的公平對待。如果需要區別對待,則需要在屬性上加一個權值。

該演算法的複雜度就在於每次都要計算距離,這個計算量也是比較大的。

二、程式碼

直接使用sklearn中的包。當然我們可以自己去造輪子,而且有這樣的事例程式碼,但是代價是泛化效能不好,侷限性太強,執行速度太慢,沒有效能優化。

引數解釋:

(1)n_clusters : 整數型別,指將當前的資料分成多少類,預設是8類。

(2)init : 可選的取值有'k-means++', 'random' 或一個ndarray型別。它指的是初始化中心base點的方法。'k-means++' 是指以函式庫內部優化的方法選取初始化點,這種方法可以減少嘗試的次數。'random' 是指從樣本集中隨機選擇一些樣本點作為base值。另外一種就是直接給定一個ndarray型別的矩陣,這個矩陣是 (n_clusters, n_features) 維的,也就是說,可以不指定樣本點,而是直接在屬性空間中隨機指定,靈活性大大增加。

(3)n_init : 整數型別,預設值是10,指的是K-means演算法執行的次數,即選取不同的初始值,得到聚類結果的次數,選取10次執行中效果最好的一次,評價標準是inertia,就是上面所述的代價函式。

(4)max_iter : 整數型別,預設是300,指的是每次執行演算法最大的迭代次數。

(5)tol : 浮點數,預設是1e-4,指的是前後兩次迭代,inertia的差值,如果小於tol,則停止迭代,即代價精度。

(6)precompute_distances: 有兩種取值,'auto',或者布林型別的True,False。這個指的是預先計算樣本點之間的距離。如果預先計算,則演算法執行更快,但是空間消耗較大。所謂的預先計算precompute,就是把運算時,之前計算過的一些距離記錄下來,之後處理時用到了,就不用再計算了,典型的一種空間換時間的方法。

     其中,'auto' 指的是當 n_samples * n_clusters > 12000000時才進行預計算,否則不計算。這對應著額外的100M的記憶體。True即指總是要採用這種方法提升速度,False 就是記憶體太珍貴,總是不用這種方法。當然,我們也可以在原始碼中修改這個auto中的數值。

(7)verbose : 預設是0,可選取其它整數。顯示詳細的訓練資訊。

(8)random_state : 和其它機器學習演算法中使用隨機狀態的引數相同,主要是為了給演算法提供不同的選取隨機數的方法,以實現資料的復現,更新等等。

(9)copy_x : 布林型別,預設是True。該引數影響的是樣本資料的中心化。如果選擇True,則樣本資料正常處理,沒有任何影響。如果為False,資料就會被中心化,所謂中心化就是求出每一個屬性的期望,然後用樣本的該屬性值減去期望值,得到的資料就是中心化的資料。但是當選擇False的時候,資料僅僅是在處理時經過了中心化,但並不會改變樣本資料集中本來的面目。

(10)n_jobs : 整數,指的是計算機執行的作業數。一個cpu在一個時刻只能執行一個job作業。如果引數選擇為-1,那麼計算機中所有的CPU都參與了該演算法的訓練。如果取1,即只有1個CPU在執行,也就是單程序,並且Python直譯器是單執行緒的,也就是說單執行緒執行。如果引數小於-1,那麼(計算機中CPU的個數+1+n_jobs)即是計算機中執行的作業數。比如我的計算機是4核的,引數取值為-2,此時有3個CPU參與了此次訓練。

(11)algorithm : 可選的值有"auto", "full" or "elkan", 預設是"auto"。指選擇哪種演算法進行訓練。如果使用經典的EM演算法,引數選"full"。"elkan" variation是什麼演算法,我也不知道,根據sklearn包的說明,可知該演算法必須在滿足距離的三角不等式前提下使用,如果不滿足,則不可使用。一般不用在稀疏資料上。"auto" 指的是在稠密資料上選擇"elkan",稀疏資料上選擇EM演算法。

該方法的屬性解釋:

cluster_centers_ : array, [n_clusters,n_features]顯示訓練完成後的聚類中心

labels_ :每個樣本點聚類的結果

inertia_ : 代價函式,樣本點到其自己類中心點的距離之和。

from sklearn.cluster import KMeans
from sklearn import datasets
import numpy as np
import pylab as pl

print "+++++++++++++++++++ 第一個例子 +++++++++++++++++++++"
X1 = np.array([[1, 2], [1, 4], [1, 0],
               [4, 2], [4, 4], [4, 0]])
kmeans = KMeans(n_clusters=2, random_state=0, verbose=3).fit(X1)
print "聚類的標籤:", kmeans.labels_
Y1 = kmeans.labels_

xx = np.array([[0, 0], [4, 4]])
yy = kmeans.predict(xx)
print "預測未知樣本屬於哪一類:", yy
print "指出每一類的聚類中心:\n", kmeans.cluster_centers_

pl.scatter(xx[:, 0],  # 正類的支援向量
xx[:, 1],  # 反類的支援向量
s=120,  # 點的半徑大小
facecolors='blue')  # face colors,支援向量的樣本點的顏色
pl.scatter(X1[:, 0],  # 樣本集的 x 軸資料
X1[:, 1],  # 樣本集的 y 軸資料
c=Y1,  # 分類結果集
s=60,
           cmap=pl.cm.Paired)  # cmap 確定顏色
pl.axis('tight')
pl.show()

print "+++++++++++++++++++ 第二個例子 +++++++++++++++++++++"
X2 = datasets.load_iris()
kmeans = KMeans(n_clusters=3, init='k-means++', algorithm='elkan', random_state=0,copy_x=False).fit(X2.data)
print "聚類的標籤:", kmeans.labels_
Y = kmeans.labels_3
for i in xrange(150):
if Y[i] == 1:
Y[i] = 0
elif Y[i] == 0:
Y[i] = 1
a = 0
print Y
print X2.target
for _ in xrange(150):
if Y[_] == X2.target[_]:
pass
    else:
a += 1
precision = float(len(Y) - a) / len(Y)
print "聚類的精度:", precision