从零实现工业级推荐系统全链路,覆盖 召回 → 特征工程 → 精排 三阶段,在 Amazon Books 数据集(30.9 万物品、12.3 万测试用户)上完成端到端实验验证。项目重点展示了负采样偏差的发现与修复过程,体现对训练-服务一致性(Training-Serving Consistency)的深入理解。
- 全链路自主实现:从召回到精排,不依赖第三方推荐框架,所有模块从零编写
- 超长序列召回:基于 Pre-LN Transformer 的 LongRetriever,支持 500 长度用户序列,Recall@100 达 3.52%(SASRec 基线 0.68%)
- 负采样偏差分析:通过三轮实验迭代,发现并量化了负采样导致的 Training-Serving Skew,Pipeline NDCG@10 从 0.0026 提升至 0.0052(+100%)
- 难负例采样策略:混合采样(Top-50 难负例 + 随机负例),使训练分布对齐推理场景
用户历史序列(均值 32 条,最长 500 条)
│
▼
┌────────────────────────────────────┐
│ Stage 1 · 召回(LongRetriever) │ 30.9 万物品 → Top-500
│ Pre-LN Transformer + ICT + MCR │──────────┐
│ Recall@100 = 3.52% │ │
└────────────────────────────────────┘ │
▼
┌────────────────────────────────────┐
│ Stage 2 · 物品特征工程 │ 4 维结构化特征
│ price_tier · rank_tier │──────────┐
│ review_tier · category_id │ │
└────────────────────────────────────┘ │
▼
┌────────────────────────────────────┐
│ Stage 3 · 精排(DIN) │ Top-500 → Top-K
│ TargetAttention + ItemFeatures │──────────▶ 最终推荐
└────────────────────────────────────┘
用户历史序列经 Pre-LN Transformer + CLS token 编码为用户向量,与全库 30.9 万物品向量做内积检索。
关键设计:
- ICT(In-Category Training):按类目过滤用户历史构建训练样本,消除跨类目数据泄露
- MCR(Multi-Channel Retrieval):多兴趣通道独立检索后取最高分合并,捕捉用户多元兴趣
| 方法 | Recall@100 | Recall@500 |
|---|---|---|
| SASRec(基线) | 0.0068 | 0.0290 |
| LongRetriever | 0.0352(+418%) | 0.0910(+214%) |
从 meta_Books.json.gz(237 万条元数据)中提取 4 维结构化特征:
| 特征 | 分档 | 覆盖率 | 说明 |
|---|---|---|---|
price_tier |
6 档 | 95.9% | 价格区间($0–$50+) |
rank_tier |
6 档 | 76.2% | salesRank 对数分桶 |
review_tier |
5 档 | 98.3% | 历史交互数分桶 |
category_id |
34 类 | 100% | 一级类目 |
候选物品 ID ──► item_embedding ──┐
├──► TargetAttention ──► attended_hist
用户历史序列 ──► item_embedding ──┘ │
│
候选物品特征 ──► ItemFeatureEncoder ─────────┤
(price / rank / review / category) │
▼
MLP([target_emb ‖ target_feat ‖
attended_hist ‖ target ⊙ attended])
│
▼
CTR sigmoid
- TargetAttention:以候选物品为 query 对用户历史加权聚合,提取与当前候选相关的兴趣子集
- ItemFeatureEncoder:price(16) + rank(16) + review(16) + category(32) → Linear(80→64) → LN → ReLU
- Embedding 迁移:精排 item_embedding 直接复用召回模型权重初始化
这是本项目最核心的实验分析,展示了推荐系统中 Training-Serving Skew 的识别和解决过程。
数据构建:对全量用户,无论 target 是否被召回,均构建训练样本(1正+19负)。
问题发现:val AUC=0.9967 极高,但 Pipeline Recall@10 仅 0.0080。
根因分析:正负样本特征分布严重不对称:
| review_tier 均值 | 特点 | |
|---|---|---|
| 正样本(target) | 2.47 | 大量冷门物品 |
| 负样本(Top-500) | 3.85 | 84.9% 为最热门物品 |
模型通过热度特征即可区分正负样本,无需学习真正的排序能力。评估时正负样本热度差异明显 → AUC 虚高;部署时候选全是 Top-500 热门物品 → 特征差异消失,AUC 优势无法转化。
修复:只保留 target 在召回 Top-500 中的用户(if target not in candidates: continue),确保正负样本来自同一候选池。
- 训练数据从 246 万条降至 ~20 万条(recall@500 ≈ 8.5% 的用户)
- AUC 从 0.9967 降至 0.9773(指标更诚实),Pipeline Recall@10 从 0.0080 提升至 0.0089(+11%)
改进:99 个负样本(20 个来自 Top-50 难负例 + 79 个随机),更接近实际"从 500 选 10"的推理场景。
| 版本 | 负采样策略 | 训练样本 | val AUC | Pipeline Recall@10 | Pipeline NDCG@10 |
|---|---|---|---|---|---|
| v1(有偏差) | 全量 target + 19 随机负 | 246 万 | 0.9967(虚高) | 0.0080 | 0.0026 |
| v2(修正) | 仅召回内 target + 19 随机负 | ~20 万 | 0.9773 | 0.0089(+11%) | 0.0044(+69%) |
| v3(最优) | 仅召回内 + 20 难 + 79 随机 | ~102 万 | 0.9661 | 0.0097(+21%) | 0.0052(+100%) |
关键 Takeaway:
- 高离线 AUC ≠ 好的线上效果。负采样策略本质上是对线上曝光分布建模,必须与部署场景对齐
- 难负例让模型聚焦于"召回分数高但非 target"的候选,学到更细粒度的排序信号
| 方法 | Recall@10 | Recall@20 | Recall@50 | NDCG@10 |
|---|---|---|---|---|
| 召回直接截断 | 0.0065 | 0.0113 | 0.0227 | — |
| 热门排序 baseline | 0.0018 | 0.0037 | 0.0093 | 0.0008 |
| RecommendFlow(v3) | 0.0097 | 0.0156 | 0.0288 | 0.0052 |
精排 vs 召回截断:Recall@10 +49%,NDCG@10 显著提升 精排 vs 热门排序:Recall@10 +439%,NDCG@10 +550%
RecommendFlow/
├── src/
│ ├── recall/ # 召回模块(LongRetriever)
│ │ ├── model.py # Pre-LN Transformer + CLS
│ │ ├── data_loader.py # ICT 数据构建
│ │ ├── train.py # 召回训练
│ │ └── eval.py # 全库检索评估
│ ├── feature/
│ │ └── extractor.py # 物品结构化特征提取
│ └── rank/
│ ├── model.py # DIN(TargetAttention + ItemFeatureEncoder)
│ ├── train.py # 精排训练(AUC + GAUC)
│ └── build_data.py # 精排数据构建(难负例采样)
├── configs/
│ ├── recall/exp03/ # 召回配置
│ └── rank/ # 精排配置(v1/v2/v3)
├── pipeline.py # 端到端评估
└── results/ # 评估结果
# 1. 召回
python src/recall/train.py --config configs/recall/exp03/ict_full.yaml
python src/recall/eval.py --config configs/recall/exp03/ict_full.yaml \
--checkpoint checkpoints/exp03_ict_full/best_model.pt
# 2. 特征工程
python src/feature/extractor.py \
--data-dir data/processed/amazon --meta-gz data/meta_Books.json.gz
# 3. 精排(v3)
python src/rank/build_data.py --output-dir data/processed/amazon_v3
python src/rank/train.py --config configs/rank/din_v3.yaml \
--recall-checkpoint checkpoints/exp03_ict_full/best_model.pt
# 4. 端到端评估
python pipeline.py \
--recall-config configs/recall/exp03/ict_full.yaml \
--recall-ckpt checkpoints/exp03_ict_full/best_model.pt \
--rank-config configs/rank/din_v3.yaml \
--rank-ckpt checkpoints/rank_din_v3/best_model.pt \
--eval-mode --top-recall 500 --top-rank 50 --eval-k 10 20 50Python 3.8+ | PyTorch 2.0+ | CUDA 12+
numpy · pandas · scikit-learn · tqdm · pyyaml · faiss-cpu