聚类分析
问题
什么是聚类分析?如何用聚类做用户分群?
答案
聚类 vs 分类
| 维度 | 分类 | 聚类 |
|---|---|---|
| 学习方式 | 监督学习(有标签) | 无监督学习(无标签) |
| 目标 | 预测已知类别 | 发现数据中的自然分组 |
| 示例 | 预测用户是否流失 | 将用户分为高/中/低价值群 |
K-Means 聚类
K-Means 将数据分为 K 个簇,每个簇由最近的质心代表:
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
# 用户 RFM 特征
features = df[['recency', 'frequency', 'monetary']]
# 标准化(聚类对尺度敏感)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(features)
# K-Means 聚类
kmeans = KMeans(n_clusters=4, random_state=42, n_init=10)
df['cluster'] = kmeans.fit_predict(X_scaled)
# 查看各群体特征
cluster_profile = df.groupby('cluster').agg({
'recency': 'mean',
'frequency': 'mean',
'monetary': 'mean',
'user_id': 'count'
}).rename(columns={'user_id': 'count'})
print(cluster_profile)
确定最佳 K 值
from sklearn.metrics import silhouette_score
# 肘部法则 + 轮廓系数
results = []
for k in range(2, 10):
km = KMeans(n_clusters=k, random_state=42, n_init=10)
labels = km.fit_predict(X_scaled)
results.append({
'k': k,
'inertia': km.inertia_, # 簇内距离和(越小越好)
'silhouette': silhouette_score(X_scaled, labels) # 越大越好
})
pd.DataFrame(results).set_index('k').plot(subplots=True, figsize=(10, 6))
选 K 的原则
- 肘部法则:Inertia 下降速度变缓的拐点
- 轮廓系数:取值
[-1, 1],越大越好,> 0.5 表示聚类效果好 - 业务合理性:分出的群体是否有业务含义
DBSCAN
DBSCAN 基于密度聚类,能发现任意形状的簇,且自动识别噪声点:
from sklearn.cluster import DBSCAN
db = DBSCAN(eps=0.5, min_samples=5)
df['cluster'] = db.fit_predict(X_scaled)
# -1 表示噪声点
print(df['cluster'].value_counts())
| 维度 | K-Means | DBSCAN |
|---|---|---|
| 需要指定 K | 是 | 否 |
| 簇形状 | 球形 | 任意形状 |
| 噪声处理 | 无 | 自动标记噪声 |
| 适用场景 | 用户分群 | 异常检测 |
常见面试问题
Q1: 聚类在数据分析中有哪些应用?
答案:
- 用户分群:RFM 聚类 → 精细化运营策略
- 异常检测:识别异常交易、异常用户
- 市场细分:发现不同消费群体
- 内容聚类:相似文章/商品聚类
Q2: 聚类前为什么要标准化?
答案: K-Means 使用欧氏距离,如果特征尺度差异大(如金额是万级,频次是个位数),大尺度特征会主导距离计算。标准化后所有特征权重相等。