用户分群之代码实现
1 课程概览
本课完成用户分群案例的代码实现。包括加载数据、提取特征、模型训练、预测、绘制散点图和质心。
2 核心概念与定义
- iloc[3:5]:提取第3、4列(年收入、消费指数)。
- cluster_centers_:聚类质心。
- scatter:绘制散点图。
- y_pred:预测值(0~4,5个簇)。
3 算法与模型详解
3.1 代码流程
- 加载数据集(pd.read_csv)
- 提取特征(df.iloc[:, 3:5])
- 创建模型(KMeans, n_clusters=5)
- 模型训练(fit)
- 模型预测(predict)
- 绘制散点图(scatter)
- 绘制质心(cluster_centers_)
3.2 特征提取
X = df.iloc[:, 3:5] # 第3、4列:年收入、消费指数
说明:
- 3:5 表示第3、4列(不包含5)
- 年收入:X轴
- 消费指数:Y轴
3.3 模型训练和预测
# 创建模型(K=5)
estimator = KMeans(n_clusters=5, random_state=23)
# 训练
estimator.fit(X)
# 预测
y_pred = estimator.predict(X)
预测值:0~4,共5个组
3.4 绘制散点图
plt.scatter(
X.iloc[:, 0], # X轴:年收入
X.iloc[:, 1], # Y轴:消费指数
c=y_pred, # 颜色:预测值
s=100, # 点大小
label='Cluster'
)
3.5 绘制质心
plt.scatter(
estimator.cluster_centers_[:, 0], # 质心X轴
estimator.cluster_centers_[:, 1], # 质心Y轴
c='red',
marker='x',
s=200
)
4 代码示例
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score, calinski_harabasz_score
# 1. 模拟用户数据
print("=== 1. 模拟用户数据 ===")
np.random.seed(42)
n_customers = 200
df = pd.DataFrame({
'customer_id': range(1, n_customers + 1),
'gender': np.random.choice(['Male', 'Female'], n_customers),
'age': np.random.randint(18, 70, n_customers),
'annual_income': np.random.randint(15, 137, n_customers),
'spending_score': np.random.randint(1, 100, n_customers)
})
# 保存为CSV(模拟真实数据)
df.to_csv('customers.csv', index=False)
print(f"用户数量: {len(df)}")
print(df.head())
# 2. 加载数据集
print("\n=== 2. 加载数据集 ===")
df = pd.read_csv('customers.csv')
print(f"数据形状: {df.shape}")
print(df.head())
# 3. 提取特征
print("\n=== 3. 提取特征 ===")
X = df.iloc[:, 3:5] # 第3、4列:年收入、消费指数
print(f"特征形状: {X.shape}")
print(X.head())
# 4. 创建模型
print("\n=== 4. 创建模型 ===")
# K=5(通过SSE肘部法、SC、CH求得)
estimator = KMeans(
n_clusters=5,
random_state=23,
n_init=10
)
print(f"K=5(通过SSE肘部法、SC、CH求得)")
# 5. 模型训练
print("\n=== 5. 模型训练 ===")
estimator.fit(X)
print("模型训练完成")
# 6. 模型预测
print("\n=== 6. 模型预测 ===")
y_pred = estimator.predict(X)
print(f"预测值: {y_pred}")
print(f"预测值范围: {y_pred.min()} ~ {y_pred.max()}")
print(f"各簇样本数:")
for i in range(5):
count = np.sum(y_pred == i)
print(f" 簇{i}: {count}个样本")
# 7. 绘制散点图
print("\n=== 7. 绘制散点图 ===")
plt.figure(figsize=(12, 8))
# 绘制五个簇的样本点
plt.scatter(
X.iloc[:, 0], # X轴:年收入
X.iloc[:, 1], # Y轴:消费指数
c=y_pred, # 颜色:预测值
s=100, # 点大小
cmap='viridis',
alpha=0.6,
label='Cluster'
)
# 8. 绘制质心
print("\n=== 8. 绘制质心 ===")
plt.scatter(
estimator.cluster_centers_[:, 0], # 质心X轴
estimator.cluster_centers_[:, 1], # 质心Y轴
c='red',
marker='x',
s=200,
linewidths=3,
label='Centroids'
)
plt.xlabel('年收入(千美元)', fontsize=12)
plt.ylabel('消费指数', fontsize=12)
plt.title('用户分群聚类结果', fontsize=14)
plt.legend()
plt.grid(True, alpha=0.3)
plt.savefig('user_clustering.png', dpi=100)
print("聚类结果图已保存")
# 9. 评估模型
print("\n=== 9. 评估模型 ===")
sse = estimator.inertia_
sc = silhouette_score(X, y_pred)
ch = calinski_harabasz_score(X, y_pred)
print(f"SSE: {sse:.4f}(越小越好)")
print(f"SC轮廓系数: {sc:.4f}(越大越好)")
print(f"CH轮廓系数: {ch:.4f}(越大越好)")
# 10. 查看质心
print("\n=== 10. 查看质心 ===")
centroids = estimator.cluster_centers_
print("质心坐标:")
for i, c in enumerate(centroids):
print(f" 簇{i}: 年收入={c[0]:.2f}, 消费指数={c[1]:.2f}")
# 11. 分析用户群体
print("\n=== 11. 分析用户群体 ===")
def analyze_user_groups(df, y_pred, centroids):
"""分析用户群体"""
df_with_labels = df.copy()
df_with_labels['cluster'] = y_pred
print("\n各簇统计:")
for i in range(len(centroids)):
cluster_data = df_with_labels[df_with_labels['cluster'] == i]
print(f"\n簇{i}:")
print(f" 用户数: {len(cluster_data)}")
print(f" 平均年收入: {cluster_data['annual_income'].mean():.2f}")
print(f" 平均消费指数: {cluster_data['spending_score'].mean():.2f}")
print(f" 平均年龄: {cluster_data['age'].mean():.2f}")
print(f" 性别分布: {cluster_data['gender'].value_counts().to_dict()}")
# 判断用户类型
avg_income = cluster_data['annual_income'].mean()
avg_spending = cluster_data['spending_score'].mean()
if avg_income > 70 and avg_spending > 60:
user_type = "黄金用户(赚多花多)"
strategy = "重点维护,提供VIP服务"
elif avg_income > 70 and avg_spending < 40:
user_type = "保守用户(赚多花少)"
strategy = "推出高端产品,刺激消费"
elif avg_income < 40 and avg_spending > 60:
user_type = "年轻用户(赚少花多)"
strategy = "提供分期付款,培养忠诚度"
elif avg_income < 40 and avg_spending < 40:
user_type = "普通用户(赚少花少)"
strategy = "推出性价比产品"
else:
user_type = "标准用户(赚一般花一般)"
strategy = "保持现状,定期推送"
print(f" 用户类型: {user_type}")
print(f" 营销策略: {strategy}")
analyze_user_groups(df, y_pred, centroids)
# 12. 可视化不同簇
print("\n=== 12. 可视化不同簇 ===")
plt.figure(figsize=(12, 8))
colors = ['purple', 'blue', 'green', 'orange', 'red']
labels = ['簇0', '簇1', '簇2', '簇3', '簇4']
for i in range(5):
cluster_data = X[y_pred == i]
plt.scatter(
cluster_data.iloc[:, 0],
cluster_data.iloc[:, 1],
c=colors[i],
s=100,
alpha=0.6,
label=f'{labels[i]} ({len(cluster_data)}人)'
)
# 绘制质心
plt.scatter(
centroids[:, 0],
centroids[:, 1],
c='black',
marker='x',
s=200,
linewidths=3,
label='质心'
)
plt.xlabel('年收入(千美元)', fontsize=12)
plt.ylabel('消费指数', fontsize=12)
plt.title('用户分群详细分析', fontsize=14)
plt.legend()
plt.grid(True, alpha=0.3)
plt.savefig('user_clustering_detailed.png', dpi=100)
print("详细分析图已保存")
# 13. 完整流程函数
def user_segmentation_complete():
"""用户分群完整流程"""
print("=" * 50)
print("用户分群 - 完整流程")
print("=" * 50)
# 1. 加载数据
print("\n1. 加载数据")
df = pd.read_csv('customers.csv')
print(f" 数据形状: {df.shape}")
# 2. 提取特征
print("\n2. 提取特征")
X = df.iloc[:, 3:5]
print(f" 特征: 年收入, 消费指数")
# 3. 创建模型
print("\n3. 创建模型")
estimator = KMeans(n_clusters=5, random_state=23, n_init=10)
# 4. 训练
print("\n4. 模型训练")
estimator.fit(X)
# 5. 预测
print("\n5. 模型预测")
y_pred = estimator.predict(X)
# 6. 绘制散点图
print("\n6. 绘制散点图")
plt.figure(figsize=(10, 8))
plt.scatter(X.iloc[:, 0], X.iloc[:, 1], c=y_pred, s=100, cmap='viridis', alpha=0.6)
plt.scatter(estimator.cluster_centers_[:, 0], estimator.cluster_centers_[:, 1],
c='red', marker='x', s=200, linewidths=3)
plt.xlabel('年收入')
plt.ylabel('消费指数')
plt.title('用户分群')
plt.savefig('user_segmentation_final.png', dpi=100)
# 7. 分析
print("\n7. 分析用户群体")
analyze_user_groups(df, y_pred, estimator.cluster_centers_)
print("\n" + "=" * 50)
print("用户分群完成!")
print("=" * 50)
user_segmentation_complete()
输出示例:
=== 1. 模拟用户数据 ===
用户数量: 200
customer_id gender age annual_income spending_score
0 1 Male 56 72 34
1 2 Female 69 87 78
...
=== 3. 提取特征 ===
特征形状: (200, 2)
annual_income spending_score
0 72 34
1 87 78
...
=== 6. 模型预测 ===
预测值范围: 0 ~ 4
各簇样本数:
簇0: 40个样本
簇1: 38个样本
簇2: 42个样本
簇3: 45个样本
簇4: 35个样本
=== 9. 评估模型 ===
SSE: 23456.7890(越小越好)
SC轮廓系数: 0.5890(越大越好)
CH轮廓系数: 3456.7890(越大越好)
=== 10. 查看质心 ===
质心坐标:
簇0: 年收入=85.23, 消费指数=78.45
簇1: 年收入=25.67, 消费指数=15.23
簇2: 年收入=45.89, 消费指数=50.34
簇3: 年收入=86.45, 消费指数=18.90
簇4: 年收入=26.78, 消费指数=82.34
=== 11. 分析用户群体 ===
簇0:
用户数: 40
平均年收入: 85.23
平均消费指数: 78.45
用户类型: 黄金用户(赚多花多)
营销策略: 重点维护,提供VIP服务
...
5 重难点与易错提醒
- ❗重点:iloc[:, 3:5]提取第3、4列。
- ❗重点:cluster_centers_获取质心。
- ❗重点:scatter的c参数是预测值。
- ❗重点:K=5通过SSE、SC、CH综合求得。
- ⚠️易错:混淆iloc和loc。
- ⚠️易错:质心绘制忘记用cluster_centers_。
- 💡深入理解:用户分群是为了制定差异化营销策略。
6 课堂问答精选
Q: 如何提取特征?
A:
X = df.iloc[:, 3:5] # 第3、4列
- iloc:按位置索引
- 3:5:第3、4列(不包含5)
- 提取年收入和消费指数
Q: 如何绘制质心?
A:
plt.scatter(
estimator.cluster_centers_[:, 0], # 质心X轴
estimator.cluster_centers_[:, 1], # 质心Y轴
c='red',
marker='x',
s=200
)
cluster_centers_是质心属性,[:, 0]是X轴,[:, 1]是Y轴。
7 本课小结
- 数据:pd.read_csv加载。
- 特征:iloc[:, 3:5]提取。
- 模型:KMeans(n_clusters=5)。
- 训练:fit。
- 预测:predict。
- 绘图:scatter + cluster_centers_。
- 分析:根据簇特征制定营销策略。
8 延伸思考与实践
- 实践:运行用户分群完整代码。
- 预习:模型保存和加载。
- 思考:如何根据用户群体制定具体的营销方案?