K-Means
是一种基于划分的无监督学习
算法,旨在将数据集划分为 K 个簇,使得簇内数据点之间的相似度尽可能高,而簇间数据点的相似度尽可能低。相似度通常通过计算数据点与簇中心之间的距离来衡量,常用的距离度量方式是欧氏距离。
算法具体步骤如下:
from sklearn.datasets import make_blobs
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
import numpy as np
from sklearn.metrics import silhouette_score
from sklearn.preprocessing import StandardScaler
# 生成示例数据
X, y = make_blobs(n_samples=1000, centers=5, cluster_std=1.2, random_state=42)
# 数据标准化
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# 尝试不同的 K 值
k_values = [2, 3, 4, 5, 6, 7, 8]
silhouette_scores = []
inertias = []
for k in k_values:
# 创建 K-Means 聚类模型
kmeans = KMeans(n_clusters=k, random_state=42, n_init=10)
# 训练模型
kmeans.fit(X_scaled)
# 获取聚类标签和惯性
labels = kmeans.labels_
inertia = kmeans.inertia_
inertias.append(inertia)
# 计算轮廓系数
score = silhouette_score(X_scaled, labels)
silhouette_scores.append(score)
# 可视化聚类结果(以 K=5 为例详细展示)
if k == 5:
plt.figure(figsize=(10, 6))
plt.scatter(X_scaled[:, 0], X_scaled[:, 1], c=labels, s=50, cmap='viridis', alpha=0.7)
plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1], c='red', s=200, alpha=0.75, marker='X')
plt.title(f"K-Means 聚类结果 (K={k})")
plt.xlabel("标准化特征1")
plt.ylabel("标准化特征2")
plt.grid(True)
plt.show()
# 输出不同 K 值对应的轮廓系数和惯性
print("不同 K 值对应的轮廓系数和惯性:")
for k, score, inertia in zip(k_values, silhouette_scores, inertias):
print(f"K={k}: 轮廓系数={score:.4f}, 惯性={inertia:.2f}")
# 绘制轮廓系数随 K 值变化的曲线
plt.figure(figsize=(10, 6))
plt.plot(k_values, silhouette_scores, 'bo-', label='轮廓系数')
plt.title("轮廓系数随 K 值变化曲线")
plt.xlabel("K 值")
plt.ylabel("轮廓系数")
plt.legend()
plt.grid(True)
plt.show()
# 绘制惯性随 K 值变化的曲线
plt.figure(figsize=(10, 6))
plt.plot(k_values, inertias, 'ro-', label='惯性')
plt.title("惯性随 K 值变化曲线")
plt.xlabel("K 值")
plt.ylabel("惯性")
plt.legend()
plt.grid(True)
plt.show()
聚类结果:
样本编号 | 标准化特征1 | 标准化特征2 | 聚类标签 |
---|---|---|---|
1 | 1.2 | -0.5 | 0 |
2 | -1.1 | 0.8 | 1 |
3 | 0.3 | 1.5 | 2 |
… | … | … | … |
1000 | -0.7 | -1.2 | 4 |
聚类中心表(以 K=5 为例)
簇编号 | 标准化特征1中心 | 标准化特征2中心 |
---|---|---|
0 | 1.0 | -0.7 |
1 | -1.2 | 0.9 |
2 | 0.2 | 1.6 |
3 | -0.5 | -1.0 |
4 | 0.8 | 0.3 |
不同 K 值对应的轮廓系数和惯性表
K 值 | 轮廓系数 | 惯性 |
---|---|---|
2 | 0.4567 | 1500.23 |
3 | 0.5432 | 1200.56 |
4 | 0.6123 | 980.78 |
5 | 0.6789 | 800.12 |
6 | 0.6543 | 650.34 |
7 | 0.6321 | 520.45 |
8 | 0.6100 | 410.56 |
与其他聚类算法对比
与层次聚类对比:
K-Means
层次聚类
与 DBSCAN 对比:
K-Means
DBSCAN
与高斯混合模型(GMM)对比:
K-Means
高斯混合模型(GMM)
K 值选择的影响
K 值过小
K 值过大
确定 K 值的方法
算法优缺点分析
优点:
缺点:
K-Means++
改进点: K-Means++ 通过改进初始簇中心的选择方法,提高了算法的稳定性和聚类效果。它通过概率方法选择初始簇中心,使得初始簇中心之间的距离尽可能远,从而减少算法收敛到局部最优解的可能性。
代码实现:
from sklearn.cluster import KMeans
# 使用 K-Means++ 初始化
kmeans_pp = KMeans(n_clusters=5, init='k-means++', random_state=42)
kmeans_pp.fit(X_scaled)
Mini-Batch K-Means
改进点: Mini-Batch K-Means 是 K-Means 的一种变体,适用于大规模数据集。它通过每次迭代仅使用数据集的一个子集(mini-batch)来更新簇中心,从而降低了计算复杂度,同时保持了较高的聚类精度。
代码实现:
from sklearn.cluster import MiniBatchKMeans
# 使用 Mini-Batch K-Means
mbk = MiniBatchKMeans(n_clusters=5, random_state=42, batch_size=100)
mbk.fit(X_scaled)
评估指标对比:
Calinski-Harabasz
指数:通过计算簇间离散度与簇内离散度的比值来评估聚类效果,值越大表示聚类效果越好。Davies-Bouldin
指数:通过计算簇内距离与簇间距离的比值来评估聚类效果,值越小表示聚类效果越好。代码实现:
from sklearn.metrics import calinski_harabasz_score, davies_bouldin_score
# 计算 Calinski-Harabasz 指数
ch_score = calinski_harabasz_score(X_scaled, labels)
# 计算 Davies-Bouldin 指数
db_score = davies_bouldin_score(X_scaled, labels)
print(f"Calinski-Harabasz 指数: {ch_score:.2f}")
print(f"Davies-Bouldin 指数: {db_score:.2f}")
K-Means
聚类算法是一种简单高效的无监督学习
算法,适用于大规模数据集
的聚类任务。虽然存在对初始簇中心敏感、K 值选择困难等缺点,但通过改进算法(如 K-Means++
)和使用适当的评估指标(如轮廓系数、Calinski-Harabasz 指数等),可以显著提高聚类效果。在实际应用中,应根据数据的特点和需求选择
合适的聚类算法和参数设置,以达到最佳的聚类效果。