1. 程式人生 > >scikit-learn學習之K-means聚類演算法與 Mini Batch K-Means演算法

scikit-learn學習之K-means聚類演算法與 Mini Batch K-Means演算法

======================================================================

本系列部落格主要參考 Scikit-Learn 官方網站上的每一個演算法進行,並進行部分翻譯,如有錯誤,請大家指正   

轉載請註明出處

======================================================================

K-means演算法分析與Python程式碼實現請參考之前的兩篇部落格:

接下來我主要演示怎麼使用Scikit-Learn完成K-means演算法的呼叫

註明:本例分析是固定輸入K值和輸入k個初始中心點,這樣做具有很大的侷限性,容易陷入區域性最優,可以利用其他演算法(如canopy演算法)進行粗聚類估計,產生n個簇,作為k-means的K值,這裡不做詳細說明

一:K-means聚類演算法

1:K-means演算法簡介

       聚類演算法,資料探勘十大演算法之一,演算法需要接受引數k和k個初始聚類中心,即將資料集進行聚類的數目和k個簇的初始聚類“中心”,結果是同一類簇中的物件相似度極高,不同類簇中的資料相似度極低

2:K-means演算法思想和描述

      思想: 以空間中k箇中心點進行聚類,對最靠近他們的物件歸類,通過迭代的方法,逐次更新各聚類中心

      描述:

       (1)適當選擇C個類的初始中心        (2)在第K此迭代中,對任意一個樣本,求其到C各中心的距離,將該樣本歸到距離最短的中心所在的類        (3)利用均值等方法更新該類的中心值        (4)對於所有的C個聚類中心,如果利用(2)(3)的迭代法更新後,值保持不變,則迭代結束,否則繼續迭代

3:集合例項的簡單介紹

                                  例如現在有四種藥物A,B,C,D,他們分別有兩個屬性。如下圖                                                      
                                   將他們表示在座標軸上為:                                                                   
第一次迭代,隨機選取兩個點作為初始中心點,eg c1,c2作為初始中心點,D0中分別為四個點到兩個樣本點的距離,X,Y為橫縱座標                                                                         
           A點離第一個點最近,所以group-1行A點置1,剩下的三個點離第二個中心點最近,所以group-2行置1  
          此時應該更新樣本點,c1不變,c2更新為((2+4+5)/3,(1+3+4)/3)=(11/3,8/3),更新後的資料中心點如下圖紅點所示                                                                         
第二次迭代,以(11/3,8/3)作為樣本中心點,分別計算四個點到樣本中心點的距離,如下圖                                                                          
         A,B點距離第一個中心點最近,C,D點距離第二個中心點最近,所以group-1行,A,B置1,group-2行C,D置1                                                                                           
         此時重新更新樣本中心點,c1=((1+2)/2,(1+1)/2)=(3/2,1),c2=((4+5)/2,(3+4)/2)=(9/2,7/2),更新後的資料中心點如下圖紅點所示                                                                            
第三次迭代,計算同上,略過,此時資料的樣本中心點不再發生變化,所以可以停止迭代,最終聚類情況如下:                                                                

4:下邊看一個使用sklearn.Kmeans的例項(例項來源

例項說明:利用sklearn.datasets.make_blobs產生1500條兩維的資料集進行不同情況下的聚類示例,程式碼如下
<span style="font-size:18px;">#coding:utf-8
'''
Created on 2016/4/25

@author: Gamer Think
'''
import numpy as np      #科學計算包
import matplotlib.pyplot as plt      #python畫圖包

from sklearn.cluster import KMeans       #匯入K-means演算法包
from sklearn.datasets import make_blobs

plt.figure(figsize=(12, 12))

'''
make_blobs函式是為聚類產生資料集
產生一個數據集和相應的標籤
n_samples:表示資料樣本點個數,預設值100
n_features:表示資料的維度,預設值是2
centers:產生資料的中心點,預設值3
cluster_std:資料集的標準差,浮點數或者浮點數序列,預設值1.0
center_box:中心確定之後的資料邊界,預設值(-10.0, 10.0)
shuffle :洗亂,預設值是True
random_state:官網解釋是隨機生成器的種子
更多引數即使請參考:http://scikit-learn.org/dev/modules/generated/sklearn.datasets.make_blobs.html#sklearn.datasets.make_blobs
'''
n_samples = 1500
random_state = 170
X, y = make_blobs(n_samples=n_samples, random_state=random_state)


# Incorrect number of clusters
y_pred = KMeans(n_clusters=2, random_state=random_state).fit_predict(X)

plt.subplot(221)  #在2圖裡新增子圖1
plt.scatter(X[:, 0], X[:, 1], c=y_pred) #scatter繪製散點
plt.title("Incorrect Number of Blobs")   #加標題

# Anisotropicly distributed data
transformation = [[ 0.60834549, -0.63667341], [-0.40887718, 0.85253229]]
X_aniso = np.dot(X, transformation)    #返回的是乘積的形式
y_pred = KMeans(n_clusters=3, random_state=random_state).fit_predict(X_aniso)

plt.subplot(222)#在2圖裡新增子圖2
plt.scatter(X_aniso[:, 0], X_aniso[:, 1], c=y_pred)
plt.title("Anisotropicly Distributed Blobs")

# Different variance
X_varied, y_varied = make_blobs(n_samples=n_samples,
                                cluster_std=[1.0, 2.5, 0.5],
                                random_state=random_state)
y_pred = KMeans(n_clusters=3, random_state=random_state).fit_predict(X_varied)

plt.subplot(223)#在2圖裡新增子圖3
plt.scatter(X_varied[:, 0], X_varied[:, 1], c=y_pred)
plt.title("Unequal Variance")

# Unevenly sized blobs
X_filtered = np.vstack((X[y == 0][:500], X[y == 1][:100], X[y == 2][:10]))
y_pred = KMeans(n_clusters=3, random_state=random_state).fit_predict(X_filtered)

plt.subplot(224)#在2圖裡新增子圖4
plt.scatter(X_filtered[:, 0], X_filtered[:, 1], c=y_pred)
plt.title("Unevenly Sized Blobs")

plt.show() #顯示圖</span>

結果圖示:

二:Mini Batch K-Means演算法

scikit-learn官網上對於Mini Batch K-Means演算法的說明如下:

Mini Batch K-Means演算法是K-Means演算法的變種,採用小批量的資料子集減小計算時間,同時仍試圖優化目標函式,這裡所謂的小批量是指每次訓練演算法時所隨機抽取的資料子集,採用這些隨機產生的子集進行訓練演算法,大大減小了計算時間,與其他演算法相比,減少了k-均值的收斂時間,小批量k-均值產生的結果,一般只略差於標準演算法。

該演算法的迭代步驟有兩步:

1:從資料集中隨機抽取一些資料形成小批量,把他們分配給最近的質心

2:更新質心

與K均值演算法相比,資料的更新是在每一個小的樣本集上。對於每一個小批量,通過計算平均值得到更新質心,並把小批量裡的資料分配給該質心,隨著迭代次數的增加,這些質心的變化是逐漸減小的,直到質心穩定或者達到指定的迭代次數,停止計算

Mini Batch K-Means比K-Means有更快的 收斂速度,但同時也降低了聚類的效果,但是在實際專案中卻表現得不明顯

這是一張k-means和mini batch k-means的實際效果對比圖


下邊給出顯示上邊這副圖的程式碼,也是對K-Means和Mini Batch K-Means演算法的一個比較:

<span style="font-size:18px;">#coding:utf8
'''
Created on 2016/4/26

@author: Gamer Think
'''
import time

import numpy as np
import matplotlib.pyplot as plt

from sklearn.cluster import MiniBatchKMeans, KMeans
from sklearn.metrics.pairwise import pairwise_distances_argmin
from sklearn.datasets.samples_generator import make_blobs

##############################################################################
# Generate sample data
np.random.seed(0)

batch_size = 45
centers = [[1, 1], [-1, -1], [1, -1]] #初始化三個中心
n_clusters = len(centers)       #聚類的數目為3
#產生3000組兩維的資料,以上邊三個點為中心,以(-10,10)為邊界,資料集的標準差是0.7
X, labels_true = make_blobs(n_samples=3000, centers=centers, cluster_std=0.7)

##############################################################################
# Compute clustering with Means

k_means = KMeans(init='k-means++', n_clusters=3, n_init=10)
t0 = time.time() #當前時間
k_means.fit(X)
#使用K-Means 對 3000資料集訓練演算法的時間消耗
t_batch = time.time() - t0

##############################################################################
# Compute clustering with MiniBatchKMeans

mbk = MiniBatchKMeans(init='k-means++', n_clusters=3, batch_size=batch_size,
                      n_init=10, max_no_improvement=10, verbose=0)
t0 = time.time()
mbk.fit(X)
#使用MiniBatchKMeans 對 3000資料集訓練演算法的時間消耗
t_mini_batch = time.time() - t0

##############################################################################
# Plot result

#建立一個繪圖物件, 並設定物件的寬度和高度, 如果不建立直接呼叫plot, Matplotlib會直接建立一個繪圖物件
'''
當繪圖物件中有多個軸的時候,可以通過工具欄中的Configure Subplots按鈕,
互動式地調節軸之間的間距和軸與邊框之間的距離。
如果希望在程式中調節的話,可以呼叫subplots_adjust函式,
它有left, right, bottom, top, wspace, hspace等幾個關鍵字引數,
這些引數的值都是0到1之間的小數,它們是以繪圖區域的寬高為1進行正規化之後的座標或者長度。
'''
fig = plt.figure(figsize=(8, 3))
fig.subplots_adjust(left=0.02, right=0.98, bottom=0.05, top=0.9)
colors = ['#4EACC5', '#FF9C34', '#4E9A06']

# We want to have the same colors for the same cluster from the
# MiniBatchKMeans and the KMeans algorithm. Let's pair the cluster centers per
# closest one.
k_means_cluster_centers = np.sort(k_means.cluster_centers_, axis=0)
mbk_means_cluster_centers = np.sort(mbk.cluster_centers_, axis=0)
k_means_labels = pairwise_distances_argmin(X, k_means_cluster_centers)
mbk_means_labels = pairwise_distances_argmin(X, mbk_means_cluster_centers)
order = pairwise_distances_argmin(k_means_cluster_centers,
                                  mbk_means_cluster_centers)

# KMeans
ax = fig.add_subplot(1, 3, 1) #add_subplot  影象分給為 一行三列,第一塊
for k, col in zip(range(n_clusters), colors):
    my_members = k_means_labels == k
    cluster_center = k_means_cluster_centers[k]
    ax.plot(X[my_members, 0], X[my_members, 1], 'w',
            markerfacecolor=col, marker='.')
    ax.plot(cluster_center[0], cluster_center[1], 'o', markerfacecolor=col,
            markeredgecolor='k', markersize=6)
ax.set_title('KMeans')
ax.set_xticks(())
ax.set_yticks(())
plt.text(-3.5, 1.8,  'train time: %.2fs\ninertia: %f' % (
    t_batch, k_means.inertia_))

# MiniBatchKMeans
ax = fig.add_subplot(1, 3, 2)#add_subplot  影象分給為 一行三列,第二塊
for k, col in zip(range(n_clusters), colors):
    my_members = mbk_means_labels == order[k]
    cluster_center = mbk_means_cluster_centers[order[k]]
    ax.plot(X[my_members, 0], X[my_members, 1], 'w',
            markerfacecolor=col, marker='.')
    ax.plot(cluster_center[0], cluster_center[1], 'o', markerfacecolor=col,
            markeredgecolor='k', markersize=6)
ax.set_title('MiniBatchKMeans')
ax.set_xticks(())
ax.set_yticks(())
plt.text(-3.5, 1.8, 'train time: %.2fs\ninertia: %f' %
         (t_mini_batch, mbk.inertia_))

# Initialise the different array to all False
different = (mbk_means_labels == 4)
ax = fig.add_subplot(1, 3, 3)#add_subplot  影象分給為 一行三列,第三塊

for k in range(n_clusters):
    different += ((k_means_labels == k) != (mbk_means_labels == order[k]))

identic = np.logical_not(different)
ax.plot(X[identic, 0], X[identic, 1], 'w',
        markerfacecolor='#bbbbbb', marker='.')
ax.plot(X[different, 0], X[different, 1], 'w',
        markerfacecolor='m', marker='.')
ax.set_title('Difference')
ax.set_xticks(())
ax.set_yticks(())

plt.show()</span>


更多內容請參考官方網址:http://scikit-learn.org/dev/modules/clustering.html#clustering