【scikit-learn基础】--『监督学习』之 均值聚类
聚類算法屬于無監督學習,其中最常見的是均值聚類,scikit-learn中,有兩種常用的均值聚類算法:
一種是有名的K-means(也就是K-均值)聚類算法,這個算法幾乎是學習聚類必會提到的算法;
另一個是均值偏移聚類,它與K-means各有千秋,只是針對的應用場景不太一樣,但是知名度遠不如K-Means。
本篇介紹如何在scikit-learn中使用這兩種算法。
1. 算法概述
1.1. K-Means
K-means算法起源于1967年,由James MacQueen和J. B. Hartigan提出。
它的基本原理是是將n個點劃分為K個集群,使得每個點都屬于離其最近的均值(中心點)對應的集群。
K-Means算法主要包含2個部分:
- 距離公式:通常采用歐幾里得距離來計算數據點與質心之間的距離
\(d(X_i, C_j) = ||X_i - C_j||^2\) 其中,\(X_i\)是數據點,\(C_j\)是質心。
- 目標函數:目標是最小化所有數據點與所屬簇的質心之間的距離平方和
\(J = \sum_{j=1}^k \sum_{i=1}^{N_j} ||X_i - C_j||^2\) 其中,\(N_j\)表示第\(j\)個簇中的樣本數量。
1.2. 均值漂移
均值漂移算法最早是由Fukunaga等人在1975年提出的。
它的基本原理是對每一個數據點,算法都會估算其周圍點的密度梯度,然后沿著密度上升的方向移動該點,直至達到密度峰值。
均值漂移算法主要有3個步驟:
- 用核函數估計數據點的密度:常用的核函數比如高斯核,
\(K(x) = \exp(-||x||^2 / (2h^2))\) 其中,\(h\)為帶寬參數,控制核的寬度。
- 均值漂移向量:也就是對于每個數據點,計算其周圍點的密度梯度
- 迭代更新:根據均值漂移向量,每個數據點會沿著密度上升的方向移動,更新自己的位置
2. 創建樣本數據
利用scikit-learn中的樣本生成器,創建一些用于聚類的數據。
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
X, y = make_blobs(n_samples=1000, centers=5)
plt.scatter(X[:, 0], X[:, 1], marker="o", c=y, s=25)
plt.show()
生成了包含5個類別的1000條樣本數據。
3. 模型訓練
首先,劃分訓練集和測試集。
from sklearn.model_selection import train_test_split
# 分割訓練集和測試集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
按照8:2的比例劃分了訓練集和測試集。
3.1. K-Means
對于K-Means算法來說,需要指定聚類的數目,通過觀察數據,我們指定聚類的數目5。
這里的樣本數據比較簡單,能夠一下看出來,實際情況下并不會如此容易的知道道聚類的數目是多少,
常常需要多次的嘗試,才能得到一個比較好的聚類數目,也就是K的值。
基于上面的數據,我們設置5個簇,看看聚類之后的質心在訓練集和測試集上的表現。
from sklearn.cluster import KMeans
# 定義
reg = KMeans(n_clusters=5, n_init="auto")
# 訓練模型
reg.fit(X_train, y_train)
# 繪制質心
_, axes = plt.subplots(nrows=1, ncols=2, figsize=(10, 4))
markers = ["x", "o", "^", "s", "*"]
centers = reg.cluster_centers_
axes[0].scatter(X_train[:, 0], X_train[:, 1], marker="o", c=y_train, s=25)
axes[0].set_title("【訓練集】的質心位置")
axes[1].scatter(X_test[:, 0], X_test[:, 1], marker="o", c=y_test, s=25)
axes[1].set_title("【測試集】的質心位置")
for idx, c in enumerate(centers):
axes[0].plot(c[0], c[1], markers[idx], markersize=10)
axes[1].plot(c[0], c[1], markers[idx], markersize=10)
plt.show()
3.2. 均值漂移
均值漂移聚類,事先是不用指定聚類的數目的,通過調整它的bandwidth參數,
可以訓練出擁有不同數目質心的模型。
下面,設置了bandwidth=5,訓練之后得到了擁有3個質心的模型。
from sklearn.cluster import MeanShift
# 定義
reg = MeanShift(cluster_all=False, bandwidth=5)
# 訓練模型
reg.fit(X, y)
# 繪制質心
_, axes = plt.subplots(nrows=1, ncols=2, figsize=(10, 4))
markers = ["x", "o", "^", "s", "*"]
centers = reg.cluster_centers_
print(len(centers))
axes[0].scatter(X_train[:, 0], X_train[:, 1], marker="o", c=y_train, s=25)
axes[0].set_title("【訓練集】的質心位置")
axes[1].scatter(X_test[:, 0], X_test[:, 1], marker="o", c=y_test, s=25)
axes[1].set_title("【測試集】的質心位置")
for idx, c in enumerate(centers):
axes[0].plot(c[0], c[1], markers[idx], markersize=10)
axes[1].plot(c[0], c[1], markers[idx], markersize=10)
plt.show()
它把左下角的3類比較接近的樣本數據點算作一類。
通過調整 bandwidth參數,也可以得到和 K-Means 一樣的結果,
有興趣的話可以試試,大概設置 bandwidth=2 左右的時候,可以得到5個質心,與上面的K-Means算法的結果類似。
4. 總結
K-Means和均值漂移聚類都是強大的聚類工具,各有其優缺點。
K-Means 的優勢是簡單、快速且易于實現,當數據集是密集的,且類別之間有明顯的分離時,效果非常好;
不過,它需要預先設定簇的數量k,且對初始質心的選擇敏感,所以,對于不是凸形狀或者大小差別很大的簇,效果并不好。
而均值漂移聚類的優勢在于不需要預先知道簇的數量,可以自適應地找到數據的“模式”,對噪聲和異常值也有很好的魯棒性。
不過,與K-Means相比,它需要選擇合適的帶寬參數,對高維數據可能不太有效,且計算復雜度較高。
最后,對于這兩種均值聚類算法來說,選擇哪種取決于數據的性質和應用的需求。
總結
以上是生活随笔為你收集整理的【scikit-learn基础】--『监督学习』之 均值聚类的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 不止八股:阿里内部语雀一些有趣的并发编程
- 下一篇: 聊聊Llama2-Chinese中文大模