第 82 课 - 实战:客户分群分析
1. 学习目标
完成本课学习后,你将能够:
- 理解客户分群(客户细分)在商业分析中的核心价值与应用。
- 掌握使用 K-Means 聚类算法进行客户分群的完整流程。
- 学会如何对数据进行预处理,特别是标准化处理,以提升聚类效果。
- 利用“肘部法则”客观地确定最佳的聚类数量(K值)。
- 对聚类结果进行解释和可视化,将其转化为有商业价值的洞察。
2. 核心概念
什么是客户分群? 想象你是一家电商平台的运营经理。你的客户成千上万,购买行为千差万别。如果对所有客户都发送同一种促销邮件,效果肯定不好。客户分群就是利用机器学习,根据客户的特征(如购买频率、消费金额、产品偏好等)自动将他们划分为几个内部相似、彼此不同的群组,就像把衣柜里的衣服按季节、场合自动分类一样。这样,你可以为不同的群组设计精准的营销策略。
聚类算法(K-Means)简介 K-Means 是最经典、最常用的无监督学习算法之一。“无监督”意味着我们没有预先定义好的客户标签(如“高价值客户”),而是让算法自己从数据中发现模式。 它的核心思想非常直观,就像整理一个散落着彩色豆子的房间:
- 选代表(初始化):你首先决定要将豆子分成K堆(K个聚类),并随机在房间里点K个位置,作为每堆的初始中心点。
- 归堆(分配):计算每个豆子到这K个中心点的距离,把它划给最近的那个中心点所代表的堆。
- 移中心(更新):每一堆都拥有了自己的豆子,然后重新计算每一堆所有豆子的平均位置,作为该堆新的中心点。
- 重复:重复步骤2和3,直到中心点的位置不再明显变化,或者达到了最大迭代次数。这时,豆子就稳定地分成了K堆。
关键步骤:数据标准化
在聚类时,算法根据“距离”来判断相似性。如果特征之间的尺度差异巨大(比如“年龄”在20-70,“年消费额”在100-100000),那么“年消费额”的微小差异在距离计算中就会占据绝对主导,导致结果不准确。标准化(如使用 StandardScaler) 会将所有特征转换到均值为0、方差为1的尺度上,让每个特征对距离的贡献更公平。
确定K值:肘部法则 我们怎么知道应该把客户分成几群呢?“肘部法则”提供了一个直观的判断标准。
- 我们尝试一系列的K值(例如从2到10)。
- 对于每一个K,计算“簇内误差平方和”(SSE),它衡量的是每个客户到其所属群组中心的距离总和,SSE越小,说明群组内部越紧凑。
- 以K值为横轴,SSE为纵轴画图。通常,随着K增大,SSE会不断下降。但当K增加到某个值后,SSE下降的速度会突然变缓,这个拐点就像一个“肘部”,它所对应的K值通常就是最佳选择。
3. 代码示例
我们将使用UCI的“在线零售II”数据集的一个子集,它包含客户的交易信息。我们将基于客户的消费总额和购买频率进行分群。
import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
import seaborn as sns
# 设置绘图风格和中文显示
plt.style.use('ggplot')
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
# 1. 加载和准备数据 (模拟数据,因原数据集较大)
# 在实际项目中,你可以从CSV文件读取
data = {
'CustomerID': range(1, 101),
'Total_Spend': np.random.exponential(scale=500, size=100).round(2), # 总消费额
'Frequency': np.random.poisson(lam=15, size=100) # 购买频率(次数)
}
df = pd.DataFrame(data)
print("数据预览:")
print(df.head())
print(f"\n数据基本信息:\n客户数: {len(df)}")
# 2. 数据预处理 - 标准化
# K-Means基于距离,标准化至关重要
features = df[['Total_Spend', 'Frequency']]
scaler = StandardScaler()
scaled_features = scaler.fit_transform(features)
print("\n标准化后的数据预览 (前5行):")
print(scaled_features[:5])
# 3. 使用肘部法则确定最佳K值
sse = []
k_range = range(1, 11) # 测试从1到10个聚类
for k in k_range:
kmeans = KMeans(n_clusters=k, random_state=42, n_init=10)
kmeans.fit(scaled_features)
sse.append(kmeans.inertia_) # inertia_ 就是SSE
# 绘制肘部法则图
plt.figure(figsize=(10, 6))
plt.plot(k_range, sse, 'bo-')
plt.xlabel('聚类数量 (K)')
plt.ylabel('簇内误差平方和 (SSE)')
plt.title('肘部法则确定最佳K值')
plt.xticks(k_range)
plt.grid(True)
plt.show()
# 根据图表(假设肘部在K=3处明显),我们选择K=3
optimal_k = 3
print(f"\n根据肘部法则,选择的K值为: {optimal_k}")
# 4. 使用最佳K值执行K-Means聚类
kmeans_final = KMeans(n_clusters=optimal_k, random_state=42, n_init=10)
clusters = kmeans_final.fit_predict(scaled_features)
df['Cluster'] = clusters # 将聚类结果添加到原始DataFrame
# 5. 分析聚类结果
print("\n各聚类的客户数量:")
print(df['Cluster'].value_counts().sort_index())
# 计算每个聚类在原始特征上的中心点(需要进行逆标准化)
cluster_centers = scaler.inverse_transform(kmeans_final.cluster_centers_)
cluster_centers_df = pd.DataFrame(cluster_centers, columns=['Total_Spend', 'Frequency'])
print("\n各聚类中心(原始尺度):")
print(cluster_centers_df.round(2))
# 6. 可视化聚类结果
plt.figure(figsize=(10, 8))
scatter = plt.scatter(df['Total_Spend'], df['Frequency'],
c=df['Cluster'], cmap='viridis', alpha=0.6, edgecolors='w')
plt.xlabel('总消费额')
plt.ylabel('购买频率')
plt.title('客户分群可视化 (K=3)')
plt.colorbar(scatter, label='聚类标签')
# 绘制聚类中心
plt.scatter(cluster_centers[:, 0], cluster_centers[:, 1],
marker='X', s=200, c='red', label='聚类中心')
plt.legend()
plt.grid(True)
plt.show()
# 7. 为聚类命名(业务解释)
cluster_names = {
0: '低价值-低频客户', # 示例名称,需根据中心点数据调整
1: '中价值-中频客户',
2: '高价值-高频客户'
}
df['Cluster_Name'] = df['Cluster'].map(cluster_names)
print("\n聚类命名后的数据预览:")
print(df[['CustomerID', 'Total_Spend', 'Frequency', 'Cluster_Name']].head(10))
4. 实践练习
练习 1 (基础): 在上面的代码中,将 optimal_k 的值手动改为 2 和 4,重新运行聚类和可视化步骤。观察聚类中心和散点图的变化,并尝试用业务语言解释每个新聚类可能代表什么类型的客户。
练习 2 (进阶): 尝试为聚类结果增加一个新特征,例如 Avg_Order_Value (平均订单价值,可由Total_Spend / Frequency近似计算)。使用 Total_Spend 和 Avg_Order_Value 两个特征重新进行分群分析。比较新旧两种特征组合下,得到的客户群组在业务解释上是否有所不同。
练习 3 (挑战): 除了K-Means,尝试使用 sklearn.cluster 中的 AgglomerativeClustering (层次聚类) 或 DBSCAN 算法对同一份数据进行聚类。对比不同算法得到的结果(群组数量、群组形状、对异常值的敏感性),并简述各自的优缺点。
5. 常见错误
- 忽视数据预处理: 直接对原始数据(尤其是包含金额、数量等量纲差异大的特征)进行聚类,导致结果严重偏向于尺度大的特征。解决方案: 无论如何,先进行标准化(
StandardScaler)或归一化(MinMaxScaler)。 - 盲目选择K值: 凭感觉选择聚类数量,或者在没有明显“肘部”的情况下强行选择一个点。解决方案: 结合肘部法则、业务理解(如我们想划分多少种客户层级)以及轮廓系数等指标综合判断。
- 结果解释错误: 只关注算法输出,不对聚类中心进行深入分析,或者给聚类赋予过于牵强的业务含义。解决方案: 将聚类中心(标准化后需逆转换)与原始特征对比,并结合业务知识进行合理命名和描述。
- 忽略异常值: 数据中存在极端异常的客户(如“天文数字”消费),会极大影响K-Means中心点的计算。解决方案: 在聚类前进行异常值分析和处理(如盖帽法、删除或单独分组)。
6. 小结
- 客户分群是实现精准营销和个性化服务的基础,其本质是无监督聚类。
- K-Means 是简单高效的聚类算法,其核心是迭代的“分配”和“更新”过程。
- 数据标准化是聚类前不可或缺的预处理步骤,确保各特征尺度一致。
- 肘部法则是确定聚类数量K的常用启发式方法,需结合业务需求判断。
- 完成聚类后,分析聚类中心并结合业务知识进行解释和命名,才是产生商业价值的关键一步。 在下一课中,我们将进入自然语言处理的实战领域,学习如何构建一个情感分析项目。