掌握了 k-means 算法的原理后,接下来最关键的步骤就是将其应用到实际数据中。本文将通过具体的代码示例,带你从零开始实现 k-means 聚类,包括数据准备、算法实现、结果可视化等完整流程,帮助你快速上手 k-means 的代码应用。
环境准备
在开始代码实现前,需要确保你的开发环境中安装了以下 Python 库,这些库是数据处理和机器学习的常用工具:
NumPy:用于数值计算和数组操作
Pandas:用于数据处理和分析
Matplotlib:用于数据可视化
Scikit-learn:提供了现成的 k-means 实现和数据预处理工具
如果尚未安装,可以通过 pip 命令快速安装:
pip install numpy pandas matplotlib scikit-learn
数据准备与预处理
k-means 算法对数据质量较为敏感,因此数据准备和预处理是至关重要的一步。我们将使用 scikit-learn 提供的模拟数据集进行演示,你也可以替换为自己的实际数据。
示例数据生成
首先,我们生成一个包含 4 个簇的二维数据集,方便后续可视化展示:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
# 生成4个簇的模拟数据,共500个样本,每个样本2个特征
X, y_true = make_blobs(n_samples=500, centers=4, cluster_std=0.60, random_state=0)
# 可视化原始数据
plt.scatter(X[:, 0], X[:, 1], s=50)
plt.title("原始数据集分布")
plt.xlabel("特征1")
plt.ylabel("特征2")
plt.show()
运行这段代码后,你会看到一个散点图,其中包含 4 个明显的密集区域,这些区域就是我们希望通过 k-means 算法识别的簇。
数据标准化处理
如前文所述,k-means 基于距离计算,因此需要对数据进行标准化处理。使用 scikit-learn 的StandardScaler可以轻松实现:
from sklearn.preprocessing import StandardScaler
# 初始化标准化器
scaler = StandardScaler()
# 对数据进行标准化处理
X_scaled = scaler.fit_transform(X)
标准化后的数据均值为 0,标准差为 1,确保了不同特征对距离计算的影响是均衡的。
使用 Scikit-learn 实现 k-means
Scikit-learn 库提供了高效的KMeans类,封装了 k-means 算法的实现,我们可以直接调用它来进行聚类分析。
基本实现步骤
from sklearn.cluster import KMeans
# 1. 初始化k-means模型,指定簇的数量k=4
kmeans = KMeans(n_clusters=4, random_state=42)
# 2. 对标准化后的数据进行拟合
kmeans.fit(X_scaled)
# 3. 获取聚类结果标签
y_kmeans = kmeans.predict(X_scaled)
# 4. 获取最终的质心坐标
centers = kmeans.cluster_centers_
代码参数说明
n_clusters:指定簇的数量 k,这里我们已知数据包含 4 个簇,因此设置为 4
random_state:随机数种子,确保结果可复现
cluster_centers_:模型训练后得到的质心坐标,是一个形状为 (k, n_features) 的数组
predict:对新数据进行聚类预测,返回每个样本所属的簇标签
聚类结果可视化
通过可视化可以直观地观察 k-means 的聚类效果:
# 绘制聚类结果
plt.scatter(X_scaled[:, 0], X_scaled[:, 1], c=y_kmeans, s=50, cmap='viridis')
# 绘制质心位置
plt.scatter(centers[:, 0], centers[:, 1], c='red', s=200, alpha=0.75, marker='X')
plt.title("k-means聚类结果")
plt.xlabel("标准化特征1")
plt.ylabel("标准化特征2")
plt.show()
运行代码后,你会看到不同簇的样本被标记为不同颜色,红色的 "X" 标记表示每个簇的质心位置。理想情况下,同簇的样本会聚集在一起,质心位于簇的中心位置。
确定最佳 k 值的代码实现
当我们不知道数据集中实际的簇数量时,可以使用肘部法来确定最佳 k 值:
# 计算不同k值对应的SSE
sse = []
k_range = range(1, 11) # 测试k从1到10
for k in k_range:
kmeans = KMeans(n_clusters=k, random_state=42)
kmeans.fit(X_scaled)
sse.append(kmeans.inertia_) # inertia_属性表示SSE值
# 绘制肘部图
plt.plot(k_range, sse, 'bo-')
plt.xlabel('k值')
plt.ylabel('误差平方和(SSE)')
plt.title('肘部法确定最佳k值')
plt.show()
在绘制的肘部图中,当 k 值增加时,SSE 会逐渐减小;当 k 值达到真实簇数量时,SSE 的下降速度会明显减缓,形成一个 "肘部",这个肘部对应的 k 值就是最佳选择。
实际应用案例:用户分群分析
下面以一个简化的用户分群案例展示 k-means 的实际应用流程:
1. 加载用户数据
import pandas as pd
# 假设用户数据包含两个特征:消费频率和平均消费金额
data = pd.DataFrame({
'消费频率': [12, 15, 3, 2, 20, 18, 5, 4, 19, 22, 6, 8],
'平均消费金额': [300, 350, 80, 60, 420, 380, 120, 90, 400, 450, 150, 130]
})
2. 数据标准化与聚类
# 标准化数据
scaler = StandardScaler()
data_scaled = scaler.fit_transform(data)
# 使用k=2进行聚类(假设分为高价值用户和普通用户)
kmeans = KMeans(n_clusters=2, random_state=42)
data['用户类型'] = kmeans.fit_predict(data_scaled)
# 查看聚类结果
print(data)
3. 结果分析
聚类完成后,可以通过分析不同簇的特征均值来解释聚类结果:
# 按用户类型分组计算均值
grouped = data.groupby('用户类型').mean()
print("不同用户类型的特征均值:")
print(grouped)
通过结果可以发现,0 类用户可能是消费频率低、消费金额少的普通用户,1 类用户可能是消费频率高、消费金额多的高价值用户,企业可以针对不同类型的用户制定差异化的营销策略。
注意事项与优化建议
处理高维数据:当数据维度较高时,建议先使用 PCA 等降维方法减少特征数量,既能提高效率,又能避免 "维度灾难"
多次运行取最优:由于 k-means 对初始质心敏感,实际应用中可以设置n_init参数(默认 10),多次运行后选择 SSE 最小的结果
处理离群点:在聚类前可以使用箱线图或 Z-score 方法检测并处理离群点,减少其对质心计算的影响
总结
通过本文的代码示例,你可以看到 k-means 算法的完整应用流程,包括数据预处理、模型训练、结果可视化和参数优化等关键步骤。Scikit-learn 的KMeans类提供了便捷的接口,让我们无需从零实现复杂的算法逻辑,就能快速进行聚类分析。
在实际应用中,建议结合具体业务场景选择合适的 k 值,仔细处理数据中的异常值,并通过可视化和统计分析来解释聚类结果,让 k-means 算法真正为业务决策提供支持。