考慮到學習知識的順序及效率問題,所以后續的幾種聚類方法不再詳細講解原理,也不再寫python實現的源代碼,只介紹下算法的基本思路,使大家對每種算法有個直觀的印象,從而可以更好的理解函數中參數的意義及作用,而重點是放在如何使用及使用的場景。
(題外話: 今天看到一篇博文:剛接觸機器學習這一個月我都做了什么? 里面對機器學習階段的划分很不錯,就目前而言我們只要做到前兩階段即可)
因為前兩篇博客已經介紹了兩種算法,所以這里的算法編號從3開始。
3.Mean-shift
1)概述
Mean-shift(即:均值遷移)的基本思想:在數據集中選定一個點,然后以這個點為圓心,r為半徑,畫一個圓(二維下是圓),求出這個點到所有點的向量的平均值,而圓心與向量均值的和為新的圓心,然后迭代此過程,直到滿足一點的條件結束。(Fukunage在1975年提出)
后來Yizong Cheng 在此基礎上加入了 核函數 和 權重系數 ,使得Mean-shift 算法開始流行起來。目前它在聚類、圖像平滑、分割、跟蹤等方面有着廣泛的應用。
2)圖解過程
為了方便大家理解,借用下幾張圖來說明Mean-shift的基本過程。
由上圖可以很容易看到,Mean-shift 算法的核心思想就是不斷的尋找新的圓心坐標,直到密度最大的區域。
3)Mean-shift 算法函數
a)核心函數:sklearn.cluster.MeanShift(核函數:RBF核函數)
由上圖可知,圓心(或種子)的確定和半徑(或帶寬)的選擇,是影響算法效率的兩個主要因素。所以在sklearn.cluster.MeanShift中重點說明了這兩個參數的設定問題。
b)主要參數
bandwidth :半徑(或帶寬),float型。如果沒有給出,則使用sklearn.cluster.estimate_bandwidth計算出半徑(帶寬).(可選)
seeds :圓心(或種子),數組類型,即初始化的圓心。(可選)
bin_seeding :布爾值。如果為真,初始內核位置不是所有點的位置,而是點的離散版本的位置,其中點被分類到其粗糙度對應於帶寬的網格上。將此選項設置為True將加速算法,因為較少的種子將被初始化。默認值:False.如果種子參數(seeds)不為None則忽略。
c)主要屬性
cluster_centers_ : 數組類型。計算出的聚類中心的坐標。
labels_ :數組類型。每個數據點的分類標簽。
d)算法示例:代碼中有詳細講解內容

from sklearn.datasets.samples_generator import make_blobs from sklearn.cluster import MeanShift, estimate_bandwidth import numpy as np import matplotlib.pyplot as plt from itertools import cycle ##python自帶的迭代器模塊 ##產生隨機數據的中心 centers = [[1, 1], [-1, -1], [1, -1]] ##產生的數據個數 n_samples=10000 ##生產數據 X, _ = make_blobs(n_samples=n_samples, centers= centers, cluster_std=0.6, random_state =0) ##帶寬,也就是以某個點為核心時的搜索半徑 bandwidth = estimate_bandwidth(X, quantile=0.2, n_samples=500) ##設置均值偏移函數 ms = MeanShift(bandwidth=bandwidth, bin_seeding=True) ##訓練數據 ms.fit(X) ##每個點的標簽 labels = ms.labels_ print(labels) ##簇中心的點的集合 cluster_centers = ms.cluster_centers_ ##總共的標簽分類 labels_unique = np.unique(labels) ##聚簇的個數,即分類的個數 n_clusters_ = len(labels_unique) print("number of estimated clusters : %d" % n_clusters_) ##繪圖 plt.figure(1) plt.clf() colors = cycle('bgrcmykbgrcmykbgrcmykbgrcmyk') for k, col in zip(range(n_clusters_), colors): ##根據lables中的值是否等於k,重新組成一個True、False的數組 my_members = labels == k cluster_center = cluster_centers[k] ##X[my_members, 0] 取出my_members對應位置為True的值的橫坐標 plt.plot(X[my_members, 0], X[my_members, 1], col + '.') plt.plot(cluster_center[0], cluster_center[1], 'o', markerfacecolor=col, markeredgecolor='k', markersize=14) plt.title('Estimated number of clusters: %d' % n_clusters_) plt.show()
e)效果圖
圖4
4)openCV主要應用於圖像處理,而Mean-shift多用於圖像跟蹤等,所以對應圖像處理這部分而言,openCV中的Mean-shift算法的功能還是強大一點。
4.Spectral Clustering
1)概述
Spectral Clustering(SC,即譜聚類),是一種基於圖論的聚類方法,它能夠識別任意形狀的樣本空間且收斂於全局最有解,其基本思想是利用樣本數據的相似矩陣進行特征分解后得到的特征向量進行聚類.它與樣本特征無關而只與樣本個數有關。
基本思路:將樣本看作頂點,樣本間的相似度看作帶權的邊,從而將聚類問題轉為圖分割問題:找到一種圖分割的方法使得連接不同組的邊的權重盡可能低(這意味着組間相似度要盡可能低),組內的邊的權重盡可能高(這意味着組內相似度要盡可能高).
2)圖解過程
圖5
如上圖所示,斷開虛線,六個數據被聚成兩類。
3)Spectral Clustering算法函數
a)核心函數:sklearn.cluster.SpectralClustering
因為是基於圖論的算法,所以輸入必須是對稱矩陣。
b)主要參數(參數較多,詳細參數)
n_clusters:聚類的個數。(官方的解釋:投影子空間的維度)
affinity:核函數,默認是'rbf',可選:"nearest_neighbors","precomputed","rbf"或sklearn.metrics.pairwise_kernels支持的其中一個內核之一。
gamma :affinity指定的核函數的內核系數,默認1.0
c)主要屬性
labels_ :每個數據的分類標簽
d)算法示例:代碼中有詳細講解內容

from sklearn.datasets.samples_generator import make_blobs from sklearn.cluster import spectral_clustering import numpy as np import matplotlib.pyplot as plt from sklearn import metrics from itertools import cycle ##python自帶的迭代器模塊 ##產生隨機數據的中心 centers = [[1, 1], [-1, -1], [1, -1]] ##產生的數據個數 n_samples=3000 ##生產數據 X, lables_true = make_blobs(n_samples=n_samples, centers= centers, cluster_std=0.6, random_state =0) ##變換成矩陣,輸入必須是對稱矩陣 metrics_metrix = (-1 * metrics.pairwise.pairwise_distances(X)).astype(np.int32) metrics_metrix += -1 * metrics_metrix.min() ##設置譜聚類函數 n_clusters_= 4 lables = spectral_clustering(metrics_metrix,n_clusters=n_clusters_) ##繪圖 plt.figure(1) plt.clf() colors = cycle('bgrcmykbgrcmykbgrcmykbgrcmyk') for k, col in zip(range(n_clusters_), colors): ##根據lables中的值是否等於k,重新組成一個True、False的數組 my_members = lables == k ##X[my_members, 0] 取出my_members對應位置為True的值的橫坐標 plt.plot(X[my_members, 0], X[my_members, 1], col + '.') plt.title('Estimated number of clusters: %d' % n_clusters_) plt.show()
e)效果圖
圖5
5.Hierarchical Clustering
1)概述
Hierarchical Clustering(層次聚類):就是按照某種方法進行層次分類,直到滿足某種條件為止。
主要分成兩類:
a)凝聚:從下到上。首先將每個對象作為一個簇,然后合並這些原子簇為越來越大的簇,直到所有的對象都在一個簇中,或者某個終結條件被滿足。
b)分裂:從上到下。首先將所有對象置於同一個簇中,然后逐漸細分為越來越小的簇,直到每個對象自成一簇,或者達到了某個終止條件。(較少用)
2)算法步驟
a)將每個對象歸為一類, 共得到N類, 每類僅包含一個對象. 類與類之間的距離就是它們所包含的對象之間的距離.
b)找到最接近的兩個類並合並成一類, 於是總的類數少了一個.
c)重新計算新的類與所有舊類之間的距離.
d)重復第2步和第3步, 直到最后合並成一個類為止(此類包含了N個對象).
3)圖解過程
圖6
4)Hierarchical Clustering算法函數
a)sklearn.cluster.AgglomerativeClustering
b)主要參數(詳細參數)
n_clusters:聚類的個數
linkage:指定層次聚類判斷相似度的方法,有以下三種:
ward:組間距離等於兩類對象之間的最小距離。(即single-linkage聚類)
average:組間距離等於兩組對象之間的平均距離。(average-linkage聚類)
complete:組間距離等於兩組對象之間的最大距離。(complete-linkage聚類)
c)主要屬性
labels_: 每個數據的分類標簽
d)算法示例:代碼中有詳細講解內容

from sklearn.datasets.samples_generator import make_blobs from sklearn.cluster import AgglomerativeClustering import numpy as np import matplotlib.pyplot as plt from itertools import cycle ##python自帶的迭代器模塊 ##產生隨機數據的中心 centers = [[1, 1], [-1, -1], [1, -1]] ##產生的數據個數 n_samples=3000 ##生產數據 X, lables_true = make_blobs(n_samples=n_samples, centers= centers, cluster_std=0.6, random_state =0) ##設置分層聚類函數 linkages = ['ward', 'average', 'complete'] n_clusters_ = 3 ac = AgglomerativeClustering(linkage=linkages[2],n_clusters = n_clusters_) ##訓練數據 ac.fit(X) ##每個數據的分類 lables = ac.labels_ ##繪圖 plt.figure(1) plt.clf() colors = cycle('bgrcmykbgrcmykbgrcmykbgrcmyk') for k, col in zip(range(n_clusters_), colors): ##根據lables中的值是否等於k,重新組成一個True、False的數組 my_members = lables == k ##X[my_members, 0] 取出my_members對應位置為True的值的橫坐標 plt.plot(X[my_members, 0], X[my_members, 1], col + '.') plt.title('Estimated number of clusters: %d' % n_clusters_) plt.show()
e)效果圖:參數linkage的取值依次為:['ward', 'average', 'complete']
6.DBSCAN
1)概述
DBSCAN(Density-Based Spatial Clustering of Applications with Noise,具有噪聲的基於密度的聚類方法)是一種基於密度的空間聚類算法。該算法將具有足夠密度的區域划分為簇(即要求聚類空間中的一定區域內所包含對象的數目不小於某一給定閾值),並在具有噪聲的空間數據庫中發現任意形狀的簇,它將簇定義為密度相連的點的最大集合。
2) 算法步驟(大致非詳細)
DBSCAN需要二個參數:掃描半徑 (eps)和最小包含點數(min_samples)
a)遍歷所有點,尋找核心點
b)連通核心點,並且在此過程中擴展某個分類集合中點的個數
3)圖解過程
圖10
在上圖中,第一步就是尋找紅色的核心點,第二步就是用綠色箭頭聯通紅色點。圖中點以綠色線條為中心被分成了兩類。沒在黑色圓中的點是噪聲點。
4)DBSCAN算法函數
a)sklearn.cluster.DBSCAN
b)主要參數(詳細參數)
eps:兩個樣本之間的最大距離,即掃描半徑
min_samples :作為核心點的話鄰域(即以其為圓心,eps為半徑的圓,含圓上的點)中的最小樣本數(包括點本身)。
c)主要屬性
core_sample_indices_:核心樣本指數。(此參數在代碼中有詳細的解釋)
labels_:數據集中每個點的集合標簽給,噪聲點標簽為-1。
d)算法示例:代碼中有詳細講解內容

from sklearn.datasets.samples_generator import make_blobs from sklearn.cluster import DBSCAN import numpy as np import matplotlib.pyplot as plt from itertools import cycle ##python自帶的迭代器模塊 from sklearn.preprocessing import StandardScaler ##產生隨機數據的中心 centers = [[1, 1], [-1, -1], [1, -1]] ##產生的數據個數 n_samples=750 ##生產數據:此實驗結果受cluster_std的影響,或者說受eps 和cluster_std差值影響 X, lables_true = make_blobs(n_samples=n_samples, centers= centers, cluster_std=0.4, random_state =0) ##設置分層聚類函數 db = DBSCAN(eps=0.3, min_samples=10) ##訓練數據 db.fit(X) ##初始化一個全是False的bool類型的數組 core_samples_mask = np.zeros_like(db.labels_, dtype=bool) ''' 這里是關鍵點(針對這行代碼:xy = X[class_member_mask & ~core_samples_mask]): db.core_sample_indices_ 表示的是某個點在尋找核心點集合的過程中暫時被標為噪聲點的點(即周圍點 小於min_samples),並不是最終的噪聲點。在對核心點進行聯通的過程中,這部分點會被進行重新歸類(即標簽 並不會是表示噪聲點的-1),也可也這樣理解,這些點不適合做核心點,但是會被包含在某個核心點的范圍之內 ''' core_samples_mask[db.core_sample_indices_] = True ##每個數據的分類 lables = db.labels_ ##分類個數:lables中包含-1,表示噪聲點 n_clusters_ =len(np.unique(lables)) - (1 if -1 in lables else 0) ##繪圖 unique_labels = set(lables) ''' 1)np.linspace 返回[0,1]之間的len(unique_labels) 個數 2)plt.cm 一個顏色映射模塊 3)生成的每個colors包含4個值,分別是rgba 4)其實這行代碼的意思就是生成4個可以和光譜對應的顏色值 ''' colors = plt.cm.Spectral(np.linspace(0, 1, len(unique_labels))) plt.figure(1) plt.clf() for k, col in zip(unique_labels, colors): ##-1表示噪聲點,這里的k表示黑色 if k == -1: col = 'k' ##生成一個True、False數組,lables == k 的設置成True class_member_mask = (lables == k) ##兩個數組做&運算,找出即是核心點又等於分類k的值 markeredgecolor='k', xy = X[class_member_mask & core_samples_mask] plt.plot(xy[:, 0], xy[:, 1], 'o', c=col,markersize=14) ''' 1)~優先級最高,按位對core_samples_mask 求反,求出的是噪音點的位置 2)& 於運算之后,求出雖然剛開始是噪音點的位置,但是重新歸類卻屬於k的點 3)對核心分類之后進行的擴展 ''' xy = X[class_member_mask & ~core_samples_mask] plt.plot(xy[:, 0], xy[:, 1], 'o', c=col,markersize=6) plt.title('Estimated number of clusters: %d' % n_clusters_) plt.show()
e)效果圖
圖11
如果不進行第二步中的擴展,所有的小圓點都應該是噪聲點(不符合第一步核心點的要求)
5)算法優缺點
a)優點
可以發現任意形狀的聚類
b)缺點
隨着數據量的增加,對I/O、內存的要求也隨之增加。
如果密度分布不均勻,聚類效果較差
7.Birch
1)概述
Birch(利用層次方法的平衡迭代規約和聚類):就是通過聚類特征(CF)形成一個聚類特征樹,root層的CF個數就是聚類個數。
2)相關概念:
聚類特征(CF):每一個CF是一個三元組,可以用(N,LS,SS)表示.其中N代表了這個CF中擁有的樣本點的數量;LS代表了這個CF中擁有的樣本點各特征維度的和向量,SS代表了這個CF中擁有的樣本點各特征維度的平方和。
圖12
如上圖所示: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)
3)圖解過程
圖13
對於上圖中的CF Tree,限定了B=7,L=5, 也就是說內部節點最多有7個CF(CF90下的圓),而葉子節點最多有5個CF(CF90到CF94)。葉子節點是通過雙向鏈表連通的。
4)Birch算法函數
a)sklearn.cluster.Birch
b)主要參數(詳細參數)
n_clusters :聚類的目標個數。(可選)
threshold :掃描半徑(個人理解,官方說法比較繞口),設置小了分類就多。
branches_factor:每個節點中CF子集群的最大數量,默認為50。
c)主要屬性
labels_ :每個數據點的分類
5) 算法示例:代碼中有詳細講解內容

import numpy as np import matplotlib.pyplot as plt from sklearn.datasets.samples_generator import make_blobs from sklearn.cluster import Birch # X為樣本特征,Y為樣本簇類別, 共1000個樣本,每個樣本2個特征,共4個簇,簇中心在[-1,-1], [0,0],[1,1], [2,2] 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], random_state =9) ##設置birch函數 birch = Birch(n_clusters = None) ##訓練數據 y_pred = birch.fit_predict(X) ##繪圖 plt.scatter(X[:, 0], X[:, 1], c=y_pred) plt.show()
6)效果圖:分別為n_clusters = None 和n_clusters = 4
圖14 圖15
8.GaussianMixtureModel(補)
1)概述
正太分布也叫高斯分布,正太分布的概率密度曲線也叫高斯分布概率曲線。
GaussianMixtureModel(混合高斯模型,GMM)。
聚類算法大多數通過相似度來判斷,而相似度又大多采用歐式距離長短作為衡量依據。而GMM采用了新的判斷依據:概率,即通過屬於某一類的概率大小來判斷最終的歸屬類別。
GMM的基本思想就是:任意形狀的概率分布都可以用多個高斯分布函數去近似,也就是說GMM就是有多個單高斯密度分布(Gaussian)組成的,每個Gaussian叫一個"Component",這些"Component"線性加成在一起就組成了 GMM 的概率密度函數,也就是下面的函數。
2)數學公式
這里不講公式的具體推導過程,也不實現具體算法。列出來公式只是方便理解下面的函數中為什么需要那些參數。
K:模型的個數,即Component的個數(聚類的個數)
為第k個高斯的權重
p(x |k) 則為第k個高斯概率密度,其均值為μk,方差為σk
上述參數,除了K是直接給定之外,其他參數都是通過EM算法估算出來的。(有個參數是指定EM算法參數的)
3)GaussianMixtureModel 算法函數
a)from sklearn.mixture.GaussianMixture
b)主要參數(詳細參數)
n_components :高斯模型的個數,即聚類的目標個數
covariance_type : 通過EM算法估算參數時使用的協方差類型,默認是"full"
full:每個模型使用自己的一般協方差矩陣
tied:所用模型共享一個一般協方差矩陣
diag:每個模型使用自己的對角線協方差矩陣
spherical:每個模型使用自己的單一方差
4)算法示例:代碼中有詳細講解內容

import matplotlib.pyplot as plt from sklearn.datasets.samples_generator import make_blobs from sklearn.mixture import GaussianMixture # X為樣本特征,Y為樣本簇類別, 共1000個樣本,每個樣本2個特征,共4個簇,簇中心在[-1,-1], [0,0],[1,1], [2,2] 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], random_state = 0) ##設置gmm函數 gmm = GaussianMixture(n_components=4, covariance_type='full').fit(X) ##訓練數據 y_pred = gmm.predict(X) ##繪圖 plt.scatter(X[:, 0], X[:, 1], c=y_pred) plt.show()
5)效果圖
圖(16)
跟圖15對比可以看出,雖然使用同樣的數據,但是不同的算法的聚類效果是不一樣的