You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python机器学习基于购买行为对用户进行聚类分析?

基于购买数据的用户聚类实现(Python)

嘿,你的这个需求非常典型——基于用户的购买行为做相似性聚类,而且你的数据里用户分组的规律已经很明显了,咱们一步步用Python来实现:

1. 先把数据整理成机器学习能处理的格式

你的原始数据是用户-物品的购买记录,我们需要先把它转换成用户-物品二元矩阵:每个用户占一行,每个物品占一列,用户买过该物品标记为1,没买过标记为0。这样算法才能准确计算用户之间的相似度。

import pandas as pd
from sklearn.metrics import pairwise_distances
from sklearn.cluster import AgglomerativeClustering

# 你的原始购买数据
data = [
    [1, 1],
    [1, 2],
    [1, 3],
    [2, 2],
    [2, 3],
    [3, 8],
    [3, 9],
    [4, 8],
    [4, 9]
]

# 转换成DataFrame方便处理
df = pd.DataFrame(data, columns=['user_id', 'item_id'])

# 构建用户-物品二元矩阵
user_item_matrix = df.pivot_table(index='user_id', columns='item_id', aggfunc=lambda x: 1, fill_value=0)
print("用户-物品矩阵:")
print(user_item_matrix)

输出的矩阵会是这样:

item_id  1  2  3  8  9
user_id               
1        1  1  1  0  0
2        0  1  1  0  0
3        0  0  0  1  1
4        0  0  0  1  1

2. 计算用户间的距离矩阵(对应你提到的需求)

因为是二元购买数据,Jaccard距离是最适合的选择——它衡量的是两个用户购买物品的交集与并集的比值,1减去这个比值就是距离,距离越小说明用户越相似。

# 计算Jaccard距离矩阵(1 - Jaccard相似度)
jaccard_distances = pairwise_distances(user_item_matrix, metric='jaccard')

# 转换成DataFrame,方便直观查看
distance_df = pd.DataFrame(
    jaccard_distances,
    index=user_item_matrix.index,
    columns=user_item_matrix.index
)

print("\n用户间Jaccard距离矩阵:")
print(distance_df)

输出的矩阵完全符合你的预期:

user_id         1         2    3    4
user_id                              
1        0.000000  0.333333  1.0  1.0
2        0.333333  0.000000  1.0  1.0
3        1.000000  1.000000  0.0  0.0
4        1.000000  1.000000  0.0  0.0

能清楚看到:用户1和2的距离约为0.333(相似度很高),用户3和4的距离为0(完全相似),和你观察到的规律一致。

3. 执行聚类分析

这里给你两种简单有效的方法:

方法一:层次聚类(Agglomerative Clustering)

适合你这种已经有初步聚类预期的场景,我们可以直接指定聚类数量为2:

# 基于预先计算好的距离矩阵执行层次聚类
cluster = AgglomerativeClustering(
    n_clusters=2,
    affinity='precomputed',  # 告诉模型我们已经传入了距离矩阵
    linkage='average'
)

# 拟合模型,得到每个用户的聚类标签
cluster_labels = cluster.fit_predict(jaccard_distances)

# 把结果和用户ID对应起来
result = pd.DataFrame({
    'user_id': user_item_matrix.index,
    'cluster_label': cluster_labels
})

print("\n层次聚类结果:")
print(result)

输出结果:

user_id  cluster_label
0        1              0
1        2              0
2        3              1
3        4              1

方法二:K-Means聚类

如果你明确知道要分成2组,K-Means也是个不错的选择,对于你的小数据量来说,结果和层次聚类一致:

from sklearn.cluster import KMeans

kmeans = KMeans(n_clusters=2, random_state=42)
kmeans_labels = kmeans.fit_predict(user_item_matrix)

kmeans_result = pd.DataFrame({
    'user_id': user_item_matrix.index,
    'cluster_label': kmeans_labels
})

print("\nK-Means聚类结果:")
print(kmeans_result)

额外补充

  • 为什么选Jaccard而不是余弦相似度?因为你的数据是二元存在型(只有买/没买,没有评分),Jaccard更关注两个用户共同购买物品占总购买物品的比例,而余弦相似度更适合有数值评分的场景。
  • 如果后续数据量变大,计算全量距离矩阵效率变低,可以换成近似聚类算法(比如MiniBatchKMeans),或者基于邻域的相似性匹配方法。

内容的提问来源于stack exchange,提问作者mortensen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 11:01:31