python3機器學習經典實例-第四章聚類16
用凝聚層次聚類進行數據分組
在介紹凝聚層次聚類之前,我們需要先理解層次聚類(hierarchical clustering)。層次聚類是一組聚類演算法,通過不斷地分解或合併集群來構建樹狀集群(tree-like clusters)。層次聚類的結構可以用一顆樹表示。層次聚類演算法可以是自下而上的,也可以是自上而下的。具體是什麼含義呢?在自下而上的演算法中,每個數據點都被看作是一個單獨的集群。這些集群不斷地合併,直到所有的集群都合併成一個巨型集群。這被稱為凝聚層次聚類。與之相反的是,自上而下層次的演算法是從一個巨大的集群開始,不斷地分解,直到所有的集群變成一個單獨的數據點。你可以在http://nlp.stanford.edu/IR-book/html/htmledition/hierarchical-agglomerative-clustering-1.html 學習更多的內容
無需修改本程序
具體步驟代碼
- 導入程序包
import numpy as npimport matplotlib.pyplot as pltfrom sklearn.cluster import AgglomerativeClusteringfrom sklearn.neighbors import kneighbors_graph
- 添加一些雜訊,增加一些不確定性。定義雜訊函數:
def add_noise(x, y, amplitude): X = np.concatenate((x, y)) X += amplitude * np.random.randn(2, X.shape[1]) return X.T
- 為了演示凝聚層次聚類的優勢,我們用它對一些在空間中是連接在一起、但彼此卻非常接近的數據進行聚類。我們希望連接在一起的數據可以聚成一類,而不是在空間上非常接近的點聚成一類。下面定義一個函數來獲取一組呈螺旋狀的數據點:
def get_spiral(t, noise_amplitude=0.5): r = t x = r * np.cos(t) y = r * np.sin(t) return add_noise(x, y, noise_amplitude)
- 我們再定義一個函數來獲取位於玫瑰曲線上的數據點(rose curve,又稱為rhodonea curve,極坐標中的正弦曲線):
def get_rose(t, noise_amplitude=0.02): # Equation for "rose" (or rhodonea curve); if k is odd, then # the curve will have k petals, else it will have 2k petals k = 5 r = np.cos(k*t) + 0.25 x = r * np.cos(t) y = r * np.sin(t)
- 為了增加多樣性,我們再定義一個hypotrochoid函數:
def get_hypotrochoid(t, noise_amplitude=0): a, b, h = 10.0, 2.0, 4.0 x = (a - b) * np.cos(t) + h * np.cos((a - b) / b * t) y = (a - b) * np.sin(t) - h * np.sin((a - b) / b * t) return add_noise(x, y, 0)
- 定義一個實現凝聚層次聚類的函數:提取標記,然後指定不同聚類在圖形中的標記:迭代數據,用不同的標記把聚類的點畫在圖形中:
def perform_clustering(X, connectivity, title, num_clusters=3, linkage=ward): plt.figure() model = AgglomerativeClustering(linkage=linkage, connectivity=connectivity, n_clusters=num_clusters) model.fit(X) # extract labels labels = model.labels_ # specify marker shapes for different clusters markers = .v* for i, marker in zip(range(num_clusters), markers): # plot the points belong to the current cluster plt.scatter(X[labels==i, 0], X[labels==i, 1], s=50, marker=marker, color=c, facecolors=r) plt.title(title)
- 現在可以定義主函數main了:
if __name__==__main__: # Generate sample data n_samples = 500 np.random.seed(2) t = 2.5 * np.pi * (1 + 2 * np.random.rand(1, n_samples)) X = get_spiral(t) # No connectivity connectivity = None perform_clustering(X, connectivity, No connectivity) # Create K-Neighbors graph connectivity = kneighbors_graph(X, 10, include_self=False) perform_clustering(X, connectivity, K-Neighbors connectivity) plt.show()
- 結果輸出out
從圖 中可以看出,使用連接特徵可以讓我們把連接在一起的數據合成一組,而不是按照它們在螺旋線上的位置進行聚類。
推薦閱讀:
※Python數據處理 II:數據的清洗(預處理)
※Python 中列表和元組有哪些區別?
※如何在本地搞一個小程序的伺服器之我沒有vps我也很絕望呀
※Python unittest單元測試框架 斷言assert