scikit-learn主要由分類、回歸、聚類和降維四大部分組成,其中分類和回歸屬於有監督學習范疇,聚類屬於無監督學習范疇,降維適用於有監督學習和無監督學習。scikit-learn的結構示意圖如下所示:
scikit-learn中的聚類算法主要有:
- K-Means(cluster.KMeans)
- AP聚類(cluster.AffinityPropagation)
- 均值漂移(cluster.MeanShift)
- 層次聚類(cluster.AgglomerativeClustering)
- DBSCAN(cluster.DBSCAN)
- BRICH(cluster.Brich)
- 譜聚類(cluster.Spectral.Clustering)
- 高斯混合模型(GMM)∈期望最大化(EM)算法(mixture.GaussianMixture)
1. K-Means
1.1 簡介
K 均值聚類(K-Means Clustering)是最基礎和最經典的基於划分的聚類算法,是十大經典數據挖掘算法之一。它的基本思想是,通過迭代方式尋找K個簇的一種划分方案,使得聚類結果對應的代價函數最小。特別地,代價函數可以定義為各個樣本距離所屬簇中心點的誤差平方和(SSE)。
1.2 算法原理
- 數據預處理,如歸一化、離散點處理等(優化)
- 隨機選擇k個簇的質心
- 遍歷所有樣本,把樣本划分到距離最近的一個質心
- 划分之后就有K個簇,計算每個簇的平均值作為新的質心
- 重復步驟3、4,直到達到停止條件
迭代停止條件:
- 聚類中心不再發生變化
- 所有的距離最小
- 迭代次數達到設定值
1.3 算法特點
- Distances between points(點之間的距離)
優點:
- 算法容易理解,聚類效果不錯
- 具有出色的速度:O(NKt)
- 當簇近似高斯分布時,效果比較好
缺點:
- 需要人工預先確定初試K值,且該值和真是的數據分布未必吻合
- 對初始中心點敏感
- 不適合發現非凸形狀的簇或者大小差別較大的簇
- 特殊值/離散值(噪點)對模型的影響比較大
- 算法只能收斂到局部最優,效果受初始值影響很大
- 從數據先驗的角度來說,在 Kmeans 中,我們假設各個 cluster 的先驗概率是一樣的,但是各個 cluster 的數據量可能是不均勻的。舉個例子,cluster A 中包含了10000個樣本,cluster B 中只包含了100個。那么對於一個新的樣本,在不考慮其與A cluster、 B cluster 相似度的情況,其屬於 cluster A 的概率肯定是要大於 cluster B的。
1.4 適用場景
- 通用, 均勻的 cluster size(簇大小), flat geometry(平面幾何), 不是太多的 clusters(簇)
- 非常大的 n_samples、中等的 n_clusters 使用 MiniBatch code
- 樣本量<10K時使用k-means,>=10K時用MiniBatchKMeans
- 不太適用於離散分類
1.5 測試代碼

1 print(__doc__) 2 3 # Author: Phil Roth <mr.phil.roth@gmail.com> 4 # License: BSD 3 clause 5 6 import numpy as np 7 import matplotlib.pyplot as plt 8 9 from sklearn.cluster import KMeans 10 from sklearn.datasets import make_blobs 11 12 plt.figure(figsize=(12, 12)) 13 14 n_samples = 1500 15 random_state = 170 16 X, y = make_blobs(n_samples=n_samples, random_state=random_state) 17 18 # Incorrect number of clusters 19 y_pred = KMeans(n_clusters=2, random_state=random_state).fit_predict(X) 20 21 plt.subplot(221) 22 plt.scatter(X[:, 0], X[:, 1], c=y_pred) 23 plt.title("Incorrect Number of Blobs") 24 25 # Anisotropicly distributed data 26 transformation = [[0.60834549, -0.63667341], [-0.40887718, 0.85253229]] 27 X_aniso = np.dot(X, transformation) 28 y_pred = KMeans(n_clusters=3, random_state=random_state).fit_predict(X_aniso) 29 30 plt.subplot(222) 31 plt.scatter(X_aniso[:, 0], X_aniso[:, 1], c=y_pred) 32 plt.title("Anisotropicly Distributed Blobs") 33 34 # Different variance 35 X_varied, y_varied = make_blobs(n_samples=n_samples, 36 cluster_std=[1.0, 2.5, 0.5], 37 random_state=random_state) 38 y_pred = KMeans(n_clusters=3, random_state=random_state).fit_predict(X_varied) 39 40 plt.subplot(223) 41 plt.scatter(X_varied[:, 0], X_varied[:, 1], c=y_pred) 42 plt.title("Unequal Variance") 43 44 # Unevenly sized blobs 45 X_filtered = np.vstack((X[y == 0][:500], X[y == 1][:100], X[y == 2][:10])) 46 y_pred = KMeans(n_clusters=3, 47 random_state=random_state).fit_predict(X_filtered) 48 49 plt.subplot(224) 50 plt.scatter(X_filtered[:, 0], X_filtered[:, 1], c=y_pred) 51 plt.title("Unevenly Sized Blobs") 52 53 plt.show()
2. AP聚類
2.1 簡介
AP(Affinity Propagation)通常被翻譯為近鄰傳播算法或者親和力傳播算法,是在2007年的Science雜志上提出的一種新的聚類算法。AP算法的基本思想是將全部數據點都當作潛在的聚類中心(稱之為exemplar),然后數據點兩兩之間連線構成一個網絡(相似度矩陣),再通過網絡中各條邊的消息(responsibility和availability)傳遞計算出各樣本的聚類中心。
2.2 算法原理
3個概念:
- 吸引度(responsibility)矩陣R:其中r(i,k)描述了數據對象k適合作為數據對象i的聚類中心的程度,表示的是從i到k的消息。
- 歸屬度(availability)矩陣A:其中a(i,k)描述了數據對象i選擇數據對象k作為其據聚類中心的適合程度,表示從k到i的消息。
- 相似度(similarity)矩陣S:通常S(i,j)取i,j的歐氏距離的負值,當i=j時,通常取整個矩陣的最小值或者中位數(Scikit-learn中默認為中位數),取得值越大則最終產生的類數量越多。
算法步驟:
1. 算法初始,吸引度矩陣和歸屬度矩陣均初始化為0矩陣。
2. 更新吸引度矩陣
3. 更新歸屬度矩陣
4. 根據衰減系數λ對兩個公式進行衰減
5. 重復步驟2/3/4直至矩陣穩定或者達到最大迭代次數,算法結束。最終取a+r最大的k作為聚類中心。
2.3 算法特點
- Graph distance (e.g. nearest-neighbor graph)(圖形距離(例如,最近鄰圖))
優點:
- 與其他聚類算法不同,AP聚類不需要指定K(經典的K-Means)或者是其他描述聚類個數的參數
- 一個聚類中最具代表性的點在AP算法中叫做Examplar,與其他算法中的聚類中心不同,examplar是原始數據中確切存在的一個數據點,而不是由多個數據點求平均而得到的聚類中心
- 多次執行AP聚類算法,得到的結果完全一樣的,即不需要進行隨機選取初值步驟.
- AP算法相對於Kmeans優勢是不需要指定聚類數量,對初始值不敏感
- 模型對數據的初始值不敏感。
- 對初始相似度矩陣數據的對稱性沒有要求。
- 相比與k-centers聚類方法,其結果的平方差誤差較小。
缺點:
- AP算法需要事先計算每對數據對象之間的相似度,如果數據對象太多的話,內存放不下,若存在數據庫,頻繁訪問數據庫也需要時間。
- AP算法的時間復雜度較高,一次迭代大概O(N3)
- 聚類的好壞受到參考度和阻尼系數的影響
2.4 適用場景
- 許多簇,不均勻的簇大小,非平面幾何
- 不可擴展的 n_samples
- 特別適合高維、多類數據快速聚類
- 圖像、文本、生物信息學、人臉識別、基因發現、搜索最優航線、 碼書設計以及實物圖像識別等領域
2.5 測試代碼

1 # -*- coding:utf-8 -*- 2 3 import numpy as np 4 import matplotlib.pyplot as plt 5 import sklearn.datasets as ds 6 import matplotlib.colors 7 from sklearn.cluster import AffinityPropagation 8 from sklearn.metrics import euclidean_distances 9 10 #聚類算法之AP算法: 11 #1--與其他聚類算法不同,AP聚類不需要指定K(金典的K-Means)或者是其他描述聚類個數的參數 12 #2--一個聚類中最具代表性的點在AP算法中叫做Examplar,與其他算法中的聚類中心不同,examplar 13 #是原始數據中確切存在的一個數據點,而不是由多個數據點求平均而得到的聚類中心 14 #3--多次執行AP聚類算法,得到的結果完全一樣的,即不需要進行隨機選取初值步驟. 15 #算法復雜度較高,為O(N*N*logN),而K-Means只是O(N*K)的復雜度,當N》3000時,需要算很久 16 #AP算法相對於Kmeans優勢是不需要指定聚類數量,對初始值不敏感 17 18 #AP算法應用場景:圖像、文本、生物信息學、人臉識別、基因發現、搜索最優航線、 碼書設計以及實物圖像識別等領域 19 20 #算法詳解: http://blog.csdn.net/helloeveryon/article/details/51259459 21 22 if __name__=='__main__': 23 #scikit中的make_blobs方法常被用來生成聚類算法的測試數據,直觀地說,make_blobs會根據用戶指定的特征數量、 24 # 中心點數量、范圍等來生成幾類數據,這些數據可用於測試聚類算法的效果。 25 #函數原型:sklearn.datasets.make_blobs(n_samples=100, n_features=2, 26 # centers=3, cluster_std=1.0, center_box=(-10.0, 10.0), shuffle=True, random_state=None)[source] 27 #參數解析: 28 # n_samples是待生成的樣本的總數。 29 # 30 # n_features是每個樣本的特征數。 31 # 32 # centers表示類別數。 33 # 34 # cluster_std表示每個類別的方差,例如我們希望生成2類數據,其中一類比另一類具有更大的方差,可以將cluster_std設置為[1.0, 3.0]。 35 36 N=400 37 centers = [[1, 2], [-1, -1], [1, -1], [-1, 1]] 38 #生成聚類算法的測試數據 39 data,y=ds.make_blobs(N,n_features=2,centers=centers,cluster_std=[0.5, 0.25, 0.7, 0.5],random_state=0) 40 #計算向量之間的距離 41 m=euclidean_distances(data,squared=True) 42 #求中位數 43 preference=-np.median(m) 44 print 'Preference:',preference 45 46 matplotlib.rcParams['font.sans-serif'] = [u'SimHei'] 47 matplotlib.rcParams['axes.unicode_minus'] = False 48 plt.figure(figsize=(12,9),facecolor='w') 49 for i,mul in enumerate(np.linspace(1,4,9)):#遍歷等差數列 50 print 'mul=',mul 51 p=mul*preference 52 model=AffinityPropagation(affinity='euclidean',preference=p) 53 af=model.fit(data) 54 center_indices=af.cluster_centers_indices_ 55 n_clusters=len(center_indices) 56 print ('p=%.1f'%mul),p,'聚類簇的個數為:',n_clusters 57 y_hat=af.labels_ 58 59 plt.subplot(3,3,i+1) 60 plt.title(u'Preference:%.2f,簇個數:%d' % (p, n_clusters)) 61 clrs=[] 62 for c in np.linspace(16711680, 255, n_clusters): 63 clrs.append('#%06x' % c) 64 for k, clr in enumerate(clrs): 65 cur = (y_hat == k) 66 plt.scatter(data[cur, 0], data[cur, 1], c=clr, edgecolors='none') 67 center = data[center_indices[k]] 68 for x in data[cur]: 69 plt.plot([x[0], center[0]], [x[1], center[1]], color=clr, zorder=1) 70 plt.scatter(data[center_indices, 0], data[center_indices, 1], s=100, c=clrs, marker='*', edgecolors='k', 71 zorder=2) 72 plt.grid(True) 73 plt.tight_layout() 74 plt.suptitle(u'AP聚類', fontsize=20) 75 plt.subplots_adjust(top=0.92) 76 plt.show()
3. 均值漂移(Mean-shift)
3.1 簡介
Mean-shift(即:均值遷移)的基本思想:在數據集中選定一個點,然后以這個點為圓心,r為半徑,畫一個圓(二維下是圓),求出這個點到所有點的向量的平均值,而圓心與向量均值的和為新的圓心,然后迭代此過程,直到滿足一點的條件結束。(Fukunage在1975年提出)
后來Yizong Cheng 在此基礎上加入了 核函數 和 權重系數 ,使得Mean-shift 算法開始流行起來。目前它在聚類、圖像平滑、分割、跟蹤等方面有着廣泛的應用。
3.2 算法原理
為了方便大家理解,借用下幾張圖來說明Mean-shift的基本過程。
由上圖可以很容易看到,Mean-shift 算法的核心思想就是不斷的尋找新的圓心坐標,直到密度最大的區域。
3.3 算法特點
- Distances between points(點之間的距離)
- 圓心(或種子)的確定和半徑(或帶寬)的選擇,是影響算法效率的兩個主要因素。
- 該算法不是高度可擴展的,因為在執行算法期間需要執行多個最近鄰搜索。
- 該算法保證收斂,但是當質心的變化較小時,算法將停止迭代。
- 通過找到給定樣本的最近質心來給新樣本打上標簽。
3.4 適用場景
- 許多簇,不均勻的簇大小,非平面幾何
- 不可擴展的 n_samples
- 適用於類別數量未知,且樣本數量<10K
- 目前它在聚類、圖像平滑、分割、跟蹤等方面有着廣泛的應用。
3.5 測試代碼

1 print(__doc__) 2 3 import numpy as np 4 from sklearn.cluster import MeanShift, estimate_bandwidth 5 from sklearn.datasets.samples_generator import make_blobs 6 7 # ############################################################################# 8 # Generate sample data 9 centers = [[1, 1], [-1, -1], [1, -1]] 10 X, _ = make_blobs(n_samples=10000, centers=centers, cluster_std=0.6) 11 12 # ############################################################################# 13 # Compute clustering with MeanShift 14 15 # The following bandwidth can be automatically detected using 16 bandwidth = estimate_bandwidth(X, quantile=0.2, n_samples=500) 17 18 ms = MeanShift(bandwidth=bandwidth, bin_seeding=True) 19 ms.fit(X) 20 labels = ms.labels_ 21 cluster_centers = ms.cluster_centers_ 22 23 labels_unique = np.unique(labels) 24 n_clusters_ = len(labels_unique) 25 26 print("number of estimated clusters : %d" % n_clusters_) 27 28 # ############################################################################# 29 # Plot result 30 import matplotlib.pyplot as plt 31 from itertools import cycle 32 33 plt.figure(1) 34 plt.clf() 35 36 colors = cycle('bgrcmykbgrcmykbgrcmykbgrcmyk') 37 for k, col in zip(range(n_clusters_), colors): 38 my_members = labels == k 39 cluster_center = cluster_centers[k] 40 plt.plot(X[my_members, 0], X[my_members, 1], col + '.') 41 plt.plot(cluster_center[0], cluster_center[1], 'o', markerfacecolor=col, 42 markeredgecolor='k', markersize=14) 43 plt.title('Estimated number of clusters: %d' % n_clusters_) 44 plt.show()
4. 層次聚類
4.1 簡介
Hierarchical Clustering(層次聚類):就是按照某種方法進行層次分類,直到滿足某種條件為止。
主要分為兩類:
- 凝聚:從下到上。首先將每個對象作為一個簇,然后合並這些原子簇為越來越大的簇,直到所有的對象都在一個簇中,或者某個終結條件被滿足。
- 分裂:從上到下。首先將所有對象置於同一個簇中,然后逐漸細分為越來越小的簇,直到每個對象自成一簇,或者達到了某個終止條件。(較少用)
4.2 算法原理(凝聚)
- 將每個對象歸為一類, 共得到N類, 每類僅包含一個對象. 類與類之間的距離就是它們所包含的對象之間的距離.
- 找到最接近的兩個類並合並成一類, 於是總的類數少了一個.
- 重新計算新的類與所有舊類之間的距離.
- 重復第2步和第3步, 直到最后合並成一個類為止(此類包含了N個對象).
圖解過程:
4.3 算法特點
- Distances between points(點之間的距離)
4.4 適用場景
- 很多的簇,可能連接限制
- 大的 n_samples 和 n_clusters
4.5 測試代碼

1 # Authors: Gael Varoquaux 2 # License: BSD 3 clause (C) INRIA 2014 3 4 print(__doc__) 5 from time import time 6 7 import numpy as np 8 from scipy import ndimage 9 from matplotlib import pyplot as plt 10 11 from sklearn import manifold, datasets 12 13 digits = datasets.load_digits(n_class=10) 14 X = digits.data 15 y = digits.target 16 n_samples, n_features = X.shape 17 18 np.random.seed(0) 19 20 def nudge_images(X, y): 21 # Having a larger dataset shows more clearly the behavior of the 22 # methods, but we multiply the size of the dataset only by 2, as the 23 # cost of the hierarchical clustering methods are strongly 24 # super-linear in n_samples 25 shift = lambda x: ndimage.shift(x.reshape((8, 8)), 26 .3 * np.random.normal(size=2), 27 mode='constant', 28 ).ravel() 29 X = np.concatenate([X, np.apply_along_axis(shift, 1, X)]) 30 Y = np.concatenate([y, y], axis=0) 31 return X, Y 32 33 34 X, y = nudge_images(X, y) 35 36 37 #---------------------------------------------------------------------- 38 # Visualize the clustering 39 def plot_clustering(X_red, labels, title=None): 40 x_min, x_max = np.min(X_red, axis=0), np.max(X_red, axis=0) 41 X_red = (X_red - x_min) / (x_max - x_min) 42 43 plt.figure(figsize=(6, 4)) 44 for i in range(X_red.shape[0]): 45 plt.text(X_red[i, 0], X_red[i, 1], str(y[i]), 46 color=plt.cm.nipy_spectral(labels[i] / 10.), 47 fontdict={'weight': 'bold', 'size': 9}) 48 49 plt.xticks([]) 50 plt.yticks([]) 51 if title is not None: 52 plt.title(title, size=17) 53 plt.axis('off') 54 plt.tight_layout(rect=[0, 0.03, 1, 0.95]) 55 56 #---------------------------------------------------------------------- 57 # 2D embedding of the digits dataset 58 print("Computing embedding") 59 X_red = manifold.SpectralEmbedding(n_components=2).fit_transform(X) 60 print("Done.") 61 62 from sklearn.cluster import AgglomerativeClustering 63 64 for linkage in ('ward', 'average', 'complete', 'single'): 65 clustering = AgglomerativeClustering(linkage=linkage, n_clusters=10) 66 t0 = time() 67 clustering.fit(X_red) 68 print("%s :\t%.2fs" % (linkage, time() - t0)) 69 70 plot_clustering(X_red, clustering.labels_, "%s linkage" % linkage) 71 72 73 plt.show()
5. DBSCAN
5.1 簡介
DBSCAN(Density-Based Spatial Clustering of Applications with Noise,具有噪聲的基於密度的聚類方法)是一種基於密度的空間聚類算法。該算法將具有足夠密度的區域划分為簇(即要求聚類空間中的一定區域內所包含對象的數目不小於某一給定閾值),並在具有噪聲的空間數據庫中發現任意形狀的簇,它將簇定義為密度相連的點的最大集合。
5.2 算法原理
算法步驟:
DBSCAN需要二個參數:掃描半徑 (eps)和最小包含點數(min_samples)
- 遍歷所有點,尋找核心點
- 連通核心點,並且在此過程中擴展某個分類集合中點的個數
圖解過程:
5.3 算法特點
- Distances between nearest points(最近點之間的距離)
優點:
- 可以發現任意形狀的聚類
缺點:
- 隨着數據量的增加,對I/O、內存的要求也隨之增加。
- 如果密度分布不均勻,聚類效果較差
5.4 適用場景
- 非平面幾何,不均勻的簇大小
- 非常大的 n_samples, 中等的 n_clusters
5.5 測試代碼

1 from sklearn.datasets.samples_generator import make_blobs 2 from sklearn.cluster import DBSCAN 3 import numpy as np 4 import matplotlib.pyplot as plt 5 from itertools import cycle ##python自帶的迭代器模塊 6 from sklearn.preprocessing import StandardScaler 7 8 ##產生隨機數據的中心 9 centers = [[1, 1], [-1, -1], [1, -1]] 10 ##產生的數據個數 11 n_samples=750 12 ##生產數據:此實驗結果受cluster_std的影響,或者說受eps 和cluster_std差值影響 13 X, lables_true = make_blobs(n_samples=n_samples, centers= centers, cluster_std=0.4, 14 random_state =0) 15 16 17 ##設置分層聚類函數 18 db = DBSCAN(eps=0.3, min_samples=10) 19 ##訓練數據 20 db.fit(X) 21 ##初始化一個全是False的bool類型的數組 22 core_samples_mask = np.zeros_like(db.labels_, dtype=bool) 23 ''' 24 這里是關鍵點(針對這行代碼:xy = X[class_member_mask & ~core_samples_mask]): 25 db.core_sample_indices_ 表示的是某個點在尋找核心點集合的過程中暫時被標為噪聲點的點(即周圍點 26 小於min_samples),並不是最終的噪聲點。在對核心點進行聯通的過程中,這部分點會被進行重新歸類(即標簽 27 並不會是表示噪聲點的-1),也可也這樣理解,這些點不適合做核心點,但是會被包含在某個核心點的范圍之內 28 ''' 29 core_samples_mask[db.core_sample_indices_] = True 30 31 ##每個數據的分類 32 lables = db.labels_ 33 34 ##分類個數:lables中包含-1,表示噪聲點 35 n_clusters_ =len(np.unique(lables)) - (1 if -1 in lables else 0) 36 37 ##繪圖 38 unique_labels = set(lables) 39 ''' 40 1)np.linspace 返回[0,1]之間的len(unique_labels) 個數 41 2)plt.cm 一個顏色映射模塊 42 3)生成的每個colors包含4個值,分別是rgba 43 4)其實這行代碼的意思就是生成4個可以和光譜對應的顏色值 44 ''' 45 colors = plt.cm.Spectral(np.linspace(0, 1, len(unique_labels))) 46 47 plt.figure(1) 48 plt.clf() 49 50 51 for k, col in zip(unique_labels, colors): 52 ##-1表示噪聲點,這里的k表示黑色 53 if k == -1: 54 col = 'k' 55 56 ##生成一個True、False數組,lables == k 的設置成True 57 class_member_mask = (lables == k) 58 59 ##兩個數組做&運算,找出即是核心點又等於分類k的值 markeredgecolor='k', 60 xy = X[class_member_mask & core_samples_mask] 61 plt.plot(xy[:, 0], xy[:, 1], 'o', c=col,markersize=14) 62 ''' 63 1)~優先級最高,按位對core_samples_mask 求反,求出的是噪音點的位置 64 2)& 於運算之后,求出雖然剛開始是噪音點的位置,但是重新歸類卻屬於k的點 65 3)對核心分類之后進行的擴展 66 ''' 67 xy = X[class_member_mask & ~core_samples_mask] 68 plt.plot(xy[:, 0], xy[:, 1], 'o', c=col,markersize=6) 69 70 plt.title('Estimated number of clusters: %d' % n_clusters_) 71 plt.show()
6. BRICH
6.1 簡介
Birch(利用層次方法的平衡迭代規約和聚類):就是通過聚類特征(CF)形成一個聚類特征樹,root層的CF個數就是聚類個數。
6.2 算法原理
相關概念
聚類特征(CF):每一個CF是一個三元組,可以用(N,LS,SS)表示.其中N代表了這個CF中擁有的樣本點的數量;LS代表了這個CF中擁有的樣本點各特征維度的和向量,SS代表了這個CF中擁有的樣本點各特征維度的平方和。
如上圖所示:N = 5
LS=(3+2+4+4+3,4+6+5+7+8)=(16,30)
SS =(32+22+42+42+32,42+62+52+72+82)=(54,190)
圖解過程
對於上圖中的CF Tree,限定了B=7,L=5, 也就是說內部節點最多有7個CF(CF90下的圓),而葉子節點最多有5個CF(CF90到CF94)。葉子節點是通過雙向鏈表連通的。
6.3 算法特點
- Euclidean distance between points(點之間的歐式距離)
6.4 適用場景
- 大數據集,異常值去除,數據簡化
- 大的 n_clusters 和 n_samples
6.5 測試代碼

1 import numpy as np 2 import matplotlib.pyplot as plt 3 from sklearn.datasets.samples_generator import make_blobs 4 from sklearn.cluster import Birch 5 6 # X為樣本特征,Y為樣本簇類別, 共1000個樣本,每個樣本2個特征,共4個簇,簇中心在[-1,-1], [0,0],[1,1], [2,2] 7 X, y = make_blobs(n_samples=1000, n_features=2, centers=[[-1,-1], [0,0], [1,1], [2,2]], cluster_std=[0.4, 0.3, 0.4, 0.3], 8 random_state =9) 9 10 ##設置birch函數 11 birch = Birch(n_clusters = None) 12 ##訓練數據 13 y_pred = birch.fit_predict(X) 14 ##繪圖 15 plt.scatter(X[:, 0], X[:, 1], c=y_pred) 16 plt.show()
7. 譜聚類
7.1 簡介
Spectral Clustering(SC,即譜聚類),是一種基於圖論的聚類方法,它能夠識別任意形狀的樣本空間且收斂於全局最有解,其基本思想是利用樣本數據的相似矩陣進行特征分解后得到的特征向量進行聚類.它與樣本特征無關而只與樣本個數有關。
基本思路:將樣本看作頂點,樣本間的相似度看作帶權的邊,從而將聚類問題轉為圖分割問題:找到一種圖分割的方法使得連接不同組的邊的權重盡可能低(這意味着組間相似度要盡可能低),組內的邊的權重盡可能高(這意味着組內相似度要盡可能高).
7.2 算法原理
如上圖所示,斷開虛線,六個數據被聚成兩類。
7.3 算法特點
- Graph distance (e.g. nearest-neighbor graph)(圖形距離(例如最近鄰圖))
7.4 適用場景
- 幾個簇,均勻的簇大小,非平面幾何
- 中等的 n_samples, 小的 n_clusters
7.5 測試代碼

1 from sklearn.datasets.samples_generator import make_blobs 2 from sklearn.cluster import spectral_clustering 3 import numpy as np 4 import matplotlib.pyplot as plt 5 from sklearn import metrics 6 from itertools import cycle ##python自帶的迭代器模塊 7 8 ##產生隨機數據的中心 9 centers = [[1, 1], [-1, -1], [1, -1]] 10 ##產生的數據個數 11 n_samples=3000 12 ##生產數據 13 X, lables_true = make_blobs(n_samples=n_samples, centers= centers, cluster_std=0.6, 14 random_state =0) 15 16 ##變換成矩陣,輸入必須是對稱矩陣 17 metrics_metrix = (-1 * metrics.pairwise.pairwise_distances(X)).astype(np.int32) 18 metrics_metrix += -1 * metrics_metrix.min() 19 ##設置譜聚類函數 20 n_clusters_= 4 21 lables = spectral_clustering(metrics_metrix,n_clusters=n_clusters_) 22 23 ##繪圖 24 plt.figure(1) 25 plt.clf() 26 27 colors = cycle('bgrcmykbgrcmykbgrcmykbgrcmyk') 28 for k, col in zip(range(n_clusters_), colors): 29 ##根據lables中的值是否等於k,重新組成一個True、False的數組 30 my_members = lables == k 31 ##X[my_members, 0] 取出my_members對應位置為True的值的橫坐標 32 plt.plot(X[my_members, 0], X[my_members, 1], col + '.') 33 34 plt.title('Estimated number of clusters: %d' % n_clusters_) 35 plt.show()
8. 高斯混合模型
8.1 簡介
高斯混合模型(Gaussian Mixture Model, GMM)也是一種常見的聚類算法,其使用了EM算法進行迭代計算。高斯混合模型假設每個簇的數據都是符合高斯分布(又叫正態分布)的,當前數據呈現的分布就是就是各個簇的高斯分布疊加在一起的結果。
8.2 算法原理
- 高斯混合模型是由K個高斯分布(正態分布)函數組成,而該算法的目的就是找出各個高斯分布最佳的均值、方差、權重。
- 指定K的值,並初始隨機選擇各參數的值
- E步驟。根據當前的參數,計算每個點由某個分模型生成的概率
- M步驟。根據E步驟估計出的概率,來改進每個分模型的均值、方差和權重
- 重復步驟2、3,直至收斂。
8.3 算法特點
- Mahalanobis distances to centers(Mahalanobis 與中心的距離)
優點
- 可以給出一個樣本屬於某類的概率是多少
- 不僅用於聚類,還可用於概率密度的估計
- 可以用於生成新的樣本點
缺點
- 需要指定K值
- 使用EM算法來求解
- 往往只能收斂於局部最優
8.4 適用場景
- 平面幾何,適用於密度估計
- Not scalable(不可擴展)
8.5 測試代碼

1 import matplotlib as mpl 2 import matplotlib.pyplot as plt 3 4 import numpy as np 5 6 from sklearn import datasets 7 from sklearn.mixture import GaussianMixture 8 from sklearn.model_selection import StratifiedKFold 9 10 print(__doc__) 11 12 colors = ['navy', 'turquoise', 'darkorange'] 13 14 15 def make_ellipses(gmm, ax): 16 for n, color in enumerate(colors): 17 if gmm.covariance_type == 'full': 18 covariances = gmm.covariances_[n][:2, :2] 19 elif gmm.covariance_type == 'tied': 20 covariances = gmm.covariances_[:2, :2] 21 elif gmm.covariance_type == 'diag': 22 covariances = np.diag(gmm.covariances_[n][:2]) 23 elif gmm.covariance_type == 'spherical': 24 covariances = np.eye(gmm.means_.shape[1]) * gmm.covariances_[n] 25 v, w = np.linalg.eigh(covariances) 26 u = w[0] / np.linalg.norm(w[0]) 27 angle = np.arctan2(u[1], u[0]) 28 angle = 180 * angle / np.pi # convert to degrees 29 v = 2. * np.sqrt(2.) * np.sqrt(v) 30 ell = mpl.patches.Ellipse(gmm.means_[n, :2], v[0], v[1], 31 180 + angle, color=color) 32 ell.set_clip_box(ax.bbox) 33 ell.set_alpha(0.5) 34 ax.add_artist(ell) 35 ax.set_aspect('equal', 'datalim') 36 37 iris = datasets.load_iris() 38 39 # Break up the dataset into non-overlapping training (75%) and testing 40 # (25%) sets. 41 skf = StratifiedKFold(n_splits=4) 42 # Only take the first fold. 43 train_index, test_index = next(iter(skf.split(iris.data, iris.target))) 44 45 46 X_train = iris.data[train_index] 47 y_train = iris.target[train_index] 48 X_test = iris.data[test_index] 49 y_test = iris.target[test_index] 50 51 n_classes = len(np.unique(y_train)) 52 53 # Try GMMs using different types of covariances. 54 estimators = {cov_type: GaussianMixture(n_components=n_classes, 55 covariance_type=cov_type, max_iter=20, random_state=0) 56 for cov_type in ['spherical', 'diag', 'tied', 'full']} 57 58 n_estimators = len(estimators) 59 60 plt.figure(figsize=(3 * n_estimators // 2, 6)) 61 plt.subplots_adjust(bottom=.01, top=0.95, hspace=.15, wspace=.05, 62 left=.01, right=.99) 63 64 65 for index, (name, estimator) in enumerate(estimators.items()): 66 # Since we have class labels for the training data, we can 67 # initialize the GMM parameters in a supervised manner. 68 estimator.means_init = np.array([X_train[y_train == i].mean(axis=0) 69 for i in range(n_classes)]) 70 71 # Train the other parameters using the EM algorithm. 72 estimator.fit(X_train) 73 74 h = plt.subplot(2, n_estimators // 2, index + 1) 75 make_ellipses(estimator, h) 76 77 for n, color in enumerate(colors): 78 data = iris.data[iris.target == n] 79 plt.scatter(data[:, 0], data[:, 1], s=0.8, color=color, 80 label=iris.target_names[n]) 81 # Plot the test data with crosses 82 for n, color in enumerate(colors): 83 data = X_test[y_test == n] 84 plt.scatter(data[:, 0], data[:, 1], marker='x', color=color) 85 86 y_train_pred = estimator.predict(X_train) 87 train_accuracy = np.mean(y_train_pred.ravel() == y_train.ravel()) * 100 88 plt.text(0.05, 0.9, 'Train accuracy: %.1f' % train_accuracy, 89 transform=h.transAxes) 90 91 y_test_pred = estimator.predict(X_test) 92 test_accuracy = np.mean(y_test_pred.ravel() == y_test.ravel()) * 100 93 plt.text(0.05, 0.8, 'Test accuracy: %.1f' % test_accuracy, 94 transform=h.transAxes) 95 96 plt.xticks(()) 97 plt.yticks(()) 98 plt.title(name) 99 100 plt.legend(scatterpoints=1, loc='lower right', prop=dict(size=12)) 101 102 103 plt.show()
參考