推荐系统实战系列

37 阅读7分钟

嗨,朋友!

聊到推荐系统,你可能会想到抖音的无限刷刷刷,或者淘宝的“猜你喜欢”。它就像是电商的灵魂,直接关系到用户体验和平台的 GMV。别担心它有多复杂,今天我们就用最接地气的方式,把它拆解得明明白白。

想象一下,我们正在为一个电商网站搭建推荐模块,最终目标是:在用户浏览商品详情页时,为他推荐“猜你喜欢”的商品。

第一步:理解核心思想——推荐系统在做什么?

在敲代码之前,先花一分钟理解它的本质。推荐系统无非就是在解决三个问题:

  1. 你是谁?(用户画像) :你需要知道你的用户是谁,他喜欢什么。
  2. 货是什么?(物品特征) :你需要了解你的商品,它有什么特点。
  3. 如何匹配?(推荐算法) :找到连接“你”和“货”的最佳桥梁。

我们今天的主角是协同过滤(Collaborative Filtering) ,这是推荐系统领域的“Hello World”,思想极其朴素: “物以类聚,人以群分” 。我们会先从它入手,让你快速建立体感。

第二步:准备“弹药”——数据和工具

任何系统都离不开数据。我们先用 Python 模拟一个最简单的用户-商品评分数据。

1. 环境准备

你需要安装 pandas 和 scikit-learn 这两个神级库。

pip install pandas scikit-learn

2. 模拟数据

在真实项目中,这些数据来自你的数据库。这里我们创建一个 DataFrame 来模拟。

import pandas as pd

# 模拟用户对商品的评分数据 (1-5分)
data = {
    'user_id': [1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 5, 5],
    'item_id': ['A', 'B', 'C', 'A', 'C', 'A', 'B', 'D', 'B', 'D', 'C', 'D'],
    'rating': [5, 4, 1, 4, 3, 1, 2, 5, 4, 4, 5, 3]
}

df = pd.DataFrame(data)
print("原始评分数据:")
print(df)

第三步:核心算法实现——基于用户的协同过滤

“人以群分”的思路是:找到和你品味相似的用户,然后把他们都喜欢、但你还没见过的商品推荐给你。

1. 计算用户相似度

怎么判断两个用户品味相似?最简单的方法就是看他们对同一商品的评分是否接近。我们可以用余弦相似度(Cosine Similarity) 来衡量。

首先,我们需要把数据转换成用户-商品矩阵(行是用户,列是商品,值是评分)。

# 创建用户-商品评分矩阵
user_item_matrix = df.pivot_table(index='user_id', columns='item_id', values='rating').fillna(0)
print("\n用户-商品评分矩阵:")
print(user_item_matrix)

输出会是这个样子,没评过分的就用 0 填充:

item_id  A  B  C  D
user_id              
1        5  4  1  0
2        4  0  3  0
3        1  2  0  5
4        0  4  0  4
5        0  0  5  3

接下来,用 scikit-learn 轻松计算用户间的相似度。

from sklearn.metrics.pairwise import cosine_similarity

# 计算用户间的余弦相似度
user_similarity = cosine_similarity(user_item_matrix)
print("\n用户相似度矩阵:")
print(user_similarity)

这个矩阵的每个值 user_similarity[i, j] 就代表用户 i+1 和用户 j+1 的相似度。

2. 生成推荐

现在,我们有了相似度,可以为任何一个用户生成推荐了。我们以用户 1 为例。

推荐逻辑:

  1. 找到和用户 1 最相似的 K 个用户(比如 K=2)。
  2. 找出这些相似用户评价过,但用户 1 没评价过的商品。
  3. 根据相似用户的评分和相似度,预测用户 1 对这些商品的可能评分。
  4. 推荐预测评分最高的 N 个商品。

下面是完整的推荐函数:

def recommend_items(user_id, user_item_matrix, user_similarity, k=2, n=2):
    """
    为指定用户推荐商品
    
    :param user_id: 目标用户ID
    :param user_item_matrix: 用户-商品矩阵
    :param user_similarity: 用户相似度矩阵
    :param k: 选择最相似的K个用户
    :param n: 推荐N个商品
    :return: 推荐的商品列表
    """
    # 1. 找到目标用户的索引
    user_idx = user_id - 1 # 假设user_id从1开始,索引从0开始
    
    # 2. 获取所有用户的相似度,并排序
    sim_scores = list(enumerate(user_similarity[user_idx]))
    sim_scores = sorted(sim_scores, key=lambda x: x[1], reverse=True)
    
    # 3. 获取最相似的K个用户的索引(排除自己)
    top_k_users_idx = [i[0] for i in sim_scores[1:k+1]]
    
    # 4. 获取目标用户已评分的商品
    known_items = set(user_item_matrix.columns[user_item_matrix.loc[user_id] > 0])
    
    # 5. 计算推荐分数
    recommendations = {}
    for similar_user_idx in top_k_users_idx:
        # 相似用户的评分
        similar_user_ratings = user_item_matrix.iloc[similar_user_idx]
        # 用户间的相似度
        similarity_score = user_similarity[user_idx][similar_user_idx]
        
        # 遍历相似用户评分过的所有商品
        for item_id, rating in similar_user_ratings.items():
            # 如果目标用户没评分过
            if item_id not in known_items and rating > 0:
                # 累加加权评分
                if item_id not in recommendations:
                    recommendations[item_id] = 0
                recommendations[item_id] += similarity_score * rating

    # 6. 按分数排序,返回前N个
    sorted_recommendations = sorted(recommendations.items(), key=lambda x: x[1], reverse=True)
    
    return [item[0] for item in sorted_recommendations[:n]]

# --- 为用户1推荐商品 ---
recommended_items = recommend_items(user_id=1, user_item_matrix=user_item_matrix, user_similarity=user_similarity)
print(f"\n为用户 1 推荐的商品是: {recommended_items}") 
# 预期输出可能是 ['D', 'C'] 或类似,取决于相似度计算

运行一下,你就能得到给用户 1 的推荐结果了!

第四步:从原型到生产——你需要思考的更多

上面的代码是学习用的“玩具”,但思路和工业级应用是一致的。当你主导一个真实的电商推荐系统时,还需要考虑这些:

  • 数据规模与性能:当用户和商品数量达到百万、千万级,上面的矩阵计算会变得非常慢。你需要:

    • 分布式计算:使用 Spark MLlib 等工具在集群上进行计算。
    • 近似最近邻搜索(ANN) :用 Faiss、Annoy 等库快速找到相似用户/商品,而不是两两计算。
  • 数据稀疏性:大部分用户只评价了极少数商品,矩阵非常稀疏,导致相似度计算不准。这时你需要:

    • 矩阵分解(Matrix Factorization) :像 SVD、ALS 等算法,能挖掘出用户的隐式特征(如“喜欢电子产品”)和商品的隐式特征(如“是电子产品”),即使数据稀疏也能有效推荐。
  • 实时性:用户刚浏览完一个商品,推荐列表应该立刻更新。这需要:

    • 流式处理:使用 Flink、Spark Streaming 实时处理用户行为日志。
    • 在线学习:模型能够实时更新,而不是每天离线训练一次。
  • 混合策略:没有一种算法是万能的。一个成熟的推荐系统通常是多种策略的组合:

    • 协同过滤:挖掘群体智慧。
    • 基于内容推荐:推荐和用户历史喜欢的商品“长得像”的(比如同品牌、同类别)。
    • 热门推荐:解决新用户的冷启动问题。
    • 业务规则:比如“新品优先”、“高利润商品优先”等。

总结:你的学习路径图

今天,我们从最简单的协同过滤入手,用代码搭建了一个可运行的推荐原型。这只是起点,一个充满魅力的起点。

对于想深入的你,我建议的学习路径是:

  1. 巩固基础:彻底搞懂协同过滤(基于用户和基于物品)和矩阵分解(SVD, ALS)。
  2. 拥抱深度学习:学习 Wide & Deep、DeepFM 等模型,它们能更好地融合特征,效果通常更好。
  3. 关注系统工程:了解推荐系统的整体架构,包括数据层、计算层、服务层、评估层。
  4. 动手实践:参加 Kaggle 上的推荐竞赛,或者自己找个公开数据集(如 MovieLens)复现一篇顶会论文。

搭建推荐系统的过程,就是不断理解用户、理解业务、并用技术创造价值的过程。这趟旅程非常有意思,祝你玩得开心!如果过程中遇到任何问题,随时可以再来聊聊。