1. 程式人生 > >機器學習之層次聚類及程式碼示例

機器學習之層次聚類及程式碼示例

一、層次聚類

層次聚類是無監督學習方法,可對給定的N個待聚類的樣本進行層次的分類,直到某種條件(類的個數、類間的距離超過某個閾值)滿足為止。

1、層次聚類的劃分

對於層次聚類,可具體分為:

a. 凝聚的(agglomerative)層次聚類:

採用自底向上的策略:先將每個樣本作為一個簇(類),然後不斷地計算各個類之間的相似度/距離、併合並最相近的兩個類成一個大類,直到某個終止條件滿足為止。(可與哈夫曼編碼演算法作類比)

b. 分裂的(divisive)層次聚類:

採用自頂向下的策略,先將所有樣本置於一個簇(類)中,然後根據一些原則逐漸細分為越來越小的類,直到某個終止條件滿足為止。(可與決策樹演算法作類比)

2、類間的距離

在整個聚類的過程中,往往需要計算兩個類的距離來進行凝聚/分隔的操作或者停止迭代的操作。判斷兩個類之間的距離/相似度可有以下三種方法:

a. SingleLinkage/Nearest-Neighbor:

取兩個類中距離最近的兩個樣本的距離作為這兩個類的距離。即最近兩個樣本之間的距離越小,這兩個類的距離就越小。這種計算方法可能導致聚類的結果比較鬆散,且這種鬆散的效應會越來越大。比如當兩個類總體上離得比較遠,但卻有對個別的點比較接近的情況。

b. CompleteLinkage:

取兩個集合中距離最遠的兩個點的距離作為這兩個類的距離,是SingleLinkage的反面極端情況。這種計算方法可能導致兩個類因為個別的點而無法合併成一個類。

c. Average-linkage:

取兩個類中的點兩兩的距離全部加在一起求平均值。這種方法得到的結果可能會受到個別點兩兩的距離的影響(偏大/偏小)。

d. Median-linkage / UCLUS:

median-linkage是average-linkage的一個變種,取兩個類中的點兩兩的距離全部加在一起取中值作為兩個類的距離。取中值與取均值相比,更加能夠減少個人偏移樣本對結果的干擾。

e. Centroids:

先分別計算出兩個類的聚類中心,再取兩個聚類中心的距離作為兩個類的距離。

f. Ward’s method

假設先將兩個類進行合併,得到合併後那個新cluster的均值點;再計算兩個類中的每個點x到均值點的距離,再平方後加起來的結果即兩個類的距離。

公式表示為 這裡寫圖片描述 ,其中 這裡寫圖片描述 為合併後那個新cluster的中心點(均值點)

二、程式碼示例:

from sklearn.datasets.samples_generator import make_moons
X,y_true = make_moons(n_samples=1000,noise=0.05)
import matplotlib.pyplot as plt
plt.scatter(X[:,0],X[:,1],c=y_true)
plt.show()

這裡寫圖片描述

from sklearn.cluster import AgglomerativeClustering
import time
t0 = time.time()
ward  = AgglomerativeClustering(n_clusters=2,affinity='euclidean',linkage='ward',compute_full_tree='false').fit(X)
t = time.time() - t0
plt.scatter(X[:, 0], X[:, 1], c=ward.labels_)
plt.title('time : %f'%t)
plt.show()

這裡寫圖片描述

from sklearn.cluster import KMeans
t0 = time.time()
kmeans = KMeans(init = 'k-means++',n_clusters=2, random_state=8).fit(X)
t = time.time() - t0
plt.scatter(X[:, 0], X[:, 1], c=kmeans.labels_)
plt.title('time : %f'%t)
plt.show()

這裡寫圖片描述

不難看出:基於距離的聚類演算法(劃分聚類、層次聚類),一般很難發現非凸形狀的集合或者大小差別很大的集合。