資料科學和人工智慧技術筆記 十七、聚類
十七、聚類
作者:Chris Albon
譯者:飛龍
凝聚聚類
# 載入庫
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
的距離度量(minkowski
,euclidean
等)。 其次,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
使用的距離度量。 例如,minkowski
,euclidean
等(請注意,如果使用 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_
正式地,第 個觀測的輪廓係數是:
其中
是觀測
的輪廓係數,
是
和同類的所有觀測值之間的平均距離,而
是
和不同類的所有觀測的平均距離的最小值。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)
MiniBatchKMeans
與KMeans
的工作方式類似,有一個顯著性差異: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]])
'''