1. 程式人生 > >資料科學和人工智慧技術筆記 十七、聚類

資料科學和人工智慧技術筆記 十七、聚類

十七、聚類

作者:Chris Albon

譯者:飛龍

協議:CC BY-NC-SA 4.0

凝聚聚類

# 載入庫
from sklearn import datasets
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import AgglomerativeClustering

# 載入資料
iris = datasets.load_iris()
X = iris.data

# 標準化特徵
scaler = StandardScaler()
X_std =
scaler.fit_transform(X)

在 scikit-learn 中,AgglomerativeClustering使用linkage引數來確定合併策略,來最小化(1)合併簇的方差(ward),(2)來自簇對的觀測點的距離均值(average) ,或(3)來自簇對的觀測之間的最大距離(complete)。

其他兩個引數很有用。 首先,affinity引數確定用於linkage的距離度量(minkowskieuclidean等)。 其次,n_clusters設定聚類演算法將嘗試查詢的聚類數。 也就是說,簇被連續合併,直到只剩下n_clusters

# 建立聚類物件
clt = AgglomerativeClustering(linkage='complete', affinity='euclidean', n_clusters=3) # 訓練模型 model = clt.fit(X_std) # 展示簇的成員 model.labels_ ''' array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 2, 0, 2, 0, 2, 0, 2, 2, 0, 2, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 2, 0, 2, 2, 0, 2, 2, 2, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) '''

DBSCAN 聚類

# 載入庫
from sklearn import datasets
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import DBSCAN

# 載入資料
iris = datasets.load_iris()
X = iris.data

# 標準化特徵
scaler = StandardScaler()
X_std = scaler.fit_transform(X)

DBSCAN有三個要設定的主要引數:

  • eps: 觀測到被認為是鄰居的另一個觀測的最大距離
  • min_samples: 小於上面的eps距離的最小觀測數量
  • metric: eps使用的距離度量。 例如,minkowskieuclidean等(請注意,如果使用 Minkowski 距離,引數p可用於設定 Minkowski 度量的指數)

如果我們在訓練資料中檢視簇,我們可以看到已經識別出兩個簇,“0”和“1”,而異常觀測被標記為“-1”。

# 建立 DBSCAN 物件
clt = DBSCAN(n_jobs=-1)

# 訓練模型
model = clt.fit(X_std)

評估聚類

import numpy as np
from sklearn.metrics import silhouette_score
from sklearn import datasets
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs

# 生成特徵矩陣
X, _ = make_blobs(n_samples = 1000,
                  n_features = 10,
                  centers = 2,
                  cluster_std = 0.5,
                  shuffle = True,
                  random_state = 1)

# 使用 k-means 來對資料聚類
model = KMeans(n_clusters=2, random_state=1).fit(X)

# 獲取預測的類別
y_hat = model.labels_

正式地,第 i i 個觀測的輪廓係數是:

s i = b i a i max ( a i , b i ) s_{i} = \frac{b_{i} - a_{i}}{\text{max}(a_{i}, b_{i})}

其中 s i s_{i} 是觀測 i i 的輪廓係數, a i a_{i} i i 和同類的所有觀測值之間的平均距離,而 b i b_{i} i i 和不同類的所有觀測的平均距離的最小值。silhouette_score返回的值是所有觀測值的平均輪廓係數。 輪廓係數介於 -1 和 1 之間,其中 1 表示密集,分離良好的聚類。

# 評估模型
silhouette_score(X, y_hat)

# 0.89162655640721422 

均值移動聚類

# 載入庫
from sklearn import datasets
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import MeanShift

# 載入資料
iris = datasets.load_iris()
X = iris.data

# 標準化特徵
scaler = StandardScaler()
X_std = scaler.fit_transform(X)

MeanShift有兩個我們應該注意的重要引數。 首先,bandwidth設定區域(即觀測核)半徑,用於確定移動方向。 在我們的比喻中,頻寬是一個人可以在霧中看到的距離。 我們可以手動設定此引數,但預設情況下會自動估算合理的頻寬(計算成本會顯著增加)。 其次,有時在均值移動中,觀測核中沒有其他觀測結果。 也就是說,我們足球上的一個人看不到任何其它人。 預設情況下,MeanShift將所有這些“孤例”觀測值分配給最近觀測核。 但是,如果我們想要留出這些孤例,我們可以設定cluster_all = False,其中孤例觀測標籤為 -1。

# 建立 MeanShift 物件
clt = MeanShift(n_jobs=-1)

# 訓練模型
model = clt.fit(X_std)

小批量 KMeans 聚類

小批量 k-means 的工作方式與上一個方案中討論的 k-means 演算法類似。 沒有太多細節,不同之處在於,在小批量 k-means中,計算成本最高的步驟僅在隨機的觀測樣本上進行,而不是所有觀測。 這種方法可以顯著減少演算法發現收斂(即適合資料)所需的時間,而質量成本很低。

# 載入庫
from sklearn import datasets
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import MiniBatchKMeans

# 載入資料
iris = datasets.load_iris()
X = iris.data

# 標準化特徵
scaler = StandardScaler()
X_std = scaler.fit_transform(X)

MiniBatchKMeansKMeans的工作方式類似,有一個顯著性差異:batch_size引數。 batch_size控制每批中隨機選擇的觀測數。 批量越大,訓練過程的計算成本就越高。

# 建立 KMeans 物件
clustering = MiniBatchKMeans(n_clusters=3, random_state=0, batch_size=100)

# 訓練模型
model = clustering.fit(X_std)

KMeans 聚類

# 載入庫
from sklearn import datasets
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import KMeans

# 載入資料
iris = datasets.load_iris()
X = iris.data

# 標準化特徵
scaler = StandardScaler()
X_std = scaler.fit_transform(X)

# 建立 KMeans 物件
clt = KMeans(n_clusters=3, random_state=0, n_jobs=-1)

# 訓練模型
model = clt.fit(X_std)

# 檢視預測類別
model.labels_

'''
array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 0, 0, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2,
       2, 0, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 2, 2,
       0, 0, 0, 0, 2, 0, 2, 0, 2, 0, 0, 2, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0,
       2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 2], dtype=int32) 
'''

# 建立新的觀測
new_observation = [[0.8, 0.8, 0.8, 0.8]]

# 預測觀測的類別
model.predict(new_observation)

# array([0], dtype=int32) 

# 檢視簇中心
model.cluster_centers_

'''
array([[ 1.13597027,  0.09659843,  0.996271  ,  1.01717187],
       [-1.01457897,  0.84230679, -1.30487835, -1.25512862],
       [-0.05021989, -0.88029181,  0.34753171,  0.28206327]]) 
'''