K-means聚类实战:用Python手把手教你做客户分群(附完整代码)
在电商和金融行业,精准识别客户群体是提升营销效率的关键。传统的人工分类方法不仅耗时耗力,还难以捕捉复杂的客户行为模式。而K-means算法作为一种经典的无监督学习技术,能够自动发现数据中的自然分组,为商业决策提供数据支持。
本文将带你从零开始实现一个完整的客户分群项目。不同于简单的算法介绍,我们会重点解决实际业务中的三个核心问题:如何准备客户数据?如何确定最佳聚类数量?以及如何解读聚类结果?通过Python代码示例和可视化分析,你将掌握可立即应用于工作的实战技能。
1. 数据准备与探索性分析
客户分群的第一步是获取和理解数据。典型的数据来源包括:
- 交易记录(购买频率、金额、品类偏好)
- 用户行为(页面浏览、点击流、停留时长)
- 人口统计信息(年龄、性别、地域)
假设我们已经从电商平台获取了以下字段的客户数据:
import pandas as pd import numpy as np # 模拟客户数据 np.random.seed(42) data = { 'age': np.random.normal(35, 10, 1000).astype(int), 'annual_income': np.random.lognormal(10.5, 0.4, 1000), 'spending_score': np.random.randint(1, 100, 1000), 'avg_session_duration': np.random.exponential(300, 1000), 'purchase_frequency': np.random.poisson(3, 1000) } df = pd.DataFrame(data)数据预处理的关键步骤:
缺失值处理:检查并填充或删除缺失值
print(df.isnull().sum()) # 检查缺失值异常值检测:使用IQR方法识别和处理异常值
Q1 = df.quantile(0.25) Q3 = df.quantile(0.75) IQR = Q3 - Q1 df = df[~((df < (Q1 - 1.5 * IQR)) | (df > (Q3 + 1.5 * IQR))).any(axis=1)]特征缩放:标准化数值特征
from sklearn.preprocessing import StandardScaler scaler = StandardScaler() scaled_features = scaler.fit_transform(df)
提示:对于分类特征,可以考虑使用独热编码或目标编码,但K-means主要适用于数值型数据。
2. 确定最佳聚类数量
K-means需要预先指定聚类数量K,选择不当会导致结果难以解释。以下是三种常用方法:
2.1 肘部法则(Elbow Method)
通过观察不同K值对应的SSE(误差平方和)变化:
from sklearn.cluster import KMeans import matplotlib.pyplot as plt sse = [] for k in range(1, 11): kmeans = KMeans(n_clusters=k, random_state=42) kmeans.fit(scaled_features) sse.append(kmeans.inertia_) plt.plot(range(1, 11), sse, marker='o') plt.xlabel('Number of clusters') plt.ylabel('SSE') plt.title('Elbow Method') plt.show()2.2 轮廓系数分析
衡量聚类紧密度和分离度的综合指标:
from sklearn.metrics import silhouette_score silhouette_scores = [] for k in range(2, 11): kmeans = KMeans(n_clusters=k, random_state=42) labels = kmeans.fit_predict(scaled_features) score = silhouette_score(scaled_features, labels) silhouette_scores.append(score) plt.plot(range(2, 11), silhouette_scores, marker='o') plt.xlabel('Number of clusters') plt.ylabel('Silhouette Score') plt.title('Silhouette Analysis') plt.show()2.3 间隙统计量(Gap Statistic)
比较实际数据与参考分布的聚类质量差异:
from gap_statistic import OptimalK # 需要安装gap-stat包 optimalK = OptimalK() n_clusters = optimalK(scaled_features, cluster_array=range(1, 11)) print(f'Optimal number of clusters: {n_clusters}')三种方法各有优劣,实际项目中建议结合业务理解综合判断。对于我们的模拟数据,K=5可能是一个合理的选择。
3. 模型训练与调优
确定了最佳K值后,可以训练最终的K-means模型:
final_kmeans = KMeans(n_clusters=5, random_state=42) clusters = final_kmeans.fit_predict(scaled_features) df['cluster'] = clustersK-means对初始质心敏感,可以通过以下方法提升稳定性:
增加n_init参数:多次随机初始化选择最佳结果
kmeans = KMeans(n_clusters=5, n_init=20, random_state=42)使用k-means++初始化:更智能的质心选择方法
kmeans = KMeans(n_clusters=5, init='k-means++', random_state=42)设置max_iter参数:控制最大迭代次数
kmeans = KMeans(n_clusters=5, max_iter=300, random_state=42)
模型训练完成后,检查各簇的统计特征:
cluster_stats = df.groupby('cluster').agg({ 'age': 'mean', 'annual_income': 'mean', 'spending_score': 'mean', 'purchase_frequency': 'mean' }).round(2) print(cluster_stats)4. 结果可视化与业务解读
可视化是理解聚类结果的关键。以下是几种有效的展示方式:
4.1 平行坐标图
展示各特征在不同簇中的分布:
from pandas.plotting import parallel_coordinates plt.figure(figsize=(12, 6)) parallel_coordinates(df, 'cluster', colormap='viridis') plt.title('Parallel Coordinates Plot') plt.show()4.2 雷达图
直观比较各簇的特征均值:
import plotly.express as px fig = px.line_polar(cluster_stats.reset_index(), r='annual_income', theta=cluster_stats.columns, color='cluster', line_close=True, template='plotly_dark') fig.show()4.3 二维投影
使用PCA降维后可视化:
from sklearn.decomposition import PCA pca = PCA(n_components=2) principal_components = pca.fit_transform(scaled_features) df['pca1'] = principal_components[:, 0] df['pca2'] = principal_components[:, 1] plt.scatter(df['pca1'], df['pca2'], c=df['cluster'], cmap='viridis') plt.title('2D PCA Projection') plt.show()基于这些分析,我们可以为每个客户群体制定针对性的营销策略:
| 客户群体 | 特征描述 | 营销建议 |
|---|---|---|
| 群体1 | 高收入、高消费 | 推送高端商品和VIP服务 |
| 群体2 | 中等收入、低频消费 | 发送优惠券刺激消费 |
| 群体3 | 年轻用户、高活跃度 | 推荐社交分享活动 |
| 群体4 | 低收入、低消费 | 提供基础商品和折扣 |
| 群体5 | 高频率、中等消费 | 会员积分和捆绑销售 |
5. 进阶技巧与常见问题
5.1 处理高维数据
当特征维度较高时,可以考虑:
- 使用PCA等降维技术
- 采用特征选择方法
- 尝试更适合高维数据的算法如谱聚类
# 使用PCA降维后再聚类 pca = PCA(n_components=0.95) # 保留95%方差 reduced_data = pca.fit_transform(scaled_features) kmeans_pca = KMeans(n_clusters=5, random_state=42).fit(reduced_data)5.2 类别型特征处理
对于包含类别型特征的数据:
- 使用独热编码
- 采用K-prototypes算法(混合型数据聚类)
- 计算类别间的距离度量
from kmodes.kprototypes import KPrototypes # 假设df包含数值型和类别型特征 kproto = KPrototypes(n_clusters=5, init='Cao') clusters = kproto.fit_predict(df, categorical=[0, 1]) # 指定类别型列索引5.3 评估聚类质量
除了轮廓系数,还可以使用:
- Calinski-Harabasz指数
- Davies-Bouldin指数
- 与业务指标的相关性分析
from sklearn.metrics import calinski_harabasz_score, davies_bouldin_score ch_score = calinski_harabasz_score(scaled_features, clusters) db_score = davies_bouldin_score(scaled_features, clusters) print(f"Calinski-Harabasz Score: {ch_score:.2f}") print(f"Davies-Bouldin Score: {db_score:.2f}")5.4 实时聚类更新
对于流式数据,可以考虑:
- Mini-Batch K-means
- 增量式聚类算法
- 定期重新训练模型
from sklearn.cluster import MiniBatchKMeans mbk = MiniBatchKMeans(n_clusters=5, random_state=42) batch_size = 100 for i in range(0, len(scaled_features), batch_size): mbk.partial_fit(scaled_features[i:i+batch_size])在实际电商项目中,我们发现将聚类结果与RFM模型(最近购买时间、购买频率、消费金额)结合,能够更精准地识别高价值客户。例如,一个高收入但最近没有购买行为的客户群体,可能需要特别的召回策略。