一、k-means
k-means算法并沒有顯示的學習過程,而且很簡單,給定一個訓練數據集,其中的實例類別已定,分類時,對新的輸入實例,根據其k個最近鄰的訓練實例的類別,通過多數表決等方式進行預測。k-means實際上利用訓練數據集對特征向量空間進行劃分,并作為其對分類的“模型”。
k-means主要是在對k值的選擇,距離的度量以及分類決策規則的調控。
K-means方法尋找的是球形或超球面形類,所以并不適用以下幾種類型的分類:
注意不要混淆K-近鄰算法和K均值聚類。 K-近鄰算法是一種分類算法,也是監督學習的一個子集。 K-means是一種聚類算法,也是非監督學習的一個子集。
那么就引入了其他的聚類方法:
二、層次聚類Hierarchical Clustering
部分內容出自這里
層次聚類能讓人直觀的了解到類之間的關系。
層次聚類( Hierarchical Clustering )是聚類算法的一種,通過計算不同類別的相似度類創建一個有層次的嵌套的樹。
假設有 n 個待聚類的樣本,對于層次聚類算法,它的步驟是:
- 步驟一:(初始化)將每個樣本都視為一個聚類;
- 步驟二:計算各個聚類之間的相似度;
- 步驟三:尋找最近的兩個聚類,將他們歸為一類;
- 步驟四:重復步驟二,步驟三;直到所有樣本歸好類。
整個過程就是建立一棵樹,在建立的過程中,可以在步驟四設置所需分類的類別個數,作為迭代的終止條件,畢竟都歸為一類并不實際。
sklearn的層次聚類
scipy畫系統樹圖
層次聚類的優缺點
優點:
- 一次性得到聚類樹,后期再分類無需重新計算;
- 相似度規則容易定義;
- 可以發現類別的層次關系,而且層次信息非常豐富;
- 可以將數據集的聚類結構視覺化
缺點:
- 計算復雜度高,不適合數據量大的;
- 算法很可能形成鏈狀。
- 對噪音和離群值很敏感
下面是層次聚類的幾種分類:
1、單連接聚類法Single Linkage
又叫做 nearest-neighbor ,就是取兩個類中距離最近的兩個樣本的距離作為這兩個集合的距離。這種計算方式容易造成一種叫做 Chaining 的效果,兩個 cluster 明明從“大局”上離得比較遠,但是由于其中個別的點距離比較近就被合并了,并且這樣合并之后 Chaining 效應會進一步擴大,最后會得到比較松散的 cluster 。單連接是查看與聚類最近的點,這可能導致形成各種形狀的聚類。
跟上面的步驟一樣,我們分解來看:
-
步驟一:(初始化)將每個樣本都視為一個聚類;
層次聚類1.png -
步驟二:計算各個聚類之間的相似度,簡單來說就是計算任意兩點之間的距離
層次聚類2.png -
步驟三:尋找最近的兩個聚類,將他們歸為一類,就是選擇兩個類之間的最短距離,然后將這兩個點作為一個聚類,在旁邊就能畫出第一個節點的層次。
層次聚類3.png
-
步驟四:重復步驟二和步驟三,當不再有單獨的點作為一個類,而是要判斷多個類和多個類之間的距離的地方(這是個關鍵的地方,這一步是區分不同層次聚類的方法的標準,究竟是看單個類,還是類的平均距離等等。)單連接聚類法關乎的是兩類間的最短距離,所以他衡量的依然是單個類與另一個類節點的最短距離,以圖例來說就是6和7是最短距離
層次聚類4.png
判斷好最短距離后,將這個單獨節點再歸到整體聚類中,成為了一個新的類,這個新的類中含有另外一個類作為子類
層次聚類5.png
如此循環規整完畢后,就生成了系統樹圖
層次聚類6.png
就像上面說的,歸為一個類是不切實際的,所以我們會給層次聚類一個輸入,那就是有多少個類,通過有多少個類,來在系統樹圖上進行切割劃分,比如我們分兩個聚類,那么如圖,截掉不必要的層次即可:
層次聚類7.png
所以 單連接聚類法 或廣義上的層次聚類法能幫我們得到一個類 或者樣本數量等等。
與k-means的區別
下圖是同樣的數據,使用k-means和使用單連接層次聚類法的區別
同樣我們通過單連接層次聚類能畫出系統樹圖來看數據的規律
雖然我們不一定能通過單連接聚類法得出最好的分類結果,但是系統樹圖還是能讓我們看出來規律,再使用其他的聚類方法來得到劃分。
2、全連接聚類Complete Linkage
這個則完全是 Single Linkage 的反面極端,取兩個集合中距離最遠的兩個點的距離作為兩個集合的距離。全連接聚類法中 這樣的距離衡量方法使得產生的類比較緊湊,比單連接聚類法產生的類更緊湊 更好,但畢竟也是只考慮單個點的存在,其效果也是剛好相反的,限制也很大。Single Linkage和Complete Linkage這兩種相似度的定義方法的共同問題就是指考慮了某個有特點的數據,而沒有考慮類內數據的整體特點。
來看具體步驟,它整體的步驟跟單連接聚類很接近,只是在步驟四時有區分
- 步驟四:之前也有說過,判斷距離方式的不同造就了不同的聚類方法,全連接聚類不再是判斷兩個類最近的距離,而是將一個類與另一個類中節點最遠的那個點作為最小距離的判斷依據(全連接聚類法關注的是兩個類中兩點之間的最遠距離作為最小距離),有點繞,看圖:
層次聚類10.png
3、組平均聚類average link
這種方法跟上兩個其實也很相似,就是把兩個集合中的點兩兩的距離全部放在一起求均值,相對也能得到合適一點的結果(詳細來說,它計算的是任意兩類中任意兩點之間的距離,然后取平均值 即為兩類之間的距離,然后判斷最小類距離作為聚類標準)。有時異常點的存在會影響均值,平常人和富豪平均一下收入會被拉高是吧,因此這種計算方法的一個變種就是取兩兩距離的中位數。
上圖舉例兩類距離求平均。
4、Ward's method離差平方和法
這種方法是 Scikit-learn 框架中一種預設的層次聚類法,它的目的是把合并類時的變量最小化,離差平方和法計算兩類間的距離的方法是:先找出這兩個聚類總體的中心位置O,然后計算每個節點和中心位置的距離記做C,分別計算這些距離C的平方,并且相加記為delta,然后找出這兩個聚類分別的中心位置O1,O2,比如第一個類的中心是O1,那么第一類的節點與O1的距離記做A,那么之前求出來的平方和delta減去所有A的平方,這樣循環得出來各個類之間的最小距離,將最小距離的類化為一類。這樣離差平方和法會最小化在每個合并步驟中的方差。
整體流程如圖:
離差平方和法和平均連接算法一般傾向于導致緊湊的聚類。
三、密度聚類Density-based Clustering
最主要的算法叫DBScan,指的是 具有噪聲的基于密度的聚類方法,對有噪聲的數據集具有很強的適用性,它并不要求我們具體說明一系列的類,一般把一些密集分布的點聚類,再將其他剩余的點標記為噪音。
具體步驟如下:
步驟一:設置最小距離,用來決定在某個范圍內是否有其他點的這個范圍,設置點的個數,即在這個范圍內是否有這么多的點存在,如果存在設置為Core point,如果不存在設置為Noise point,如果不存在,但是在之前設置的core point范圍內,那么就為border point。
步驟二:隨機找到一個數據點,看是否有足夠數量的點在范圍內
步驟三:重復步驟二
以下圖為例,可以將數據點劃為下面幾種:
DBSCAN優缺點
優點:
- 不需要指明類數量,而是通過舉例和點數量來分的,即點的密度
- 能夠找到并分離各種形狀和大小的聚類,不局限于外形
- 能夠處理噪聲和離群值
缺點: - 邊界點很有可能在多次運行時不會被劃分為同一個類,因為運行算法時的點是隨機選取的
- 在找到不同密度的聚類方面有一定的困難,畢竟只能設置一個密度(所以我們可以用 DBSCAN 的變體 HDBSCAN 即具有噪聲的基于密度的高層次空間聚類算法)
DBSCAN和Kmeans的對比
sklearn實現DBSCAN
因為可控參數不太多,那么有一些基本的規律在里面:
- 如果聚類后有很多小的聚類。超出了數據集的預期數量。
措施:增大 min_samples 和 ε - 很多點都屬于一個聚類
措施:降低 ε 并增大 min_samples - 大部分/所有數據點都標記為噪點
措施:增大 ε 并降低 min_sample - 除了非常密集的區域之外,大部分/所有數據點都標記為噪點(或者所有點都標記為噪點)。
措施:降低 min_samples 和 ε
四、高斯混合模型聚類Gaussian Mixture Model Clustering
部分參考這里和這里
統計的先修知識也可以先查看我以前寫過的文章。
GMM和k-means其實是十分相似的,區別僅僅在于對GMM來說,我們引入了概率,這種聚類算法假定每個類都遵循特定的統計分布,它大量使用概率和統計學知識來找出這些類。說到這里,我想先補充一點東西。統計學習的模型有兩種,一種是概率模型,一種是非概率模型。所謂概率模型,就是指我們要學習的模型的形式是P(Y|X),這樣在分類的過程中,我們通過未知數據X可以獲得Y取值的一個概率分布,也就是訓練后模型得到的輸出不是一個具體的值,而是一系列值的概率(對應于分類問題來說,就是對應于各個不同的類的概率),然后我們可以選取概率最大的那個類作為判決對象(算軟分類soft assignment)。而非概率模型,就是指我們學習的模型是一個決策函數Y=f(X),輸入數據X是多少就可以投影得到唯一的一個Y,就是判決結果(算硬分類hard assignment)。回到GMM,學習的過程就是訓練出幾個概率分布,所謂混合高斯模型就是指對樣本的概率密度分布進行估計,而估計的模型是幾個高斯模型加權之和(具體是幾個要在模型訓練前建立好)。每個高斯模型就代表了一個類(一個Cluster)。對樣本中的數據分別在幾個高斯模型上投影,就會分別得到在各個類上的概率。然后我們可以選取概率最大的類所為判決結果。
如圖:
單高斯模型
要理解高斯混合模型,首先要知道最基本的高斯模型是什么,下面是找到的定義:
高斯混合模型(GMM)
那么再回到高斯混合模型,高斯混合模型可以看作是由 K 個單高斯模型組合而成的模型,這 K 個子模型是混合模型的隱變量(Hidden variable)。一般來說,一個混合模型可以使用任何概率分布,這里使用高斯混合模型是因為高斯分布具備很好的數學性質以及良好的計算性能。
舉個不是特別穩妥的例子,比如我們現在有一組狗的樣本數據,不同種類的狗,體型、顏色、長相各不相同,但都屬于狗這個種類,此時單高斯模型可能不能很好的來描述這個分布,因為樣本數據分布并不是一個單一的橢圓,所以用混合高斯分布可以更好的描述這個問題,如下圖所示:
模型參數學習
對于單高斯模型,我們可以用最大似然法(Maximum likelihood)估算參數θ的值,
這里我們假設了每個數據點都是獨立的(Independent),似然函數由概率密度函數(PDF)給出。
由于每個點發生的概率都很小,乘積會變得極其小,不利于計算和觀察,因此通常我們用 Maximum Log-Likelihood 來計算(因為 Log 函數具備單調性,不會改變極值的位置,同時在 0-1 之間輸入值很小的變化可以引起輸出值相對較大的變動):
對于高斯混合模型,Log-Likelihood 函數是:
如何計算高斯混合模型的參數呢?這里我們無法像單高斯模型那樣使用最大似然法來求導求得使 likelihood 最大的參數,因為對于每個觀測數據點來說,事先并不知道它是屬于哪個子分布的(hidden variable),因此 log 里面還有求和, K 個高斯模型的和不是一個高斯模型,對于每個子模型都有未知的α,μ,σ ,直接求導無法計算。需要通過迭代的方法求解。
這就引出了下面這個算法EM算法:
期望最大化算法(EM算法)概述
先來看下整體的步驟的定義:
那么拆解下來詳細看:
第一步 初始化 K 個高斯分布
那么需要設置這幾個高斯分布的均值和標準差,最簡單的方法是設定為數據集本身的均值和標準差,另一種方法是在數據集使用k-means,然后使用由 k means生成的聚類來初始化這K個高斯分布。
下面的例子假設為2個高斯分布,隨機初始化了兩個分布的均值和標準差:
第二步 假設參數已知,去估計隱藏變量的期望,即將數據軟聚類成我們初始化的兩個高斯,這一步稱為期望步驟 或 E-step
公式如圖,中間N()是正態分布的概率密度函數,那么N(A)是指屬于A正太的概率密度是多少,同理N(B)是指屬于B正太的概率密度是多少,那么E(Z_1A)中,1是指某一個點,A是指屬于A正太分布,Z是所謂的隱藏變量或潛在變量,那么通過公式和具體的點和正態分布的均值標準差,就能計算出所有點的期望值。
第三步 利用E步求得的隱藏變量的期望,根據最大似然估計求得參數,然后新得到的參數值重新被用于E步,即基于軟聚類重新估計高斯,即求極大,計算新一輪迭代的模型參數,這一步稱為最大化步驟 或 M-step
這一步就是用第二步的結果作為輸入,來生成新的均值和標準差。
那么新均值,怎么出來的呢?是所有屬于這一類的點的加權平均值,權值就是上面的期望值,如圖:
這樣就得出了聚類A的新均值。
接著計算新標準差的平方即方差,整體思路差不多,套公式(跟傳統計算方差的公式很像)帶進去算屬于該類的所有點加權平均的方差即可,同樣E是之前第二步計算出的期望值:
第四步 我們評估對數似然來檢查收斂,如果它收斂,則認為一切正常,返回結果,如果它不收斂 我們回到第二步直到它收斂
這個計算出來的結果越高,我們越能確定生成的混合模型適合我們有的數據集,所以我們的目的就是通過改變合適的混合系數π,均值μ,方差σ^2,從而來最大化這個值,即達到最大值或每一步開始增加一小部分,這樣就停止運算,然后選擇那些計算好的模型作為高斯混合模型的組成部分。
上面例子是使用方差來,只能衡量一維數據的離散程度,對于二維數據,就用到了協方差(最上面提過的那個式子),那么就不單單是方差的圓形范圍而可以是橢圓范圍了。
使用協方差來進行運算,上面那些數據點就可以分成這樣:
具體的公式與推導可以看這里.
sklearn實現GMM
GMM優缺點
優點:
- 為我們提供軟聚類,軟聚類是多個聚類的示例性隸屬度。
- 在聚類外觀方面很有靈活性
缺點: - 對初始化值很敏感
- 有可能收斂到局部最優
- 收斂速度慢
五、聚類分析過程
1、總體流程
第一步 特征選擇和特征提取
特征選擇是從一組候選特征中選擇特征,我們不必對所有的數據集都使用聚類方法,畢竟運算量非常大,進行選擇并提取后,留下與所需數據強相關的數據從而來進行運算即可,特征提取是對數據進行轉換,以生成新的有用特征(例如PCA)
sklearn實現特征縮放
>>> from sklearn.preprocessing import MinMaxScaler
>>>
>>> data = [[-1, 2], [-0.5, 6], [0, 10], [1, 18]]
>>> scaler = MinMaxScaler()
>>> print(scaler.fit(data))
MinMaxScaler(copy=True, feature_range=(0, 1))
>>> print(scaler.data_max_)
[ 1. 18.]
>>> print(scaler.transform(data))
[[0. 0. ]
[0.25 0.25]
[0.5 0.5 ]
[1. 1. ]]
>>> print(scaler.transform([[2, 2]]))
[[1.5 0. ]]
第二步 選擇一個聚類算法
根據需要做什么和數據的外觀,試驗哪一個算法可以給你更好的結果,沒有任何算法可以普遍地適用于我們可能面臨的問題,在這一步,我們必須選擇一個鄰近度度量,比如歐幾里得距離,余弦距離,Pearson 相關系數等等。
第三步 聚類評價
評估一個聚類的效果如何,除了在可能的情況下對聚類結果進行可視化以外,我們還可以使用一些評分方法來評估,基于特定標準的聚類結構的質量,這些評分方法被稱為指數,每一個指數稱為聚類有效性指標
第四步 聚類結果解釋
可以從最終的聚類結構中學習到什么樣的見解,這一步驟需要領域專業知識為集群提供標簽,并試圖從中推斷出一些見解
2、詳解聚類評價
聚類評價是客觀和定量評估聚類結果的過程,大多數評價指標是通過緊湊性和可分性來定義的,緊湊性是衡量一個聚類中的元素彼此之間的距離,可分性是表示不同聚類之間的距離,聚類方法通常希望產生一個聚類中的元素彼此最相似,而聚類之間最不相同的聚類,聚類評價方法總共有三種:
2.1、外部指標
處理有標簽數據時使用的評分
調整蘭德系數定義
調整蘭德系數優缺點
優點:
- 對任意數量的聚類中心和樣本數,隨機聚類的ARI都非常接近于0;
- 取值在[-1,1]之間,負數代表結果不好,越接近于1越好;
- 可用于聚類算法之間的比較。
缺點:
- 需要真實標簽
舉例調整蘭德系數求解過程:
Sklearn實現
>>> from sklearn import metrics
>>> labels_true = [0, 0, 0, 1, 1, 1]
>>> labels_pred = [0, 0, 1, 1, 2, 2]
>>> metrics.adjusted_rand_score(labels_true, labels_pred)
0.24
2.2、內部指標
大部分非監督學習是沒有評分,所以一般用內部指標比較合理,內部指標僅使用數據來衡量數據和結構之間的吻合度
輪廓系數定義
另外提示下:處理 DBSCAN 時,不要使用輪廓系數,而使用DBCV評價指標。
舉例輪廓系數求解過程:
Sklearn實現
>>> import numpy as np
>>> from sklearn.cluster import KMeans
>>> kmeans_model = KMeans(n_clusters=3, random_state=1).fit(X)
>>> labels = kmeans_model.labels_
>>> metrics.silhouette_score(X, labels, metric='euclidean')
...
0.55
...
2.3、相對指標
這個指標表明兩個聚類結構中哪一個在某種意義上更好,基本上所有的外部指標都能作為相對指標
更多指標詳解可以看這里