推荐系统
→ 返回应用领域
推荐系统从海量候选中找到用户最感兴趣的内容,是工业界最高频的 AI 应用之一。现代推荐系统通常分为召回和排序两个阶段。
整体架构
用户请求
↓
【召回层】从百万候选中粗筛出 100-1000 个
├── 协同过滤召回
├── 向量召回(ANN 近似最近邻)
├── 热门召回
└── 关键词/标签召回
↓
【粗排层】轻量模型排序,保留 50-200 个(可选)
↓
【精排层】复杂模型精细排序,输出 Top-N
↓
【重排层】多样性、业务规则、去重、广告插入
↓
展示给用户
召回算法
协同过滤(CF)
用户-物品协同过滤:相似用户喜欢的物品,你也可能喜欢:
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np
# user_item_matrix[i][j] = 用户 i 对物品 j 的评分(0 表示未评分)
user_item_matrix = np.array([
[5, 4, 0, 1, 0],
[4, 0, 4, 0, 2],
[0, 0, 5, 4, 0],
])
# 计算用户相似度
user_sim = cosine_similarity(user_item_matrix)
def recommend(user_id, top_k=5):
# 找最相似用户
sim_scores = user_sim[user_id].copy()
sim_scores[user_id] = 0 # 排除自己
similar_users = np.argsort(sim_scores)[::-1][:5]
# 加权汇总相似用户的评分
pred_scores = np.zeros(user_item_matrix.shape[1])
for su in similar_users:
pred_scores += sim_scores[su] * user_item_matrix[su]
# 排除已看过的
seen = np.where(user_item_matrix[user_id] > 0)[0]
pred_scores[seen] = 0
return np.argsort(pred_scores)[::-1][:top_k]向量召回(Two-Tower 双塔模型)
用户塔和物品塔分别生成 Embedding,ANN 检索:
import torch
import torch.nn as nn
class UserTower(nn.Module):
def __init__(self, user_feat_dim, emb_dim=64):
super().__init__()
self.net = nn.Sequential(
nn.Linear(user_feat_dim, 128), nn.ReLU(),
nn.Linear(128, emb_dim),
)
def forward(self, user_features):
return nn.functional.normalize(self.net(user_features), dim=-1)
class ItemTower(nn.Module):
def __init__(self, item_feat_dim, emb_dim=64):
super().__init__()
self.net = nn.Sequential(
nn.Linear(item_feat_dim, 128), nn.ReLU(),
nn.Linear(128, emb_dim),
)
def forward(self, item_features):
return nn.functional.normalize(self.net(item_features), dim=-1)
# 训练目标:用户 Embedding 与正样本物品相似度最大化,与负样本最小化
# 部署:物品 Embedding 离线计算后建 Faiss 索引,在线检索精排:特征交叉模型
DeepFM
结合因子分解机(FM)的显式特征交叉和 DNN 的隐式交叉:
输入特征 → Embedding
↓ ↓
FM 层 DNN 层
(显式二阶交叉)(高阶交叉)
↓ ↓
拼接 → Sigmoid → CTR 预估
DIN(深度兴趣网络)
用注意力机制对用户历史行为建模,权重由候选物品决定:
class AttentionLayer(nn.Module):
"""候选物品对历史行为的注意力权重"""
def forward(self, candidate_emb, history_embs):
# candidate_emb: [B, D]
# history_embs: [B, L, D]
scores = torch.sum(history_embs * candidate_emb.unsqueeze(1), dim=-1)
weights = torch.softmax(scores, dim=-1) # [B, L]
attended = torch.sum(history_embs * weights.unsqueeze(-1), dim=1) # [B, D]
return attended评估指标
| 指标 | 公式 | 说明 |
|---|---|---|
| 精确率@K | 推荐 K 个中命中数 / K | 推荐结果准不准 |
| 召回率@K | 推荐 K 个中命中数 / 总喜欢数 | 找到了多少用户喜欢的 |
| NDCG@K | 归一化折损累积增益 | 考虑排序位置,越靠前越重要 |
| AUC | ROC 曲线面积 | 离线分类能力 |
| 在线 CTR | 点击次数 / 展示次数 | 最终业务指标 |
| 覆盖率 | 被推荐的物品占总物品比例 | 长尾物品被发现的能力 |
冷启动问题
| 场景 | 挑战 | 解决方案 |
|---|---|---|
| 新用户 | 无历史行为 | 基于用户基础属性推荐;引导填写兴趣标签;热门推荐 |
| 新物品 | 无交互数据 | 基于内容特征(文本/图像)相似推荐;强制曝光策略 |
| 新系统 | 无任何数据 | 显式收集偏好;迁移相关领域数据 |
LLM + 推荐
用大模型增强推荐系统的几种方式:
| 方式 | 说明 |
|---|---|
| 物品理解 | 用 LLM 提取物品描述的语义特征,改善冷启动 |
| 用户兴趣挖掘 | 用 LLM 从用户评论/行为中总结兴趣画像 |
| 对话推荐 | 用 LLM 直接与用户对话,理解意图后推荐 |
| 解释生成 | 用 LLM 为推荐结果生成自然语言解释 |