推荐系统为什么必须分成召回和排序两步来做
推荐系统为什么必须分成召回和排序两步来做一亿件商品、200 毫秒延迟推荐系统凭什么敢答应答案是一个被算力逼出来的架构召回先快筛排序再精算。今天把这条分层逻辑讲透。一、背景与痛点把推荐系统想象成一个深夜营业的商场导购货架上摆着一亿件商品顾客只肯等 200 毫秒而这位导购是个每次只能同时掂量几百件商品的精算师。他不可能把一亿件商品逐一过秤再挑出最合适的——那是以小时计的活儿他必须先靠几把快筛子楼层分区、热销榜、顾客的历史口味把候选压到几百件再对这几百件精算。这个先快筛、后精算的结构就是推荐系统最古老也最稳定的架构法则召回在前排序在后。早期协同过滤时代物品库只有千级万级暴力算得动候选生成与打分是揉在一起的可当物品涨到百万、千万全库打分被算力一票否决分层就成了约束下的唯一可行解。理解这层逻辑你才会明白为什么把精排模型直接拿来扫全库是个常识性错误。二、核心原理1. 漏斗的每一层一个典型的工业漏斗有四级括号内是常见量级107∼108 全库 →①召回 103∼104 →②粗排 102∼103 →③精排 101∼102 →④重排 10∼30 曝光10^7\sim10^8\ \text{全库}\ \xrightarrow{\text{①召回}}\ 10^3\sim10^4\ \xrightarrow{\text{②粗排}}\ 10^2\sim10^3\ \xrightarrow{\text{③精排}}\ 10^1\sim10^2\ \xrightarrow{\text{④重排}}\ 10\sim30\ \text{曝光}107∼108全库①召回103∼104②粗排102∼103③精排101∼102④重排10∼30曝光每一层的使命与考核完全不同。召回的使命是别漏用双塔向量匹配这类低成本模型延迟预算只有几毫秒衡量覆盖率与召回率粗排是缓冲层用轻量模型把几千条压到几百条精排才上 DeepFM/DIN 这类重模型对几百条候选精细打分单条成本毫秒级合计恰好填满百毫秒级预算重排处理多样性、商业规则与新鲜度看的是整体业务指标。每一层都在做同一件事用上一层的预算约束把下一层的输入压到它算得动的规模。2. 召回与排序本质是两个问题表面上只是模型轻重不同本质是问题形态不同。召回是集合检索给定用户在全库MMM个物品里捞出一个可能相关的集合衡量 RecallK排序是顺序比较给定用户和已筛出的NNN个候选排出正确顺序衡量 AUC、NDCG。这带来三个推论特征面不同召回广而稀排序窄而密、训练目标不同召回用正样本采样负样本排序用曝光-点击对、评估口径不同召回要在全库上评估排序在候选集内评估即可。这也解释了为什么两个模型不能互相替换。3. 算力账为什么精排不能扫全库把它算成账就一目了然。设全库M108M10^8M108精排单条耗时c0.5msc0.5\text{ms}c0.5ms全库精排一次要Mc108×0.5ms5×104s≈14 小时Mc 10^8\times0.5\text{ms} 5\times10^4\text{s}\approx14\ \text{小时}Mc108×0.5ms5×104s≈14小时即使把单条成本压到5μs5\mu\text{s}5μs也还要 500 秒——远超每请求 200ms 的预算。而分层方案让召回层用近似检索ANN把复杂度从O(M)O(M)O(M)降到约O(logM)O(\log M)O(logM)精排只在几百条上跑重模型总账从小时级压到百毫秒级差了五六个数量级。4. 分层的新风险层间漏检分层不是没有代价如果召回只有一路比如只有热门召回喜欢小众内容的用户就永远进不了候选排序模型再准也排不到没进候选的物品——Recall0 时精度毫无意义。所以工业界用多条互补的召回通道并行。假设RRR路召回相互独立、单路召回率为ρr\rho_rρr并集覆盖率的期望约为1−∏r1R(1−ρr)1-\prod_{r1}^{R}(1-\rho_r)1−r1∏R(1−ρr)这就是多路召回提升覆盖的数学来源。记住一条铁律召回决定上限排序决定下限的实现程度。三、代码实战用 numpy 模拟漏斗逐层截断并顺手算一笔不分层的算力账importnumpyasnp N_POOL10_000_000# 全库候选 1000 万rngnp.random.default_rng(42)scoresrng.random(N_POOL)# 假设的前置打分量CAPS[5000,300,30,20]# 召回/粗排/精排/重排容量names[①召回,②粗排,③精排,④重排]candnp.arange(N_POOL)print(全库,N_POOL,条)forname,capinzip(names,CAPS):kmin(cap,len(cand))topnp.argpartition(scores[cand],-k)[-k:]# 取 Top-kcandcand[top]print(name,-,len(cand),条)# 算力账不分层直接用精排模型扫全库print(不分层全库精排耗时: %.0f s%(N_POOL*0.4e-3))运行输出全库 10000000 条 ①召回 - 5000 条 ②粗排 - 300 条 ③精排 - 30 条 ④重排 - 20 条 不分层全库精排耗时: 4000 s候选数从 1000 万一路过滤到 20 条而不分层直接全库精排需要 4000 秒约 1 小时对比分层方案的百毫秒级预算差距触目惊心。这就是分层架构的第一性原理。四、关键经验/避坑先画漏斗再选模型动手前先定好每层进多少、出多少、给多少延迟再按层选型双塔进召回、小模型做粗排、重模型才上精排。召回要故意多召回宁可带回噪声粗排会去噪也别漏掉相关物品召回数量不足时先加路而不是硬压排序。层间口径必须一致特征版本、标签口径、样本窗口在召回/粗排/精排之间要对齐否则层间分数互不信任系统空转。用曲线定阈值别拍脑袋画召回数量-覆盖率曲线找拐点超过拐点后多出的槽位主要是噪声却要下游多花算力。监控每层的漏检信号统计最终曝光由哪路召回供给“未曝光但精排分高的物品占比”后者是召回漏检的早期预警。小规模系统别硬套五层候选十万级时两路召回 一个精排模型就够了分层每多一层就多一份维护成本。五、完整系列推荐 本文选自《推荐系统详解》100 期系统教程第 051 期召回 vs 排序的分层逻辑每期配可运行 Python 代码。完整系列100 期正文 3 篇番外每期文章代码已在 ima 知识号【Kruptos】持续更新 69 技术知识库计算机视觉、强化学习、推荐系统、大模型微调、操作系统、AI Agent……几乎覆盖全部软硬件技术栈 8 款 AI 技能系列生产、知识库管理、CMMI 受管开发、自进化 Agent 等已在 ima 技能广场上架即装即用✅ 全部免费订阅后续更新自动推送 订阅方式打开 ima腾讯智能工作台→ 搜索「Kruptos」→ 一键订阅或在 ima 内直接搜索《推荐系统详解》。作者Kruptos西电毕业13 年无线通信/DSP/嵌入式科研现深耕 AI 与云原生原创内容转载注明出处。