搜广推笔记 召回
搜广推[召回]
Created by: Yuanpeng QU
Created time: 2025年8月5日 22:51
一、 推荐系统总体架构 (Overall Recommendation System Architecture)
1. 级联漏斗范式 (Cascading Funnel Paradigm) 现代大规模推荐系统的核心架构,普遍遵循一种级联漏斗范式 (Cascading Funnel Paradigm)。这个范式的诞生,是为了解决一个根本性的矛盾:一方面,我们的候选物品库是海量的(百万、千万甚至上亿级别);另一方面,用户的屏幕空间是有限的,且要求响应速度极快(毫秒级)。
因此,我们不可能对所有物品都用最复杂的模型进行最精确的计算。漏斗范式通过设置多个层层递进的过滤环节,实现了从海量到少量,从粗糙到精准的逐级筛选,在计算效率和推荐效果之间取得了极致的平衡。
这个漏斗通常包含以下四个核心层级:
1. 召回层 (Recall Layer)
- 核心目标:“海选”——保证覆盖率与多样性
- 召回层的首要任务是从全量的、数以亿计的物品库中,快速、高效地筛选出一个几百到几千的、与用户兴趣可能相关的候选集合。它的核心目标是“宁可错杀,不可放过”,即尽可能地保证用户未来真正会感兴趣的物品,都包含在这个候选集里。它追求的是高召回率 (Recall Rate),可以牺牲一定的精确率。
- 处理规模: 从全量(10^8 - 10^9+)筛选至中等规模(10^2 - 10^3)。
- 模型/策略特点:
- 速度第一:模型和策略必须极度高效,计算复杂度低。
- 多路并行:通常会并行运行数十甚至上百路不同的召回策略,并将结果合并,以保证候选集的多样性。常见的召回策略包括:
- 协同过滤:UserCF, ItemCF, Swing 等。
- 向量化召回:最主流的方式,如双塔模型 (DSSM)。
- 图模型召回:DeepWalk, GNN 等。
- 序列模型召回:SDM 等。
- 策略性召回:热门召回、新上物品召回、复购召回、地理位置召回等。
- 一个比喻:招聘中的“简历筛选”:
- HR 助手面对成千上万份简历,他会用一些简单的规则(如学历、关键词、工作年限)快速过滤,筛选出几百份基本符合要求的简历进入下一轮。他不会去深究每份简历的细节,目标是快速缩小范围,别把合适的人漏掉。
2. 粗排层 (Coarse Ranking Layer)
- 核心目标:“初试”——初步过滤,减轻精排压力
- 粗排层是一个“缓冲带”或“减压阀”,位于召回和精排之间。它使用比召回更丰富但比精排更简单的特征和模型,对召回送来的几百上千个物品进行一次快速的排序,进一步筛选掉那些明显不那么相关的物品。
- 处理规模: 从中等规模(10^2 - 10^3)筛选至小规模(10^2 级别)。
- 模型/策略特点:
- 平衡效率与效果:模型比召回复杂,但远比精排简单,要求在可接受的延迟内完成计算。
- 特征简化:会使用部分用户和物品的交叉特征,但会避免使用那些计算开销巨大的特征。
- 常用模型:逻辑回归 (LR)、浅层的神经网络 (MLP)、或简化版的精排模型。
- 一个比喻:招聘中的“电话面试”
- 招聘专员对通过简历筛选的几百人进行一轮简短的电话沟通,通过一些标准化的、核心的问题,快速淘汰掉那些明显不合适的候选人,只把几十个最有希望的留给部门经理去面试。
3. 精排层 (Fine-Ranking Layer)
- 核心目标:“终面”——精准排序,最大化核心指标
- 精排层是整个推荐系统最核心、最能体现技术水平的部分。它的目标是对粗排送来的上百个高质量候选物品,使用最复杂的模型和最丰富的特征,进行最精确的个性化排序。它追求的是高精确率 (Precision),直接对最终的业务指标(如CTR、CVR、GMV)负责。
- 处理规模: 从小规模(10^2 级别)排序后,输出最终呈现给用户的几十个物品的有序列表。
- 模型/策略特点:
- 效果第一:在延迟允许的范围内,可以不计代价地使用复杂的模型和特征。
- 模型复杂:广泛使用各种深度学习模型,如 Wide&Deep, DeepFM, DIN, DCN, MMoE 等。
- 特征海量:会用到用户、物品、上下文、行为序列、交叉组合等成百上千维,甚至更多的特征。
- 一个比喻:招聘中的“专家小组面试”
- 部门经理、总监、核心技术专家组成面试小组,对最终的几十位候选人进行长达数小时的、全方位的深入面试。他们会动用所有能考察的信息和手段,最终给出一个非常精确的候选人能力排序,决定录用谁,以及录用优先级。
4. 重排层 (Re-ranking Layer)
- 核心目标:“发Offer前的最终考量”——业务调控,提升整体体验
- 在精排之后,列表已经是按照某个指标(如预估点击率)从高到低排好的。但一个好的推荐结果,除了“准”,还需要考虑多样性、新颖性、公平性等宏观指标。重排层的目标就是对这个已经排好的列表进行微调,以优化最终的用户体验和生态健康。
- 处理规模: 对精排输出的 Top-N 结果(如前50个)进行局部顺序调整。
- 模型/策略特点:
- 规则驱动:大量使用业务规则和启发式算法。
- 列表级优化:它的优化目标是整个列表,而不是单个物品。
- 常见操作:
- 打散:避免同类目、同作者或同品牌的商品连续出现。
- 去重:过滤掉用户近期已经看过或消费过的内容。
- 提权/降权:提升新品、高利润商品的权重,打压过曝内容。
- N-box:在固定位置(如第3位)强制插入一个运营指定的内容。
- 一个比喻:招聘中的“确定录用名单”
- 面试结束后,管理层看着排好序的候选人名单。他们可能会说:“前两名都是搞算法的,第三名虽然分数稍低但是搞工程的,为了团队平衡,我们把第三名提上来,让他排第二。” 或者 “第一名虽然技术最强,但要求的薪资太高/无法立即入职,我们把第二名排在最前面。” 这就是基于整体考量对局部顺序的微调。
二、 召回层核心技术详解 (Detailed Core Technologies of the Recall Layer)
1. 召回模型的基石:双塔模型 (Foundation: Two-Tower Model)
在现代推荐系统的召回阶段,双塔模型(Two-Tower Model)已经成为事实上的行业标准和基石架构。它之所以如此成功,是因为它优雅地解决了从海量候选集中进行高效语义匹配的核心难题。
1.1. 向量召回基本原理 (Principle of Vector Recall)向量召回的诞生,是为了解决传统召回方法(如基于协同过滤或标签匹配)的根本性缺陷:泛化能力弱和语义鸿沟问题。传统方法很难发现用户潜在的、跨领域的兴趣。
向量召回的基本原理,是将推荐问题从“匹配”问题转化为了一个“空间距离”问题。
- 万物皆可向量化 (Embedding Everything):其核心思想是将系统中的两种核心实体——用户 (User) 和 物品 (Item),通过深度学习模型,分别映射(或称为“嵌入”,Embedding)到一个共同的、高维的向量空间中。这个空间也被称为“语义空间”或“兴趣空间”。
- 以“距离”度量“相关性” (Proximity as Relevance):在这个被学习出来的空间里,向量之间的几何距离被赋予了语义上的意义。如果一个用户的向量和一个物品的向量在这个空间中的位置非常接近,我们就认为该用户对这个物品的兴趣程度很高。
- 核心度量:内积/余弦相似度 (Core Metric: Dot Product / Cosine Similarity):衡量“距离”最常用且最高效的方式就是计算两个向量的点积 (Dot Product)。在对向量进行 L2 归一化(即长度统一为1)之后,点积在数学上等价于余弦相似度 (Cosine Similarity),直接度量了两个向量在方向上的对齐程度。点积越大,代表夹角越小,兴趣越一致。
- 一个比喻:兴趣地图
- 我们可以把这个高维向量空间想象成一张“兴趣地图”。一个深度科幻迷用户的坐标,会落在地图上“硬核科幻”这个区域;而电影《流浪地球》的坐标,也会落在同一个区域。因此,通过计算地图上两个坐标点的距离,我们就能判断他们的匹配程度,即便这个用户以前从未看过《流浪地球》。
1.2. 模型架构:用户塔与物品塔 (Architecture: User & Item Towers)双塔模型就是实现上述“向量化”和“映射”过程的具体神经网络结构。它由两个相互独立、结构上非对称的子网络(塔)组成。
- 用户塔 (User Tower / Query Tower):
- 输入:关于用户的一切特征。包括:
- 用户画像特征:年龄、性别、地域等。
- 长期行为特征:历史点击/购买过的物品序列。
- 实时上下文特征:当前时间、使用的设备、最近的几次操作等。
- 结构:一个深度神经网络(DNN),通常由多层全连接层(MLP)构成,也可以集成更复杂的结构如 Attention、RNN 来处理序列特征。
- 输出:一个固定维度的用户向量
User Embedding。
- 输入:关于用户的一切特征。包括:
- 物品塔 (Item Tower / Candidate Tower):
- 输入:关于物品的一切特征。包括:
- 物品属性特征:类目、品牌、价格、标签、文本描述、图片等。
- 物品统计特征:历史点击率、曝光数、好评率等。
- 结构:另一个独立的深度神经网络。
- 输出:一个与用户向量维度相同的物品向量
Item Embedding。
- 输入:关于物品的一切特征。包括:
- 交互方式:在训练时,两个塔的输出——
User Embedding和Item Embedding——最终只通过一个极其简单的点积操作进行交互,并将结果送入损失函数。正是这个点积操作和后续的损失函数,作为“桥梁”和“监督者”,在反向传播时共同指导两个独立的塔去学习,迫使它们学会将用户和其喜欢的物品映射到兴趣空间中的相近位置。两个塔的参数不共享,从而可以为两种不同性质的实体分别建模。
- 用户塔 (User Tower / Query Tower):
1.3. 训练与在线服务分离思想 (Separation of Training & Serving)这是双塔模型能够被广泛应用于工业界最核心的工程优势。它巧妙地将计算量巨大的部分移到线下,从而保证了线上服务的毫秒级响应。
- 离线阶段 (Offline):训练与索引
- 模型训练:使用海量的用户历史交互数据(如点击日志),以端到端的方式联合训练用户塔和物品塔。
- 物品向量生成:模型训练完成后,丢弃用户塔。使用训练好的物品塔,对全量的、数以百万计的物品进行一次完整的计算,生成所有物品的 Embedding 向量。这是一个计算量巨大但可以接受的离线任务。
- 构建ANN索引:将所有物品的 Embedding 向量存入专门的近似最近邻 (Approximate Nearest Neighbor, ANN) 检索引擎中(如 Facebook 的 Faiss、Google 的 ScaNN)。这个过程相当于为海量的物品向量建立了一个高效的“索引目录”。
- 在线阶段 (Online):实时召回
- 当一个用户发起请求时,系统获取用户的实时特征。
- 将这些特征输入到训练好的用户塔中,进行一次前向计算,实时生成该用户的
User Embedding。这个计算非常快,因为只涉及一个样本和一个网络。 - 用这个新鲜出炉的
User Embedding,去预先构建好的 ANN 索引中进行查询,瞬间找出与它“距离最近”的 Top-K 个物品向量。 - 返回这 K 个物品的ID,完成召回。
- 离线阶段 (Offline):训练与索引
2. 模型训练的核心:样本构建 (Core of Training: Sample Construction)
这是整个模型训练环节中最重要、最能体现算法工程师“手艺”的地方。模型的理论上限可能由架构决定,但模型的实际效果,几乎完全由样本的质量决定。
2.1. 正样本的选择与定义 (Selection of Positive Samples)正样本,顾名思义,是那些能够明确或间接表明用户兴趣和满意度的行为。它是模型学习的“靶心”,模型的一切努力,都是为了能更准确地预测出这类行为的发生。
什么是正样本?—— 不仅仅是点击
一个常见的误区是认为“点击”就是唯一的正样本。在工业界,我们会根据业务目标,定义一个从弱到强的正样本信号谱系:
- 弱正样本 (Weak Positive Signals):
- 点击 (Click):这是最常用但信号也最模糊的正样本。用户可能因为标题党、好奇、误触而点击,点击后可能立刻就退出了。
- 短时观看/停留 (Short Dwell Time):比如观看了一个视频的15%,或者在一个商品详情页停留了10秒。
- 强正样本 (Strong Positive Signals):
- 长时观看/停留 (Long Dwell Time):比如一个视频被完整播放,或者用户在商品页停留了超过1分钟。这比单纯的点击更能代表用户的真实兴趣。
- 点赞 (Like) / 收藏 (Favorite) / 分享 (Share):这些是用户的显式表达,代表了高度的认可。
- 加入购物车 (Add-to-Cart):在电商场景中,这是比点击强得多、仅次于购买的信号。
- 购买 (Purchase) / 付费 (Pay):终极正样本,商业价值最高,代表了用户的最终决策。
实践中的考量
- 与业务目标对齐:选择什么样的行为做正样本,必须和你的业务目标紧密挂钩。如果你的目标是提升用户粘性,那么“长时观看”就是比“点击”更好的正样本。如果目标是提升GMV,“购买”就是最好的正样本。
- 数据清洗:真实的用户行为数据充满了噪声。我们需要通过规则或模型,排除掉“脏数据”,比如:
- 机器人的刷量行为。
- 用户的快速、连续点击(可能是误触或程序bug)。
- 点击后“秒退”(停留时间小于1-2秒)的行为,这些甚至可以被当作负样本。
- 弱正样本 (Weak Positive Signals):
2.2. 负样本的选择策略 (Negative Sampling Strategies)如果说正样本是“明”的,那么负样本就是“暗”的。用户与物品的交互记录构成了正样本,而海量的、用户从未交互过的物品则构成了潜在的负样本空间。如何从这片“汪洋”中,聪明地捞取能让模型有效学习的负样本,是样本构建中最具挑战性的部分。负样本的作用是为模型提供“边界”,告诉模型“用户不喜欢什么”或者“用户对什么无感”,从而让模型学会区分好坏。
2.2.1. 全局随机采样 (Global Random Sampling)这是最基础、最直接的负采样方法。
- 工作方式:
对于每一个正样本对<User, Item_positive>,我们从整个物品库 (Item Corpus) 中,随机地抽取一个或多个该 User 从未交互过的物品Item_negative,来构成训练三元组<User, Item_positive, Item_negative>。 - 核心目的与优势:
- 克服样本选择偏差 (Sample Selection Bias, SSB):这是它最大的优点。在很多场景下,我们能观测到的只有“曝光”数据,如果只从曝光未点击的物品中选择负样本,模型就永远不知道那些从未被曝光的物品是什么样的,视野会变得越来越窄。全局随机采样,相当于让模型**“见过世面”**,给了模型一个关于“世界”是怎样的无偏估计,强迫它去学习用户的真实、泛化的兴趣,而不是只学会在一小撮热门物品里做排序。
- 实现简单:逻辑清晰,易于实现。
- 缺点与挑战:
- 训练效率低下(Easy Negative 问题):想象一下,为了教模型“用户喜欢科幻电影”,我们随机采样到的负样本大概率是“一口锅”、“一条毛巾”或者“一本言情小说”。这些负样本太“简单”了,模型几乎毫不费力就能将它们与科幻电影区分开。模型在这些样本上学不到太多有用的信息(梯度很小),导致训练收敛速度慢,效率低下。
- 可能采到“假负例” (False Negative):这是个很严重的问题。我们随机采样的物品,有可能是用户未来会喜欢的,只是他还没发现而已。我们却错误地把它作为负样本喂给了模型,让模型去学习“用户不喜欢这个物品”,这会干扰模型的正常学习,给训练引入了错误的信号。
- 无法学习细粒度差异:由于绝大多数负样本都是“风马牛不相及”的简单负样本,模型缺乏足够的机会去学习区分那些相似物品之间的细微差别。比如,它很难学会“为什么用户喜欢《流浪地球》而不是《上海堡垒》”,因为它的“同学”大部分是“锅碗瓢盆”。
- 工作方式:
2.2.2. Batch内负采样 (In-batch Negative Sampling)
在全局随机采样的“低效”问题背景下,Batch内负采样应运而生。它以其惊人的工程效率和出色的效果,成为了当前双塔召回模型训练中最主流、最核心的负采样策略。工作原理与结构 (Mechanism & Structure)
其核心思想是**“就地取材”**,不再需要去一个庞大的全局物品库里额外捞取负样本,而是巧妙地利用了每个训练批次(batch)内已有的数据。
- 数据准备:首先,数据加载器会准备一个批次的数据,这个批次由
N个独立的正样本对<User, Positive_Item>构成。- 例如,一个
batch_size=N的批次看起来像:[(U₁, I₁), (U₂, I₂), ..., (Uₙ, Iₙ)]
- 例如,一个
- 动态构建训练实例:模型在训练时,会以批次中的每一个样本对为中心,动态地构建其对应的正负样本集。我们以第一个样本
(U₁, I₁)为例:- 正样本 (Positive):对于用户
U₁,其正样本就是I₁。 - 负样本 (Negatives):对于用户
U₁,其负样本就是这个批次中所有其他的N-1个物品{I₂, I₃, ..., Iₙ}。
- 正样本 (Positive):对于用户
- 训练目标:对于
U₁而言,模型的目标就转化成了一个多分类问题:从{I₁, I₂, I₃, ..., Iₙ}这N个物品中,准确地把I₁给识别出来。这天然地适配了我们之前讨论过的 Softmax 交叉熵损失函数。
这个过程会对批次内的每一个样本都重复一遍。当轮到处理
(U₂, I₂)时,I₂就是正样本,而{I₁, I₃, ..., Iₙ}就成了它的负样本集。- 数据准备:首先,数据加载器会准备一个批次的数据,这个批次由
优缺点与挑战 (Pros, Cons & Challenges)
- 优点 (Pros):
- 极致的训练效率:这是它最大的优势。因为它不需要任何额外的数据库查询或磁盘I/O来获取负样本,所有需要的样本(正例和负例)都已经一次性加载到内存/显存中,极大提升了数据吞吐量和训练速度。
- 隐式的困难负样本挖掘:由于一个批次内的物品都是被其他用户真实点击过的,它们通常是热门或高质量的物品。让模型去区分“我喜欢的这个好东西”和“别人喜欢的那些好东西”,本身就是一种非常有效的困难负样本训练。这强迫模型去学习更细粒度的、个性化的用户偏好,而不是简单地区分“好”与“坏”。
- 缺点与挑战 (Cons & Challenges):
- 样本选择偏差 (Sample Selection Bias, SSB):这是它最主要的理论缺陷。因为负样本全部来自于热门物品,模型在训练时永远也见不到那些冷门或长尾的物品。这导致模型的“视野”是有偏的,它只擅长在热门物品中做选择,对于挖掘长尾兴趣的能力有限。
- 假负例问题 (False Negatives):这个问题在这里尤为突出。用户
U₁可能本身也喜欢物品I₂(只是没被观测到),但在训练时I₂却被当作了U₁的负样本,这会向模型传递一个错误的、有冲突的信号。 - 对 Batch Size 高度敏感:为了让每个正样本都能有足够多、足够丰富的负样本进行对比,该方法要求 Batch Size 非常大(通常是1024, 4096甚至更大)。小的 Batch Size 会导致负样本集既少又缺乏多样性,训练效果很不稳定。这对训练硬件(如GPU显存)提出了很高的要求。
- 优点 (Pros):
2.2.3. 高级困难负样本挖掘 (Advanced Hard Negative Mining)Batch内负采样提供的是一种“隐式”的、便捷的困难负样本。但在很多场景下,我们希望更“显式”地、更有针对性地为模型提供“高质量的难题”来攻克,这就是高级困难负样本挖掘的目标。“困难负样本”的定义:那些与正样本非常相似,以至于模型在当前状态下很难将它们区分开的负样本。在向量空间中,它们通常是与用户向量或正样本物品向量距离非常近的负样本点。常见的挖掘策略:
- 基于 Embedding 空间的挖掘 (Offline):
- 这是目前工业界非常流行的一种离线挖掘方式。
- 流程:使用一个预训练好的双塔模型,先为所有物品生成 Embedding。对于一个正样本
I+,我们利用 ANN 引擎(如Faiss) 在海量的物品向量中,找出与I+的 Embedding 距离最近的 Top-K 个物品。排除掉其他正样本后,这些“近邻”就是非常高质量的困难负样本,因为它们在语义上与正样本高度相似。
- 基于模型预测的挖掘 (Online):
- 在训练的每一步,对于一个
<U, I+>对,我们可以额外拿U的向量去和一个实时的、包含大量候选物品的向量索引进行查询,找出除了I+之外,得分最高的那些物品。这些物品就是模型当前“认知”中最容易混淆的负样本。这种方式更加动态,但实现也更复杂。
- 在训练的每一步,对于一个
- 基于业务规则/知识图谱的挖掘:
- 利用业务先验知识来构造困难负样本。
- 例子:
- 同类目不同品牌:用户点击了“华为手机”,那么“小米手机”、“苹果手机”就是它的困难负样本。
- 同session内曝光未点击:用户在一次会话中,浏览了A、B、C三个物品,但最终只点击了A。那么B和C对于A来说,就是非常好的困难负样本。
- 从下游排序模型中挖掘(“蒸馏”思想):
- 这是一个非常强大的策略。排序模型(精排)通常比召回模型强大得多。那些能够通过召回和粗排,但最终在精排阶段被打了低分的物品,是“金牌”困难负样本。
- 将这些样本捞回来给召回模型做负样本,相当于在告诉召回模型:“你觉得这个东西还不错,但更聪明的精排模型认为它不行,你要好好学学为什么不行。” 这能极大地帮助召回模型理解更复杂的排序逻辑。
使用困难负样本的挑战:挖掘的“度”很重要。如果负样本“太难”(甚至就是假负例),可能会让模型训练过程不稳定,甚至不收敛。因此,实践中往往是将困难负样本与**简单负样本(如全局随机采样)**按照一定比例混合起来进行训练,达到一个平衡。
- 基于 Embedding 空间的挖掘 (Offline):
3. 训练范式与损失函数 (Training Paradigms & Loss Functions - LTR)
3.1. Pointwise (点对) - BCELossPointwise 是最直观、最简单的训练范式。它将复杂的“排序”问题,彻底简化为了一个基础的“二分类”问题。它在看待数据时,是“一个一个点”地看,完全独立,不考虑样本之间的任何关联。
- 处理单元:一个独立的
<User, Item>对。 - 任务转化:对于每一个
<User, Item>对,模型需要回答一个问题:“这位用户会点击这个物品吗?” (Yes/No)。 - 标签 (Label):
y=1(代表正样本,如点击) 或y=0(代表负样本,如曝光未点击)。 - 模型目标:模型需要输出一个概率值
p(介于0和1之间),这个p代表了模型预测该用户会点击该物品的概率。Pointwise 的目标就是让预测概率p无限逼近真实标签y。
损失函数:BCELoss (Binary Cross-Entropy Loss / 二元交叉熵损失)
为了达成上述目标,Pointwise 范式最常使用的损失函数就是 BCELoss。
- 公式:

- 工作原理详解:
- 当处理正样本时 (
y_i=1):- 公式简化为
L = -log(p_i)。 p_i是模型对这个正样本的预测概率。为了让损失L最小,log(p_i)就要最大,这意味着p_i必须无限趋近于 1。- 效果:强迫模型对正样本输出高分。
- 公式简化为
- 当处理负样本时 (
y_i=0):- 公式简化为
L = -log(1-p_i)。 - 为了让损失
L最小,log(1-p_i)就要最大,这意味着1-p_i必须无限趋近于 1,也就是p_i必须无限趋近于 0。 - 效果:强迫模型对负样本输出低分。
- 公式简化为
- 当处理正样本时 (
- 总结与评价:
- Pointwise 的优点是简单、易于理解、并行性好。
- 但它的核心缺陷在于,它没有直接对“排序”这个目标进行优化。它只关心分数预测的绝对准确性,而不在乎物品之间的相对顺序。一个模型的预测可能是
{正:0.6, 负:0.5},另一个模型的预测是{正:0.9, 负:0.1},对于BCELoss来说,两者的损失可能差不多,但后者的排序效果显然要好得多。
- 处理单元:一个独立的
3.2. Pairwise (对对) - BPR Loss, Triplet LossPairwise 范式是对 Pointwise 的一次重大升级,它更贴近“排序”的本质。它不再孤立地看待每个物品,而是将重点放在**“比较”**上。它认为,一个好的推荐模型,关键在于能准确判断出一对物品中,哪一个更值得被推荐。
- 处理单元:一个三元组
<User, Positive_Item, Negative_Item>。 - 任务转化:对于一个用户,给定一个他喜欢的物品
I+和一个他不喜欢的物品I-,模型需要回答:“I+是否比I-更值得推荐?”。 - 模型目标:让模型为
I+打出的分数Score_pos,高于为I-打出的分数Score_neg。即Score_pos > Score_neg。
损失函数1:BPR Loss (Bayesian Personalized Ranking Loss)
BPR Loss 是 Pairwise 范式中最具代表性的损失函数之一。
公式:

工作原理详解:
- 计算分差:首先计算正样本得分与负样本得分的差值
x = Score_{pos} - Score_{neg}。我们的目标是让这个差值x越大越好。 - Sigmoid 激活:将差值
x送入 Sigmoid 函数σ(x)。Sigmoid 函数会将任何实数映射到(0, 1)区间。在这里,σ(x)可以被巧妙地理解为**“模型认为正样本排在负样本前面的概率”**。x越大,σ(x)就越接近1。 - 负对数似然:最后,对这个概率取
log。这是在应用最大似然估计的原理。最小化log(概率),就等价于最大化这个概率。
- 效果:整个优化过程,就是在强迫模型去最大化“正样本排在负样本前面”的概率。
- 计算分差:首先计算正样本得分与负样本得分的差值
损失函数2:Triplet Loss (三元组损失 / Hinge Loss)
Triplet Loss 是另一种非常流行的 Pairwise 损失,它比 BPR 的要求更“严格”。
公式:

工作原理详解:
- 引入安全边界 (Margin):
m是一个预先设定的超参数,称为“边界”或“间隔”。 - 更严格的目标:Triplet Loss 不仅要求
Score_pos > Score_neg,它要求Score_pos必须比Score_neg至少大m,即Score_pos - Score_neg > m。 - Hinge 机制:
max(0, ...)的作用在于:- 如果
Score_pos - Score_neg已经大于m了,说明这个“PK对”已经被模型轻松、正确地分开了,那么m - (Score_pos - Score_neg)就是一个负数,max(0, ...)的结果就是 0。这意味着对于简单的、区分明显的样本对,不产生任何损失。 - 只有当这个边界条件不被满足时 (
Score_pos - Score_neg < m),才会产生一个正的损失值。
- 如果
- 效果:这种机制强迫模型将更多的精力集中在那些**“模棱两可”的、难以区分的困难样本对**上,努力将它们的得分差距拉开至少
m,从而使得学出来的向量空间分布更合理,边界更清晰。
- 引入安全边界 (Margin):
- 处理单元:一个三元组
3.3. Listwise (列表对) - Softmax Cross-Entropy LossListwise 是三种 LTR 范式中理论上最先进、最贴近真实排序目标的思想。Pointwise 只看“点”,Pairwise 比较“线”(一对点),而 Listwise 则着眼于整个“面”——它将一个完整的候选列表视为一个整体来进行优化。
- 处理单元:一个用户的“学习实例”,由
<User, Positive_Item, {A_Set_of_Negative_Items}>构成。 - 任务转化:Listwise 将排序问题巧妙地转化成了一个**“在候选列表中,找出哪个是正确答案”的多分类问题**。
- 模型目标:对于给定的候选列表,模型需要为真正的那个正样本,分配到最高的概率。
工作原理与损失函数

图示完美地展示了其工作流程:
计算原始分 (Logits):对于一个用户,模型首先计算出他与列表中每一个物品(1个正样本 + N个负样本)的相似度得分。我们得到一个分数向量
[s+, s₁⁻, s₂⁻, ..., sₙ⁻]。Softmax 归一化:将这个分数向量送入 Softmax 函数。
P(itemi)=∑j∈Listexp(sj)exp(si)
- 作用:Softmax 会将原始的、任意大小的分数,转换成一个概率分布。所有物品的概率值都在 (0, 1) 之间,且它们的总和为1。
P(item+)就代表了模型认为“在这个列表中,正样本 item+ 是正确答案”的预测概率。
- 作用:Softmax 会将原始的、任意大小的分数,转换成一个概率分布。所有物品的概率值都在 (0, 1) 之间,且它们的总和为1。
交叉熵损失 (Cross-Entropy Loss):
真实标签 (Ground Truth):在这个多分类问题中,真实的标签是一个 one-hot 向量,只有正样本对应的位置是1,其他所有负样本的位置都是0。即
y = [1, 0, 0, ..., 0]。损失函数:计算模型的预测概率分布和真实的 one-hot 标签分布之间的交叉熵。由于真实标签中只有正样本位置是1,公式可以简化为:
LListwise=−log(P(item+))
优化目标:最小化这个损失,就等同于最大化正样本的预测概率
P(item+)。为了让正样本的概率变大,模型必须同时做到两件事:提升正样本的分数s+,以及压低所有负样本的分数s⁻。
- 总结与评价:
- Listwise 通过一次性考虑整个列表,能够更好地学习到物品之间的相互关系,其优化目标也与最终的排序评估指标(如NDCG)更接近。
- 它天然地适用于 Batch 内负采样的场景,因为 Batch 内负采样本身就为每个正样本提供了一个“列表”来进行对比。
- 处理单元:一个用户的“学习实例”,由
3.4. 训练高级技巧- 向量归一化 (L2 Normalization)
- 是什么:在计算完用户或物品的原始 Embedding 向量后,通过一个数学操作,使其 L2 范数(可以理解为向量的“长度”)等于1。这相当于把所有向量都投影到一个高维的“单位球”的表面上。
- 为什么至关重要:
- 稳定训练,防止模型“作弊”:这是最核心的原因。如果没有归一化,模型为了让正样本的点积
u·v变大,可能会走一条“捷径”:不是努力地让u和v的方向变得更接近,而是无脑地把u和v的长度(模长)变得无限大。这是一种无效的学习。归一化后,所有向量长度都为1,模型唯一的优化路径就只剩下调整向量的方向,这才能真正学到语义上的相似性。 - 让点积等价于余弦相似度:对于长度为1的单位向量,
u·v = |u||v|cos(θ) = cos(θ)。这让我们的优化目标变得非常明确和纯粹:就是最小化用户和正样本向量之间的夹角。 - 提升数值稳定性:防止向量中的值在训练中爆炸或消失,导致梯度问题。
- 稳定训练,防止模型“作弊”:这是最核心的原因。如果没有归一化,模型为了让正样本的点积
- 温度系数 (Temperature τ)
- 是什么:一个标量超参数
τ,在将分数(logits)送入 Softmax 函数之前,先用它来对分数进行缩放:Softmax(scores / τ)。 - 作用:控制模型预测的“锐利度”
- 低温 (τ < 1, e.g., 0.1):
scores的差距会被放大,Softmax 的输出会变得非常**“尖锐 (Peaky)”。模型会以极高的置信度(比如99%的概率)指向它认为最可能的那个选项。这会强迫模型更关注那些最困难的负样本**,努力将它们与正样本彻底分开。 - 高温 (τ > 1, e.g., 2.0):
scores的差距会被缩小,Softmax 的输出会变得非常**“平滑 (Smooth)”**。概率会更均匀地分布在多个选项上。这会让模型变得不那么“自信”,可以防止它在有噪声的标签上过拟合。
- 低温 (τ < 1, e.g., 0.1):
- 与归一化的关系:当使用了 L2 归一化后,logits 的值被限制在
[-1, 1]的小区间内。此时,如果不使用温度系数(相当于τ=1),不同 logits 之间的差距会很小,导致 Softmax 输出的概率区分度不大,损失函数的梯度信号微弱,模型难以学习。因此,归一化之后,通常必须配合一个较小的温度系数τ来“放大”信号,让模型有效训练。
- 是什么:一个标量超参数
- 采样修正损失 (Sampling-Corrected Loss): NCE, Sampled Softmax
- 动机:我们之前讨论过,无论是全局随机采样还是 Batch 内负采样,我们构造的负样本分布,都和数据真实的全局分布存在偏差 (Bias)。采样修正损失就是为了在数学上校正这种偏差。
- NCE (Noise Contrastive Estimation / 噪声对比估计):
- 它将问题从“预测是哪个物品”转化为了“判断一个样本是来自真实数据还是噪声”。
- 它的损失函数中,会显式地减去
log(Q(item))这一项,其中Q(item)是这个物品在我们的负采样(噪声)分布中被抽到的概率。这个修正项的作用是,对于那些很容易被当做负样本采到的热门物品,对其进行“惩罚”,从而得到一个更无偏的、更能反映真实喜好的分数。
- Sampled Softmax:
- 当物品库极其巨大时(如数百万),计算标准 Softmax 的分母(需要对所有物品求和)是不可能的。
- Sampled Softmax 通过只在**“一个正样本 + 少量随机采样的负样本”**这个小集合上计算 Softmax 来近似全局 Softmax。
- 为了保证这种近似的无偏性,它的损失函数同样会利用负样本的采样概率
Q(item)来对结果进行校正。
- 向量归一化 (L2 Normalization)
4. 高级召回模型架构 (Advanced Recall Model Architectures)[拓展]
4.1. 基于图的召回 (Graph-based): DeepWalk传统的协同过滤或双塔模型,往往关注用户和物品的直接交互,但可能会忽略物品之间更深层次的、间接的关联(比如 A-B-C,A和C之间的关系)。图(Graph)结构是描述这种复杂网络关系的天然工具,而 DeepWalk 则是将图结构与深度学习结合的开创性工作。核心思想:将所有用户的行为历史聚合成一张巨大的物品关系图,然后在这张图上“漫步”,生成物品序列,最后用自然语言处理(NLP)中的 Word2Vec 模型来学习图中每个物品的向量表示(Embedding)。
建图 -> 随机游走 -> Word2Vec训练工作流程三部曲
第一步:建图 (Graph Construction)
- 节点 (Nodes):图中的每一个节点,就是一个独立的物品 (Item)。
- 边 (Edges):用户的一次连续行为,构成了物品节点之间的有向边。
- 过程:我们收集大量用户的行为序列,比如用户1的行为是
物品A -> 物品B -> 物品C,用户2的行为是物品D -> 物品B -> 物品E。 - 聚合:我们将这些序列中的相邻关系全部投影到一张图上。
A->B就在节点A和B之间画一条边,B->C就在B和C之间画一条边,D->B就在D和B之间画一条边……最终,所有用户的行为汇集成一张包含了所有物品及其流转关系的复杂网络。边的权重可以由转换发生的频率来隐式定义。
- 过程:我们收集大量用户的行为序列,比如用户1的行为是
- 意义:这张图浓缩了所有用户的“群体智慧”,物品之间的连接强度和路径,反映了它们在真实世界中的关联性。
第二步:随机游走 (Random Walk)
- 目的:我们手头最强大的序列处理工具是 Word2Vec,但它只能处理线性的句子,不认识图这种非线性结构。随机游走的任务,就是把图的结构信息,“翻译”成 Word2Vec 能读懂的线性序列格式。
- 过程:
- 在图上随机选择一个节点作为起点。
- 从当前节点,等概率地随机跳转到它的一个邻居节点。
- 不断重复上一步,直到走满一个预设的长度(比如80步)。
- 这样走出的一条节点序列,如
[Item_A, Item_B, Item_D, Item_F, ...],就被我们视作一个**“句子”**。
- 效果:通过在图上进行海量的随机游走,我们就能得到数百万条这样的“物品句子”。由于游走被图的结构所约束,那些在图中连接紧密的物品(比如同一个“社区”内的物品),会更频繁地在这些“句子”中共同出现。
第三步:Word2Vec 训练
- 类比:这是最关键的认知转换。
- 图中的每个物品节点 <==> 语言中的每个单词。
- 随机游走产生的物品序列 <==> 语言中的一个句子。
- 模型 (Skip-gram):我们使用 Word2Vec 中的 Skip-gram 模型来训练。它的目标是**“根据中心词预测上下文”**。
- 应用:我们将物品“句子”喂给 Skip-gram 模型。模型在学习时,会不断地尝试根据序列中的一个中心物品(如 Item_B),去预测它前后窗口内的其他物品(如 Item_A, Item_D)。
- 结果:为了完成这个预测任务,模型必须为每个物品学习一个向量 Embedding。那些经常在相似上下文(即相似的邻域结构)中出现的物品,最终会被赋予相似的向量表示。至此,我们就成功地将图的结构信息,编码进了每个物品的 Embedding 之中。
4.2. 多兴趣召回 (Multi-Interest): MIND (Capsule Network)核心痛点:标准双塔模型最大的局限性,在于它试图将一个用户的所有兴趣——无论是看电影、买菜还是学编程——都强行压缩到一个单一的向量中。这就像把一个人的所有性格特点平均一下,得到一个“不好不坏”的平庸结论,造成了巨大的信息损失。
核心思想:一个用户有多个兴趣,我们就应该为他提取出多个兴趣向量。MIND 模型巧妙地借鉴了胶囊网络中的**“动态路由 (Dynamic Routing)”**机制,来自动地将用户的行为序列聚类成多个兴趣簇,并为每个簇生成一个代表性的兴趣向量。
工作流程:
第一步:动态路由与多兴趣提取
- 目标:输入一个用户的历史行为物品序列(的Embedding矩阵),输出 K 个代表不同兴趣的向量(称为“兴趣胶囊”)。
- 比喻:智能分拣系统
- 想象一个传送带上放着用户过去点击过的50个物品(的Embedding),我们有 K 个篮子(兴趣胶囊)。我们希望能自动地把“电子产品”都分到1号篮,“服饰鞋帽”都分到2号篮……
- 迭代式的“投票-聚类”过程 (Routing by Agreement):
- 初始化:随机生成 K 个“兴趣篮子”的初始位置。
- 循环迭代 (通常3次):
- a. 投票 (Agreement):传送带上的每一个物品,都会看一下当前的 K 个篮子,然后判断自己和哪个篮子的“气质”最像(向量点积最大)。
- b. 分配权重:根据相似度,这个物品会决定将自己“归属于”每个篮子的权重(通过Softmax计算)。比如,一个“iPhone”可能会以90%的权重归属于“数码篮”,10%的权重归属于“生活篮”。
- c. 更新篮子位置:每一个篮子收集所有物品分配给它的权重,然后通过对所有物品向量进行加权求和,来更新自己的位置。这个新位置更能代表所有“支持者”(高权重物品)的中心。
- 收敛:经过几轮迭代,K 个篮子的位置会稳定下来,每一个篮子都准确地找到了它所代表的那个“兴趣簇”的中心。这 K 个最终的篮子向量,就是我们提取出的用户多兴趣向量。
第二步:目标注意力机制 (Target Attention)
- 问题:现在,我们有了用户的 K 个兴趣向量(比如“数码兴趣”和“服饰兴趣”),当要预测用户是否会点击一个目标商品(比如一个“鼠标”)时,我们应该用哪个兴趣向量呢?
- 解决方案:让目标物品自己来决定!
- 过程:
- 拿出“鼠标”的 Embedding。
- 让“鼠标”的 Embedding,分别去和用户的 K 个兴趣向量计算相似度。
- “鼠标”会发现,它和“数码兴趣”向量的相似度极高,和“服饰兴趣”向量的相似度极低。
- 将这些相似度得分通过 Softmax 转换成一组注意力权重。此时,“数码兴趣”的权重会非常高(如0.98),其他兴趣的权重会非常低。
- 用这组权重,对 K 个兴趣向量进行加权求和。
- 过程:
- 结果:最终得到的用户向量,几乎就等于他原始的“数码兴趣”向量。这个最终向量是为当前目标物品“量身定制”的,它动态地聚焦于用户最相关的那个兴趣侧面,极大地提升了预测的精准性。
4.3. 生成式召回 (Generative): Deep Retrieval (Item-to-Path)[拓展]核心思想:从“匹配”到“生成”
- 传统判别式模型 (如双塔):它的核心是回答一个问题:“给定的
<User, Item>对,它们的匹配分数是多少?” 它是在判断一个已存在的对。 - 生成式召回 (DR):它的核心是回答一个问题:“对于这个
User,他/她感兴趣的**‘兴趣篮子’(或称为‘路径’,Path)是哪几个?” 然后再看哪些物品属于这些篮子。它是在为用户生成**一个兴趣表示。
你可以把这种方法想象成一个**“兴趣篮子”**模型。
- 定义篮子:我们不直接学习物品本身,而是在系统中预先定义好几千个全局的“兴趣篮子”(在论文里称为“路径”Path)。比如:
[科幻电影篮],[周末烘焙篮],[篮球装备篮]等等。 - 模型任务:模型的任务有两个:
- 对用户:预测这个用户最喜欢哪几个“篮子”。
- 对物品:决定每个物品应该被放入哪个“篮子”。
- 召回方式:当一个用户来访时,模型先预测出他最感兴趣的几个篮子(比如“科幻电影篮”和“篮球装备篮”),然后直接把这两个篮子里的所有物品都作为召回结果推荐给他。
这种“先生成兴趣篮子,再取出物品”的方式,就是所谓的生成式召回。
遇到的最大难题:“路径坍缩”
这个想法虽好,但在实际训练中会遇到一个致命问题——路径坍缩 (Path Collapse)。
- 简单比喻:“所有鸡蛋都放进了一个篮子”。
- 问题描述:模型在训练时会“偷懒”,它会发现一个降低损失最快的捷径:把所有物品(无论科幻电影还是篮球鞋)都拼命地塞进同一个、最热门的篮子里。
- 后果:最终,几千个篮子里只有一个被有效使用,其他都空了。模型完全丧失了区分用户多兴趣的能力,这个精巧的设计也就失败了。
聪明的解决方案:“两步走”的EM算法
为了解决“路径坍缩”这个“鸡生蛋还是蛋生鸡”的难题,研究者们采用了一种叫 EM 的算法,把复杂的训练过程拆成了交替进行的两步。
第一步:E-Step (分篮子 - Path Assignment)
- 目标:打破“所有鸡蛋放一个篮子”的局面。
- 做法:在这一步,我们先“冻结”住神经网络,不让它动。然后,对于一个用户的历史物品,我们用一个聪明的规划算法(贪心算法),强制性地为他选出多个最合适的篮子。
- 通俗理解:我们不再听凭模型“偷懒”,而是像一个“整理师”,手动帮用户把他的物品(《三体》、篮球、烤箱)合理地分配到不同的篮子里(“科幻篮”、“运动篮”、“生活篮”)。这一步保证了分配结果是多样化的。
第二步:M-Step (学分配 - Network Update)
- 目标:让模型学会我们刚才聪明的分配方法。
- 做法:现在,我们“冻结”住上一步分配好的“篮子方案”,把它当作**“标准答案”**。然后,我们解冻神经网络,开始训练它。
- 通俗理解:我们指着分配好的篮子告诉模型:“看,对于这个用户,这就是他兴趣的正确答案(他喜欢这3个篮子),你要好好学习,下次要能准确地预测出来!”
通过**“先手动分好篮子”** -> “再让模型学习这个分配结果” -> “学好后再更智能地分篮子”……这样来回交替进行,模型就被引导着学会了如何利用多个篮子来刻画用户的多元兴趣,从而完美地解决了“路径坍缩”的问题。
- 传统判别式模型 (如双塔):它的核心是回答一个问题:“给定的
4.4. 解决特定问题的模型演化多目标学习: MMoE (与大模型MoE的对比)要解决的问题:当“鱼”和“熊掌”都想要
在现代推荐系统中,业务目标往往是多元的。我们不仅希望用户点击(提升CTR),还希望他们长时间观看(提升Duration)、点赞/分享(提升Interaction),甚至购买(提升CVR)。这些目标之间有时甚至是相互冲突的(比如,标题党内容CTR高,但观看时长短)。如果只用一个模型优化一个目标,必然会顾此失彼。
解决方案:MMoE (Multi-gate Mixture-of-Experts)
MMoE 是一种非常优雅且高效的多任务学习框架,它的核心思想是**“共享专家,任务独有门控”**。
- 架构组成:
- 多个专家网络 (Experts):模型底层设置了多个共享的、结构相同但参数不共享的子网络(即“专家”)。每个专家都可以从输入特征中学习到一种特定的、有侧重的知识表示。你可以把它们想象成一个顾问团里的“财务专家”、“市场专家”、“技术专家”等。
- 多个门控网络 (Gating Networks):这是MMoE的精髓。它为每一个学习任务都配备一个专属的“门控网络”。这个门控网络也是一个小型神经网络,它的作用是根据输入特征,智能地决定应该以多大的“权重”去听取每一位专家的意见。
- 工作流程:
- 输入特征同时送入所有的专家网络,得到多份并行的“专家意见”。
- 对于任务A(如预测点击),其专属的门控网络A会输出一组权重,比如
{专家1: 0.7, 专家2: 0.1, 专家3: 0.2}。然后用这组权重对所有专家的意见进行加权求和,得到专门用于预测点击的最终表示。 - 同时,对于任务B(如预测时长),其专属的门控网络B可能会输出另一组完全不同的权重,比如
{专家1: 0.2, 专家2: 0.6, 专家3: 0.2},然后用这组权重去融合专家的意见,得到专门用于预测时长的最终表示。
- 与大模型 MoE 的对比:
- 核心目标不同:推荐中的 MMoE 是为了有效进行多任务学习,解决任务冲突;大模型中的 MoE 是为了用可控的计算成本极大化模型容量。
- 工作方式不同:MMoE 中,所有专家都参与计算,每个任务只是对它们的意见进行不同的**“加权融合”。而 MoE 中,对于一个输入,路由器会选择性地激活Top-K个(通常是1或2个)专家,是一种“稀疏激活”**,绝大部分专家在“休息”。
- 架构组成:
信息瓶颈问题: SeNet, 并行多塔要解决的问题:双塔模型的“致命弱点”
标准双塔模型最大的结构缺陷在于,两个塔辛辛苦苦将丰富的特征信息编码成高维向量后,最终却只通过一个极其简单的**“点积 (Dot Product)”操作来决定生死。这个点积操作是一个巨大的信息瓶颈**,它无法捕捉特征之间复杂的、高阶的交互关系,损失了大量有价值的信息。
解决方案1:SeNet (Squeeze-and-Excitation Network) - “为特征划重点”
- 核心思想:在进行点积之前,先用一个“注意力”模块,动态地学习 Embedding 中每个维度的重要性,然后进行加权,突出重要信息,压制噪声信息。
- 工作流程:
- Squeeze (压缩):将原始 Embedding 的全局信息压缩成一个简短的概要。
- Excitation (激励):基于这个概要,通过一个微型网络,为原始 Embedding 的每一维都生成一个
0~1之间的重要性权重。 - Reweight (重赋权):将原始 Embedding 与这个权重向量按位相乘,得到一个“划过重点”的、信息量更精纯的新 Embedding。
- 效果:让简单的点积操作,也能作用在经过“智能预处理”的、信息含量更高的向量上。
解决方案2:并行多塔 (Parallel Multi-Towers) - “集思广益”
- 核心思想:既然一种交互方式有局限,那就让多种不同的、各有所长的交互模块并行工作,最后将它们的结果综合起来。
- 架构:将原始的用户和物品 Embedding,同时输入到多个并行的“交互通道”中,例如:
- MLP 通道:学习隐式的、高阶的非线性特征交互。
- DCN (Deep & Cross Network) 通道:擅长学习显式的、有限阶的特征交叉。
- FM / CIN (Factorization Machine / Compressed Interaction Network) 通道:擅长学习显式的二阶特征交叉。
- 融合:将所有通道的输出结果进行拼接或加权求和,得到一个综合了各种交互模式的、更鲁棒的最终匹配分数。
物品冷启动问题: SSL双塔要解决的问题:新物品的“无人问津”
一个新上架的物品,没有任何用户的交互记录(点击、购买等)。传统的、依赖用户行为的召回模型(如协同过滤、标准双塔),完全无法为它生成一个有意义的 Embedding,导致它永无出头之日。这就是“物品冷启动”问题。
解决方案:SSL双塔 - “让物品自己教自己”
- 核心思想:既然没有用户行为数据,我们就想办法只利用物品自身的属性特征(如标题、类目、品牌、图片等)来进行学习。通过自监督学习 (SSL),让物品塔在没有用户的情况下,也能完成“预训练”。
- 工作流程:
- 构造正样本对:这是SSL的关键。我们对一个物品的原始特征进行两次独立的数据增强 (Data Augmentation),比如随机遮盖掉一些词(Masking)或随机丢弃一些特征(Dropout),得到两个“面目全非”但“同根同源”的增强版特征。这两个增强版就被视作一个正样本对。
- 自监督训练:
- 将这两个增强版的特征,分别送入同一个物品塔,得到两个 Embedding
emb_aug1和emb_aug2。 - 采用对比学习损失 (InfoNCE Loss):这个损失函数的目标是,在向量空间中,拉近
emb_aug1和emb_aug2的距离,同时推远它们与同一个 batch 中其他物品的增强向量的距离。
- 将这两个增强版的特征,分别送入同一个物品塔,得到两个 Embedding
- 混合训练:最终,模型的总损失由两部分组成:一部分是来自用户-物品交互的监督学习主损失;另一部分就是这个自监督SSL损失。
- 效果:通过SSL部分的训练,物品塔学会了从物品自身属性中理解其内在的语义。当一个新物品到来时,即使没有任何用户行为,物品塔也能根据它的标题、类目等信息,直接生成一个高质量、有意义的 Embedding,使其能够被公平地推荐给可能对它感兴趣的用户,从而完美地解决了冷启动问题。
5. 经典与其他召回策略 (Classic & Other Recall Strategies)
5.1. 协同过滤 (Collaborative Filtering)协同过滤(CF)是推荐系统历史上最重要、应用最广泛的算法范式之一。它的魅力在于,它完全不需要理解物品本身的内容(比如电影的情节或商品的功能),仅通过分析用户与物品之间的交互行为数据(“用户行为矩阵”),就能给出相当精准的推荐。
其核心哲学是“物以类聚,人以群分”,即利用群体智慧来进行推荐。它主要分为两大流派:基于用户的协同过滤(UserCF)和基于物品的协同过滤(ItemCF)。
UserCF, ItemCFUserCF (User-Based Collaborative Filtering)
- 核心思想:“向与你品味相似的朋友寻求推荐”
- UserCF 的逻辑非常符合人类社会的社交推荐行为。它分为两步:
- 找到与你(目标用户)的兴趣品味最相似的一群用户。
- 将这群“品味相投”的朋友们喜欢过,而你还未接触过的物品,推荐给你。
- UserCF 的逻辑非常符合人类社会的社交推荐行为。它分为两步:
- 工作流程详解:
- 计算用户相似度:这是 UserCF 的核心与计算瓶颈。系统会遍历所有用户,计算目标用户与每一个其他用户之间的相似度。常用的相似度度量包括:
- Jaccard 相似系数:计算两个用户交互过的物品集合的交集与并集的比例。
- 余弦相似度:将每个用户对物品的偏好(如评分或点击)视为一个向量,计算向量之间的夹角。
- 生成推荐列表:
- 找出与目标用户最相似的 Top-K 个用户。
- 汇总这 K 个用户喜欢过的所有物品,并根据“推荐强度”进行排序(例如,一个物品被越多的相似用户喜欢,其推荐强度就越高)。
- 过滤掉目标用户已经交互过的物品后,得到最终的推荐列表。
- 计算用户相似度:这是 UserCF 的核心与计算瓶颈。系统会遍历所有用户,计算目标用户与每一个其他用户之间的相似度。常用的相似度度量包括:
- 优点与挑战:
- 优点:能够发现一些用户潜在的、跨领域的兴趣,推荐结果具有新颖性和惊喜性 (Serendipity)。比如,通过相似用户,一个科幻迷可能会被推荐一本他从未接触过的硬核历史小说。
- 挑战:
- 可扩展性差 (Poor Scalability):在用户量巨大(千万、上亿级别)的现代平台,计算所有用户两两之间的相似度,其计算量是平方级别的,几乎是不可接受的。
- 数据稀疏性 (Sparsity):用户交互过的物品相对于整个物品库来说极其稀少,导致很难找到有足够多共同交互物品的“相似用户”。
- 时效性差:用户的兴趣是会变化的,但用户相似度矩阵的计算成本极高,无法频繁更新。
ItemCF (Item-Based Collaborative Filtering)
为了解决 UserCF 的可扩展性等问题,ItemCF 应运而生,并迅速成为业界主流。
- 核心思想:“根据你喜欢的,推荐与它相似的”
- ItemCF 的逻辑更关注物品之间的关联性。我们日常在电商网站看到的“购买此商品的顾客也购买了…”功能,就是 ItemCF 思想最经典的体现。
- 它的工作流程同样分为两步:
- (离线)计算出整个平台中,物品与物品之间的相似度。
- (在线)根据你历史上喜欢过的物品,找到与它们最相似的一批物品,推荐给你。
- 工作流程详解:
- (离线)构建物品相似度矩阵:这是 ItemCF 的核心。系统会遍历所有用户的行为历史,计算物品两两之间的相似度。最基础的计算方法是:
Similarity(i, j) = |U(i) ∩ U(j)| / sqrt(|U(i)| * |U(j)|),其中U(i)是喜欢物品i的用户集合。这个计算量巨大,但由于物品之间的关系相对稳定,可以离线计算并定期更新。 - (在线)生成推荐列表:
- 获取用户的历史正反馈物品列表
L。 - 对于
L中的每一个物品i,从预先计算好的相似度矩阵中,找出与i最相似的 Top-K 个物品。 - 将所有这些找出的相似物品进行汇总、加权(比如,用物品相似度分乘以用户对
i的喜爱程度)、排序、去重后,得到最终的推荐列表。
- 获取用户的历史正反馈物品列表
- (离线)构建物品相似度矩阵:这是 ItemCF 的核心。系统会遍历所有用户的行为历史,计算物品两两之间的相似度。最基础的计算方法是:
- 优点与挑战:
- 优点:
- 可扩展性好:物品数量通常比用户数量少且增长慢,物品相似度矩阵可以离线计算,在线推荐速度极快。
- 推荐更稳定且可解释:推荐结果往往与用户的近期行为高度相关,更容易被用户理解和接受(“因为你喜欢A,所以推荐B”)。
- 挑战:
- 推荐多样性与新颖性不足:由于推荐结果高度依赖用户已有行为,很难跳出用户当前的兴趣圈,挖掘新的兴趣领域。
- 热门偏见 (Popularity Bias):这是 ItemCF 最大的缺陷。两个本身不相关的热门物品(比如《新华字典》和“可口可乐”),很可能因为都被大量用户购买过,而被算法错误地认为“非常相似”。
- 优点:
- 核心思想:“向与你品味相似的朋友寻求推荐”
Swing 算法[拓展]Swing 算法:ItemCF 的高级进化版
Swing 算法的提出,就是为了精准打击 ItemCF 的热门偏见问题。
- 核心思想:两个物品
i和j的相似度,不应该由那些“大众品味”的用户决定,而应该由那些“小众、专一”的用户来定义。 - 一个直观的例子:
- 场景1:用户A只买了“键盘”和“鼠标”,用户B也只买了“键盘”和“鼠标”。这两个用户的行为,极强地证明了“键盘”和“鼠标”是高度相关的。
- 场景2:用户C是个“数码达人”,买了100件商品,其中包括“键盘”和“鼠标”;用户D也是“数码达人”,也买了这100件商品。这两个用户的行为,只能微弱地证明“键盘”和“鼠标”相关,因为它们可能只是“数码产品”这个大筐子里的两个普通成员。
- Swing 的工作原理:
- 它考察的是所有同时喜欢了物品
i和j的用户对<u, v>。 - 它认为,如果用户
u和v的交集很小(像场景1中的A和B),那么他们共同喜欢i和j的行为,就对sim(i, j)的贡献非常大。 - 反之,如果用户
u和v的交集很大(像场景2中的C和D),那么他们共同喜欢i和j的行为,对sim(i, j)的贡献就非常小。 - 公式体现:
sim(i, j) = Σ [1 / (α + |I(u) ∩ I(v)|)],其中I(u)是用户u喜欢的物品集合。分母上的交集项,完美地实现了**“交集越大,贡献越小”**这一核心思想。
- 它考察的是所有同时喜欢了物品
- 效果:Swing 能够有效地滤除热门物品带来的噪声,挖掘出物品之间更真实、更鲁棒的关联关系,是目前工业界应用非常广泛且有效的 ItemCF 升级方案。
- 核心思想:两个物品
5.2. 序列建模 (Sequential Modeling): SDM (长短期兴趣)**核心动机:用户的兴趣是“流动的河”。**我们之前讨论的协同过滤、图模型等方法,很多时候是将用户的历史行为看作一个静态的“集合”,忽略了一个至关重要的维度——时间。
用户的兴趣并非一成不变,而是像一条流动的河。你刚刚点击过的几个物品,远比你一年前喜欢的东西,更能代表你当下的意图。序列建模的核心,就是为了捕捉用户兴趣的动态性、时序性,从而做出更即时、更精准的推荐。
SDM 模型是阿里在2019年提出的,是序列化召回领域的经典之作。它的核心创见在于,它认为一个用户的最终兴趣,是其长期稳定的泛在兴趣和短期即时的会话兴趣共同作用的结果,并设计了一套精巧的结构来分别建模并融合它们。
SDM 的核心架构:长短期兴趣的“双轨制”
1. 长期兴趣建模 (Long-Term Interest Modeling)
- 目标:刻画用户稳定、持久的“核心品味”或“用户画像”。
- 输入:用户的较长跨度的历史行为序列(比如过去一个月的几百次点击)。
- 建模方式:
- 由于长期兴趣不强调严格的顺序,而在于“用户到底喜欢过哪些东西”的整体面貌,SDM 直接将这些物品的 Embedding 进行处理。
- 最简单的方式是直接平均池化 (Average Pooling)。
- 更高级的方式是如
image_4b0f4d.png中提到的 Att Net (Attention Network),即通过一个注意力网络,为用户的每一个长期行为物品赋予一个权重,然后进行加权求和。这可以让模型自动识别出哪些历史行为最能代表用户的核心兴趣。
- 输出:一个代表用户长期、泛在兴趣的向量
U_long。
2. 短期兴趣建模 (Short-Term Interest Modeling)
- 目标:精准捕捉用户在当前会话 (Session) 中的即时意图。
- 输入:用户的最近几次行为序列(比如最近1小时内的10次点击)。
- 建模方式:
- 短期兴趣对顺序极为敏感(比如,你先搜了“显示器”,再搜“显卡”,这和你反过来搜,意图可能完全不同)。
- 因此,必须使用能处理时序信息的模型。SDM 的论文中,综合对比了多种方法,最终采用了 RNN + 多头自注意力 (Multi-Head Self-Attention) 的组合。
- RNN (或 LSTM/GRU):先用一个循环神经网络来初步编码序列中的时序依赖关系。
- 多头自注意力:这是借鉴了 Transformer 的思想。在 RNN 初步编码后,再用一个多头自注意力层,来捕捉序列内部不同物品之间的复杂关联。比如,在一个序列
[手机壳, 充电器, 钢化膜]中,注意力机制能学会这三者是紧密关联的“手机配件”组合,从而提炼出一个更精准的“购买手机配件”的短期意图。
- 输出:一个代表用户短期、即时兴趣的向量
U_short。
3. 长短期兴趣融合 (Fusion)
问题:现在我们有了代表“我是谁”的
U_long和代表“我现在想干嘛”的U_short,该如何将它们融合成一个最终的用户向量呢?解决方案:门控网络 (Gating Network)
SDM 设计了一个巧妙的门控单元。这个门也是一个微型神经网络,它会根据输入信息,动态地生成一个权重
g(一个0到1之间的数值)。最终的用户向量通过如下方式加权融合:
Ufinal=g⋅Ushort+(1−g)⋅Ulong
门控的意义:这个权重
g就像一个**“智能调控阀”**。- 当用户的短期行为意图非常明确时(比如连续搜索了某个特定商品),门控网络会学会输出一个较大的
g,使得最终的用户向量更偏向于短期兴趣U_short。 - 当用户只是在无目的地“闲逛”,短期行为很发散时,门控网络会学会输出一个较小的
g,使得最终的用户向量更偏向于稳定可靠的长期兴趣U_long。
- 当用户的短期行为意图非常明确时(比如连续搜索了某个特定商品),门控网络会学会输出一个较大的
SDM 模型的核心贡献在于:
- 首次清晰地将用户兴趣拆分为长、短期两个维度,并使用不同的、更具针对性的网络结构(RNN/Attention vs. Attention/Pooling)进行建模。
- 设计了门控网络这一动态融合机制,让模型可以根据上下文,智能地权衡用户的即时意图和稳定偏好。
- 相比于之前的模型,SDM 能够更精准、更动态地捕捉用户的兴趣变化,尤其是在短视频、新闻、电商等需要对用户即时意图做出快速响应的场景下,取得了非常显著的效果,是序列化召回领域的一个里程碑。
5.3. 内容与运营策略 (Content & Operational Strategies)如果说协同过滤和深度学习模型是召回系统里依靠“数据和算法”驱动的“正规军”,那么内容与运营策略召回,就是系统中不可或缺的、负责查漏补缺、处理特殊情况、注入业务理解的“特种部队”和“后勤保障部队”。一个成熟的召回系统,绝对是这两类方法协同作战的结果。
标签召回 (Tag-based Recall / u2tag2i)
这是一种以“标签”为核心,连接用户与物品的、非常经典且有效的内容召回方法。
**核心思想:“以标签为媒,连接人与物”。**它的逻辑非常清晰,分为两步:
- u2tag (User-to-Tag):先搞清楚用户喜欢什么标签。
- tag2i (Tag-to-Item):再根据用户喜欢的标签,去找带有这些标签的物品。
工作流程详解
- 构建用户标签偏好画像 (u2tag):
- 简单统计:分析用户历史交互过(点击、购买等)的所有物品,将这些物品携带的标签进行汇总、加权。比如,用户点击了10件带有“科幻”标签的物品,5件带有“悬疑”标签的物品,那么他对“科幻”标签的偏好权重就更高。
- 模型预测:也可以训练一个模型,根据用户的行为和属性,直接预测他对各个标签的偏好得分。
- 最终产出:一个用户的标签偏好画像,形式通常是
{“科幻”: 0.9, “悬疑”: 0.7, “爱情”: 0.1, ...}。
- 匹配物品 (tag2i):
- 系统中需要有一个**“物品-标签”的倒排索引**,即能快速地根据一个标签,找到所有具备该标签的物品。
- 将用户的标签偏好向量,与全量物品的标签进行匹配,计算一个匹配分数,召回得分最高的物品。
优点与挑战
- 优点:
- 可解释性强:推荐理由非常直观(“因为你喜欢科幻,所以为你推荐……”)。
- 泛化能力强,善于“破圈”:可以为用户推荐他从未见过,但标签符合其偏好的新物品,是解决物品冷启动和挖掘用户新兴趣的利器。
- 挑战:
- 极度依赖标签体系的质量:标签的准确性、覆盖率、粒度直接决定了这条召回路径效果的上限。构建和维护一个高质量的标签体系,需要大量的人工、算法和业务经验投入,是典型的“脏活累活”。
热销/热门召回 (Hot-Item Recall)
这是所有召回策略中最简单、最鲁棒,也是不可或缺的“保底”策略。**核心思想:“相信群众的选择”。**它的逻辑是,不管用户是谁,把当前整个平台上最受欢迎、最多人消费的物品推荐给他,总归不会犯大错。这些热门物品本身已经经过了市场的“检验”,通常质量和吸引力都有保障。
主要应用场景:终极“安全网”
- 用户冷启动:这是热门召回最重要的使命。对于一个没有任何行为历史的新用户,我们对他一无所知,任何个性化算法都无从下手。此时,提供一个热门榜单是开启用户“探索之旅”、收集其初始偏好的最有效方式。
- 个性化召回“失灵”的补充:当所有个性化召回路径(如双塔、协同过滤)因为数据稀疏等原因,没有为某个用户召回足够多的物品时,热门召回可以作为补充,确保推荐页面不会“开天窗”。
实践中的挑战
实现一个好的热门召回,远不止是“按销量排个序”那么简单,需要精细化运营:
- “热门”的定义:
- 时间窗口:是取最近1小时的热门,还是24小时,或是7天?不同的时间窗口反映了不同的趋势。实时热门榜能追热点,但可能不稳定;周期热门榜更稳健,但对突发事件不敏感。
- 统计口径:是用绝对的销量/点击量,还是用点击率/转化率?
- 分门别类:全局的热门榜很容易被少数几个大品类(如手机、服饰)霸占。更精细的做法是维护分品类、分地域、分人群的热门榜。
- 热门的偏见与反作弊:
- 需要剔除大促、营销活动带来的“虚假”热门。
- 要警惕热门推荐带来的“马太效应”,即越热门的越被推荐,越被推荐的就越热门,导致多样性下降。需要加入一些时间衰减、多样性打散的机制。
其他策略 (复购, 高CTR等)
除了上述策略,召回系统还会配置多种满足特定业务目标的策略。
- 复购召回 (Rebuy Recall)
- 逻辑:向用户推荐他们曾经购买过的商品。
- 应用场景:对消耗品(如纸巾、饮料、猫粮、化妆品等)极其有效。
- 实现:识别出消耗品类目,结合用户的平均购买周期,在用户可能即将用完时,触发复购召回。
- 高CTR/CVR召回 (High CTR/CVR Recall)
- 逻辑:维护一个全站范围内,历史上平均点击率或转化率最高的物品列表。
- 应用场景:这些物品是“转化效率”的保证。在需要提升关键指标时,或者作为探索用户兴趣的“钩子”,适量混入这些高CTR物品,能有效提升整体收益。
- 高质量/好评召回 (High-Quality Recall)
- 逻辑:召回由平台编辑、专家或高分用户评选出的高质量内容/商品。
- 应用场景:用于提升平台格调和用户信任感,平衡纯数据驱动可能带来的“劣币驱逐良币”问题。
- 复购召回 (Rebuy Recall)
三、 召回系统工程与策略 (Recall System Engineering & Strategy)
1. 模型与数据的更新机制 (Model & Data Updating)
推荐系统不是一个静态的系统,它是一个需要与用户实时互动的“生命体”。用户的兴趣在变,平台上的物品在变,热点趋势也在变。因此,模型和它所依赖的数据必须保持“新鲜”,才能做出精准、及时的推荐。如何保持新鲜?业界主要有两种策略:全量更新和增量更新。
1.1. 全量更新 (Full Retraining)这是一种最稳健、最经典的更新方式。
- 核心思想:“推倒重来,定期大扫除”
- 全量更新的逻辑是,我们会设定一个更新周期(比如每天一次)。在这个周期内,我们彻底丢弃掉旧的模型,然后收集这个周期内(比如过去24小时或过去7天)的全部新数据,从零开始重新训练一个全新的模型。
- 工作流程详解:
- 数据聚合:在固定的时间点(比如每天凌晨),一个ETL任务会启动,将过去一段时间(如24小时)的所有用户行为日志(点击、曝光、购买等)收集、清洗、整合成一个庞大的训练数据集。
- 模型训练:使用这个完整的数据集,从头开始训练我们的召回模型(如双塔模型)。这个过程会持续数小时,直到模型完全收敛。
- 离线评估:在训练好的新模型上线前,会在一个预留的测试集上进行评估,确保其效果优于旧模型。
- 全量部署:评估通过后,用这个新模型为全量的用户和物品生成最新的 Embedding 向量,构建新的 ANN 索引,然后通过原子切换,将线上服务指向这个全新的模型和索引。
- 优点与缺点:
- 优点:
- 模型效果最稳定、全局最优:由于模型每次都能看到一个完整周期内的全局数据分布,它能学习到最宏观、最鲁棒的模式,不易被短期的数据噪声或趋势带偏。
- 工程实现与维护相对简单:整个流程是周期性的、批量的,逻辑清晰,更容易调试和管理。
- 缺点:
- 时效性极差,延迟高:这是它最大的弊端。从用户产生一个行为,到这个行为被模型学到,中间的延迟非常长(通常是T+1,即延迟一天)。这导致模型无法捕捉实时热点,对用户兴趣的快速变化响应迟钝。
- 计算资源开销巨大:每天都对海量数据进行一次从零开始的训练,是对计算资源的巨大消耗,成本高昂。
- 优点:
- 一个比喻:年度体检
- 全量更新就像我们每年做一次全面的身体检查。它非常彻底,能发现深层次的、全局性的健康状况,但你无法通过它来了解自己此时此刻的瞬时心率。
- 核心思想:“推倒重来,定期大扫除”
1.2. 增量更新 (Incremental/Online Learning)为了解决全量更新时效性差的问题,增量更新应运而生。
- 核心思想:“即刻反馈,持续微调”
- 增量更新不再“推倒重来”,而是在一个已经训练好的线上模型的基础上,利用实时产生的新数据,对模型进行持续、小步快跑式的微调。
- 工作流程详解:
- 数据流式传输:用户的行为数据不再是每天打包一次,而是通过消息队列(如 Kafka)以流的形式实时地传输到训练平台。
- 实时训练 (Near Real-time Training):一个持续运行的训练服务会消费这个数据流,以很小的批次(mini-batch)为单位,对线上的模型进行不间断的训练(梯度更新)。
- 模型同步:更新后的模型参数或特定的 Embedding(尤其是 User Embedding)会以较高的频率(比如每10分钟或每小时)被同步到线上的推荐服务实例中。
- 最常见的增量更新:对于用户塔,可以实现分钟级的更新。当用户产生新行为后,可以立即重新计算并更新他本人的 User Embedding,这样他下一次刷新就能看到基于他刚才行为的推荐。
- 优点与缺点:
- 优点:
- 时效性极佳:模型能够分钟级甚至秒级地学习到用户的最新行为和全局热点的变化,推荐的相关性和即时性非常强。
- 资源效率高:每次只处理新产生的数据,避免了重复计算,节省了大量资源。
- 缺点:
- 有“过拟合”于近期数据的风险:模型可能会过度关注最新的数据流,而慢慢“忘记”长期、稳定的用户兴趣模式,这种现象被称为“灾难性遗忘 (Catastrophic Forgetting)”。
- 工程实现与维护极其复杂:构建一个稳定、可靠的流式数据处理和实时训练系统,其技术挑战远高于批处理系统。
- 训练可能不稳定:实时数据流中可能存在噪声或异常数据,容易对模型造成短期的负面冲击。
- 优点:
- 一个比喻:可穿戴健康手环
- 增量更新就像一个7x24小时佩戴的智能手环。它能实时监测你的心率、步数,并立刻给你反馈,但它可能无法发现那些需要全面检查才能看出的深层健康问题。
- 核心思想:“即刻反馈,持续微调”
1.3. 行业标准:混合模式 (Hybrid Approach)在现代工业界,几乎没有任何一个大型推荐系统只采用上述两种模式中的一种。最成熟、最普遍的解决方案是**“全量+增量”的混合模式**:
- 以“全量更新”为根本:保持一个天级或周级的全量训练流程,用于产出一个高质量、鲁棒的基座模型 (Base Model)。这个基座模型保证了系统的下限和稳定性,能够纠正增量学习可能带来的长期漂移。
- 以“增量更新”为抓手:在这个高质量的基座模型之上,进行小时级或分钟级的增量更新。这保证了系统对实时变化的敏感性和响应速度。
2. 多路召回的策略设计 (Multi-Path Recall Strategy Design)
2.1. 场景化策略 (Homepage vs. Detail Page)一个核心的策略思想是:“用户的意图,由场景决定;召回的策略,由意图决定。” 不同的推荐场景(用户在APP里的不同位置),暗示了用户完全不同的心理状态和需求。我们的召回策略必须具备“见人下菜碟”的能力。
首页/信息流推荐 (Homepage/Feed Recommendation)
- 用户意图:模糊、宽泛、探索性 (Exploratory & Broad)
- 用户打开APP首页时,通常没有一个非常具体的目标,心态是“随便逛逛,看看有什么有意思的”。
- 召回目标:探索与多样性 (Exploration & Diversity)
- 我们的首要任务是快速试探出用户当下的兴趣点,或者为他打开一扇新世界的大门。因此,召回结果必须丰富多样、覆盖面广。
- 策略组合:多路、宽泛策略为主
- 个性化泛兴趣召回:基于用户的长期、泛在兴趣画像进行向量化召回(User-based)。
- 热门召回:必须有,用于捕捉全局热点,并服务于冷启动用户。
- 社交网络/图召回:挖掘圈层热点,实现“破圈”。
- 标签召回 (u2tag2i):根据用户的兴趣标签,推荐一些他可能从未见过的新品类。
- 一个比喻:大型百货商场的橱窗
- 商场入口处的橱窗,会陈列当季最新款的服装、最酷的电子产品、最香的香水……它的目标是吸引各种不同需求的顾客,让他们产生“进去逛逛”的欲望。
详情页/播放页推荐 (Detail Page/Post-Interaction Recommendation)
- 用户意图:明确、深入、关联性 (Focused & Deep)
- 当用户点进一个具体的物品(比如一部手机)的详情页时,他的意图变得非常清晰:他此刻正高度关注这个物品或其同类。
- 召回目标:深化与精准 (Deepening & Precision)
- 我们的任务不再是探索,而是要**“趁热打铁”**,提供与当前物品高度相关的内容,满足用户的深度挖掘需求,促成转化。
- 策略组合:精准、窄域策略为主
- Item-to-Item (I2I):绝对的主力。包括基于向量的I2I(找Embedding最近邻)、基于协同过滤的I2I(如Swing算法)、基于图关联的I2I等。
- 属性召回:召回同一品牌、同一细分品类、同一作者/店铺的其他物品。
- 一个比喻:超市里的特定货架
- 当你拿起一包“番茄味薯片”时,你身边的货架上一定是其他各种口味的薯片、其他品牌的薯片,以及搭配薯片的可乐。所有推荐都围绕着“薯片”这个核心。
- 用户意图:模糊、宽泛、探索性 (Exploratory & Broad)
2.2. 召回配额管理 (Quota Management)当系统中有几十上百路召回策略并行时,我们就面临一个关键问题:最终要呈现给粗排的1000个候选中,每一路策略应该“贡献”多少个名额?这就是配额管理。
- 静态/固定配额:
- 做法:最简单的方式,由算法工程师根据离线实验和线上经验,为每一路召回手动配置一个固定的数量或比例。例如:向量召回出400个,ItemCF出200个,热门召回出100个……
- 优缺点:实现简单,稳定可控。但无法做到个性化,对所有用户都“一视同仁”。
- 动态/个性化配额:
- 核心思想:不同用户、不同场景下,各路召回策略的“靠谱程度”是不同的。因此,配额也应该是因人而异、因时而异的。
- 做法:训练一个轻量级的**“配额分配模型”**(比如 Logistic Regression 或浅层MLP)。
- 输入:用户的特征,如活跃度(新用户/老用户)、会话状态(刚打开APP/已浏览一段时间)、用户画像(兴趣是否收敛)等。
- 输出:一个权重分布,代表了每一路召回策略在当前情况下的“推荐价值”。
- 例子:
- 对于一个新用户,该模型可能会给“热门召回”分配90%的配额。
- 对于一个深度篮球迷,模型可能会给“篮球圈层I2I召回”分配70%的配额。
- 效果:通过动态配额,系统可以为每个用户“量身定制”一个最优的召回策略组合,将宝贵的粗排计算资源,集中在那些最可能产生好结果的召回源上。
- 静态/固定配额:
2.3. 特殊场景优化 (如电商付费推荐)除了通用的推荐场景,召回系统还必须为一些具有明确商业目标的特殊场景进行深度定制。以电商付费推广(广告)为例:
- 目标变化:此时的最终目标,不再仅仅是用户的“兴趣”,而是平台的**“收入” (RPM/eCPM),需要同时平衡用户体验、平台收入、广告主ROI**三方利益。
- 召回策略的适配与演化:
- 候选集变化:召回的候选池不再是全量商品库,而是广告商品池。
- 关联性重定义:I2I的逻辑,从“看了A的用户也看了B”,演变为“点击了A商品详情页的用户,最终转化(购买)了B广告商品”。
- 商业化目标融入召回:
- 出价 (Bid) 感知的召回:如我们之前讨论的,通过数学变换,将广告主的出价信息融入到物品向量
a'中,使得召回模型在计算点积时,天然地倾向于那些**“eCPM潜力高”**的广告。
- 出价 (Bid) 感知的召回:如我们之前讨论的,通过数学变换,将广告主的出价信息融入到物品向量
- 高意图场景的重点优化:
- 在**“购物车页面”、“支付成功页”、“订单详情页”**等场景,用户的购买意图极强。
- 在这些“黄金地段”,召回策略会变得更“激进”,大力度地推荐与用户购买/加购商品高度相关的付费推广商品,转化率极高。
总结:特殊场景的优化,要求我们将业务逻辑深度嵌入到召回算法的设计中。召回模型需要理解的,不再仅仅是用户的兴趣向量,更是复杂的场景上下文、用户意图强度和商业化目标。
3. 多路召回的融合方法 (Merging Methods for Multi-Path Recall)[拓展]
3.1. Zigzag Merge 策略核心思想:“交叉轮播,雨露均沾”
Zigzag Merge,又称交叉合并,它的核心思想非常直观:避免任何单一召回源霸占最终列表的头部位置,保证各路召回的优质结果都有机会得到展现,从而提升最终候选集的整体多样性和覆盖率。
它就像洗牌一样,将来自不同牌堆的牌交叉地叠在一起,形成一副新的、混合均匀的牌。
工作流程详解
中清晰地展示了 Zigzag Merge 的完整步骤,我们来详细解读一下:
第一步:召回排序 (Rank within each path)
- 前提条件:在进行合并之前,每一路召回策略必须已经完成了内部的排序。
- 例如:
- 向量召回A路,已经根据点积分数从高到低排出了它的结果:
[A1, A2, A3, A4, A5, ...] - ItemCF召回B路,已经根据物品相似度从高到低排出了它的结果:
[B1, B2, B3, B4, B5, ...] - 热门召回C路,已经根据热度分数从高到低排出了它的结果:
[C1, C2, C3, C4, C5, ...]
- 向量召回A路,已经根据点积分数从高到低排出了它的结果:
第二步:设定比例 (Set Proportions)
- 策略核心:这是注入业务理解和策略调控的关键一步。我们需要根据不同召回路径的重要性和历史表现,为它们设定一个在最终候选集中的期望占比。
- 例如,我们设定:
- 路径A (主力个性化路径):占比 50%
- 路径B (补充关联性路径):占比 30%
- 路径C (保证多样性与新颖性路径):占比 20%
- 这个比例
5:3:2将作为后续交叉提取的指导方针。
第三步:交替提取 (Interleaving / The “Zigzag”)
这是 Zigzag Merge 最核心的执行步骤,一个轮流从不同列表“取货”的过程。
- 过程:
- 系统会为每个列表维护一个指针,初始都指向列表的第一个位置。
- 根据
5:3:2的比例,进行一轮“取货”。为了尽可能地模拟这个比例,我们可以决定这一轮“取2个A,取1个B,取1个C”。 - 开始取货:
- 从 A 列表的头部取出 2 个物品:
A1, A2。 - 从 B 列表的头部取出 1 个物品:
B1。 - 从 C 列表的头部取出 1 个物品:
C1。
- 从 A 列表的头部取出 2 个物品:
- 更新指针:A列表的指针移动到第3位,B和C的指针移动到第2位。
- 循环往复:不断重复这个“按比例轮流取货”的过程,直到最终的候选集数量达到预设的目标(比如1000个)。
第四步:结果去重 (Deduplication)
- 必要性:不同的召回路径,完全有可能召回同一个物品。比如,一个物品既是热门,又和用户的历史兴趣高度相似。
- 做法:这是一个在交替提取过程中实时进行的步骤。每当要从某个列表(比如B列表)取出一个物品(比如
B2)时,系统会先检查这个B2是不是已经存在于我们正在构建的最终候选集里了。- 如果已存在,就跳过
B2,尝试取 B 列表的下一个物品B3。 - 如果不存在,才将
B2加入最终候选集。
- 如果已存在,就跳过
第五步:最终候选集 (Final Candidate Set)
- 通过以上步骤,我们最终得到一个融合了多路召回结果的、多样化且内部相对有序的候选列表,例如:
[A1, A2, B1, C1, A3, B2, A4, C2, ...]。这个列表将作为下一阶段——粗排层的输入。
总结:Zigzag Merge 的价值
- 保证多样性与公平性:这是它最大的价值。通过交叉轮播,它确保了即使是占比很小的召回路径(如新奇特物品探索路径),它的头部优质结果也有机会出现在最终候选集的前列,从而避免了整个推荐系统只推荐“安全牌”,丧失探索能力。
- 简单高效:它是一种启发式规则,不涉及复杂的模型计算,实现简单,运行速度极快,完全满足召回阶段的低延迟要求。
- 灵活可控:算法工程师和策略运营人员可以非常方便地通过调整“第二步”的比例,来调控不同召- 回源在最终结果中的影响力,实现精细化的运营。
四**、 评估体系 (The Evaluation Framework)**
1. 离线评估 (Offline Evaluation)
1. Recall@K (召回率@K)
核心问题:“在我为用户召回的 Top-K 个物品中,成功‘覆盖’了多少用户在未来真正喜欢的物品?”
公式 (针对单个用户):

名词解释:
召回的TopK结果:你的新召回模型为该用户产出的前 K 个物品。用户真实喜欢的物品集合 (Ground Truth):在测试集中,该用户有过明确正反馈(如点击、购买)的物品集合。
举例说明:
- 在测试数据中,用户小明真实点击了5个商品
{A, B, C, D, E}。 - 你的召回模型为他召回了500个商品,其中排名前500的结果里,包含了
{A, D, F, G, ...}。 - 两个集合的交集是
{A, D},数量为2。 - 那么,你的模型对小明的
Recall@500= 2 / 5 = 40%。 - 最终的全局指标,是所有用户的 Recall@K 的平均值。
- 在测试数据中,用户小明真实点击了5个商品
解读与局限:
- 解读:这个指标直接衡量了召回模型的“本职工作”——查全率。它反映了模型为后续排序阶段提供“炮弹”(好物料)的能力。Recall@K 越高,说明漏掉的好东西越少。
- 局限:它完全不关心顺序。在上面的例子中,无论 A 和 D 出现在召回列表的第1、2位,还是第499、500位,Recall@500 的值都是一样的。
“教科书”中的 Recall:二分类世界的视角
在一个二分类问题(比如,判断一封邮件是不是垃圾邮件)中:
- TP (True Positive):邮件是垃圾邮件,模型也正确地预测为垃圾邮件。
- FN (False Negative):邮件是垃圾邮件,但模型错误地预测为正常邮件。(漏报了)
- FP (False Positive):邮件是正常邮件,但模型错误地预测为垃圾邮件。(误报了)
- TN (True Negative):邮件是正常邮件,模型也正确地预测为正常邮件。
这里的 Recall(召回率) 公式是:

- 分母 (TP + FN):代表所有实际上是正样本的数量(所有真正的垃圾邮件数量)。
- 分子 (TP):代表在所有正样本中,被模型成功找出来的数量。
所以,它的核心问题是:“在所有真正的垃圾邮件里,我们成功揪出来了多少?” 它衡量的是模型“找全”正样本的能力。
推荐召回场景的特殊性
现在,我们试着把这个定义直接套用到推荐召回上,会发现两个核心困难:
- “负样本”的定义极其困难,尤其是 TN:
- TP:我们推荐了一个物品,用户点击了。(√ 好定义)
- FN:一个物品用户很喜欢,但我们没推荐。 (√ 好定义)
- TN (True Negative):我们没有推荐一个物品,而用户也确实不喜欢它。这个集合有多大? 对于一个用户来说,可能是几百万甚至上亿的物品!我们不可能知道用户对所有未推荐物品的真实偏好。因为无法确定 TN,也就无法计算像 Accuracy 这样的指标。
- 推荐的输出不是“是/否”,而是一个“列表”:
- 二分类模型会对每一个样本都给出一个“是”或“否”的判断。
- 推荐召回系统不会对全站所有物品都做判断,它的最终输出是一个Top-K 的、排好序的候选列表(比如,召回500个物品)。
2. Hit Rate@K (命中率@K)
核心问题:“我的召回策略,对于多大比例的用户群体是‘有效’的?”
计算方式:
对于每一个用户,判断他的
Ground Truth中,是否有至少一个物品出现在了召回的 Top-K 结果里。如果有,则记为一次**“命中 (Hit)”**,这位用户的得分是1;否则为0。
最终的指标是:

举例说明:
- 我们在10000个用户上进行测试。
- 测试结果发现,有7800个用户,他们至少有一个未来点击的商品,被我们的模型成功召回在了Top-500的列表里。
- 那么,
Hit Rate@500= 7800 / 10000 = 78%。
解读与局限:
- 解读:Hit Rate 衡量了召回策略的**“覆盖广度”**。一个高 Hit Rate 意味着你的策略对于大部分用户都能起到最基本的作用,至少没“空手而归”。
- 局限:这是一个非常粗粒度的指标。对于一个用户,命中1个物品和命中10个物品,都被记为一次 Hit,它无法区分这种“命中质量”的差异。
3. MAP@K (Mean Average Precision@K / 平均准确率均值@K)
- 核心思想:这个指标开始**关心“排序位置”**了。它认为,命中一个物品,且这个物品排在召回列表的越前面,得分就应该越高。
- 计算方式:它由两个部分构成:AP 和 MAP。
Precision@i (P@i):前 i 个推荐结果中的准确率。
Average Precision (AP@K) (针对单个用户):只在命中正样本的位置计算 P@i,然后求平均。

其中
rel(i)是一个指示函数,如果位置i的物品是正样本,则为1,否则为0。Mean Average Precision (MAP@K):将所有用户的 AP@K 值求算术平均。
- 举例说明:
- 小明的 Ground Truth 是
{A, C}。 - 模型的召回列表是
[A, B, C, D, ...](K>=4)。 - 计算小明的 AP@4:
- 在位置1,命中了A:此时 P@1 = 1/1 = 1.0。
- 在位置2,没命中。
- 在位置3,命中了C:此时 P@3 = 2/3 ≈ 0.67。
- AP@4 = (1.0 + 0.67) / 2 = 0.835。
- 如果召回列表是
[B, C, D, A, ...],那么 AP@4 = (1/2 + 2/4) / 2 = 0.5。分数显著降低。
- 小明的 Ground Truth 是
- 解读:MAP@K 是一个对排序非常敏感的指标,它能很好地反映出模型将好东西排在前面的能力。
4. NDCG@K (Normalized Discounted Cumulative Gain@K / 归一化折损累计增益@K)
核心思想:这是目前学术界和工业界最常用、最科学的排序评估指标之一。它在 MAP 的基础上,考虑了**“相关度的等级”**。
计算方式:由四个部分层层递进。
Cumulative Gain (CG@K):累计增益。只把 Top-K 个物品的相关度得分(不再是0/1,可以是1, 2, 3, 4, 5这样的等级)加起来,不考虑顺序。
Discounted CG (DCG@K):折损累计增益。对排在后面的物品进行“惩罚”,即越往后的物品,其相关度得分要除以一个越大的“折损”系数(通常是
log₂(position+1))。
Ideal DCG (IDCG@K):理想折损累计增益。即对于一个用户,最理想的、完美的推荐排序所能得到的 DCG 分数。
Normalized DCG (NDCG@K):将模型的实际 DCG 分数除以理想的 IDCG 分数,得到一个
[0, 1]之间的归一化结果。
解读:NDCG@K 不仅对排序位置敏感(DCG),还能处理多等级的相关度(比如“完美相关=5分”,“一般相关=3分”),并且通过归一化(NDCG),使得不同用户之间的评估结果具有可比性,是衡量排序质量的**“金标准”**。
召回离线评估的挑战与实践
- 全库评估的难题:在召回阶段,我们不可能真的为每个用户都对全量百万、千万的物品进行打分和排序来计算上述指标,这在计算上是不可行的。
- 业界常用实践:将评估问题转化为一个**“排序中的排序”问题。对于测试集中的每一个正样本**,我们再额外随机采样 999个(或其他数量)用户未交互过的负样本,构成一个1+999的候选池。然后,我们评估新召回模型,能否在这个1000个物品的集合中,将那个唯一的正样本排在尽可能靠前的位置。在这个小集合上,我们就可以高效地计算上述所有指标。
2. 在线评估 (Online Evaluation)
离线评估是在“实验室”里用历史数据进行的“模拟考试”,它快速、安全、低成本。然而,在线评估,才是在真实世界里检验模型能力的“最终高考”。
离线评估有其固有局限性(如数据偏差、无法衡量新颖性等),因此,一个离线指标提升的模型,在线上不一定能带来业务增长。在线评估通过将新策略推送给真实的、活生生的用户,直接衡量它对核心业务指标的真实影响,是所有算法和策略迭代最终的、最权威的“裁判”。
在线评估主要有两种黄金标准方法:A/B 测试和交叉实验。
2.1. A/B 测试 (A/B Testing)
A/B 测试是互联网产品迭代和算法评估的基石,是一种严谨的对照实验方法。
核心思想:“控制变量,对比观察”
比喻:药物临床试验
- 为了验证一种新药是否有效,我们会招募两组病人。一组服用新药(实验组),另一组服用外观一样的安慰剂(控制组)。通过严格对比两组病人的康复情况,我们就能科学地判断新药的真实疗效。
如何设计一个召回策略的 A/B 测试
确定目标与假设 (Define Goal & Hypothesis)
- 假设:明确你认为新策略会带来什么改变。例如:“我假设,新的 Swing 算法召回策略,相比于老的 ItemCF 策略,能够提升用户的点击率和互动多样性。”
- 目标:将假设转化为可量化的指标。
划分流量 (Split Traffic)
- 将线上用户随机、均匀地分成几个互不重叠的组。最简单的就是两组:
- 控制组 (Group A):继续使用当前线上的、稳定的旧召回策略。这是我们的基线 (Baseline)。
- 实验组 (Group B):使用我们想要验证的新召回策略。
- 划分方法:通常使用用户ID或设备ID进行哈希,然后对哈希值取模来分流,以保证分组的随机性和均匀性。必须确保两个组的用户画像(如新老、活跃度等)在统计上是一致的。
确定实验周期 (Determine Duration)
- 实验需要运行足够长的时间,以保证收集的数据量足以得出统计显著的结论。
- 同时,周期应覆盖一个完整的业务循环(比如至少一周),以消除节假日、周末等周期性因素的干扰,并减弱新功能上线带来的“新奇效应”。
数据收集与分析 (Collect & Analyze Data)
- 在实验期间,系统会记录并区分来自不同组的用户行为日志。
- 实验结束后,我们会对比两组的核心业务指标,并通过统计检验(如t检验、卡方检验)来判断观察到的差异是否统计显著 (Statistically Significant)。只有当p-value小于一个阈值(如0.05)时,我们才能有信心地说:“实验组的提升不是由偶然运气造成的,而是新策略的真实效果。”
关注哪些核心业务指标
一个好的评估体系,会同时监控多维度指标,以全面判断一个策略的好坏。
- 效果指标 (Engagement Metrics) - “用户是否更喜欢?”
- 点击率 (CTR)、转化率 (CVR):最核心的效率指标。
- 人均观看/停留时长 (Duration):衡量用户的内容消费深度。
- 互动率:人均点赞、评论、分享、收藏等。
- 商业/效率指标 (Business/Efficiency Metrics) - “我们是否更赚钱?”
- 人均推荐贡献收入 (GMV / RPM):在电商或广告场景下,衡量变现效率。
- 人均推荐引导访问/购买数。
- 生态/长期指标 (Ecosystem/Long-term Metrics) - “推荐是否健康可持续?”
- 推荐多样性:推荐结果的类目、作者是否更丰富。
- 负反馈率:用户“不感兴趣”、屏蔽、取消关注等行为的比例。
- 用户留存率 (Retention):新策略是否对用户的长期留存有正向或负向影响。这是一个非常重要的“护栏”指标,需要警惕那些短期提升CTR但长期损害用户留存的“标题党”式策略。
2.2. 交叉实验 (Interleaving)
核心思想:“同台竞技,立分高下”
A/B 测试虽然严谨,但当两个策略效果差异很微小时,往往需要很长的测试时间和海量用户才能得出结论。交叉实验是一种更灵敏、更高效的,专门用于对比两个排序算法优劣的在线评估方法。
比喻:饮料的“盲品测试”
- A/B测试就像让一群人连续一周只喝可口可乐,另一群人只喝百事可乐,最后看哪个群体更开心。
- 交叉实验则是把可口可乐和百事可乐都倒进没有标签的杯子里,让同一个人同时品尝,然后直接问他“你更喜欢哪一杯?”。这种直接的、并列的比较,能更快速、更敏感地分出高下。
工作原理
混合列表:被分到交叉实验组的用户,看到的推荐列表不是单纯来自策略A或策略B,而是一个由A和B的结果混合而成的列表。
交替展示 (Interleave):系统会从A的排序结果 [A1, A2, A3, ...] 和 B的排序结果 [B1, B2, B3, ...] 中,交替地取出物品,形成一个最终展示给用户的混合列表,比如 [A1, B1, A2, B2, A3, B3, ...]。
点击归因 (“投票”):当用户在这个混合列表上发生点击时,这个点击就会被归因于最初提供这个物品的那个策略。
- 如果用户点击了
A2,那么策略A就**“得一分”**。 - 如果用户点击了
B3,那么策略B就**“得一分”**。
对比胜率:实验运行一段时间后,我们统计策略A和策略B各自的总得分。如果策略A的得分显著高于策略B,我们就能非常有信心地判断:策略A的排序结果比B更吸引用户。
优点与局限
优点:
- 极高的灵敏度:由于是在同一个用户、同一个页面上进行直接比较,它消除了大量因“用户差异”带来的噪声,能够检测出非常微弱的排序效果差异。
- 极高的效率:达到统计显著性所需要的用户量和时间,远少于A/B测试。非常适合算法工程师进行快速的、小步快跑式的迭代。
局限:
- 应用范围窄:它主要用于评估排序质量的优劣,不适用于评估那些无法以“排序列表”形式呈现的、差异巨大的产品改动(比如UI界面、商业化策略等)。
- 实现更复杂:需要开发一套支持列表混合、点击归因的实验框架。
3. 超越准确性的评估
如果我们只关注 CTR、CVR 等准确性指标,推荐系统会很快陷入一个**“越推越窄”的恶性循环,最终给用户造成“信息茧房”和审美疲劳**。多样性、新颖性和覆盖率,就是衡量系统这种“健康度”和“长远眼光”的核心指标。
3.1. 多样性 (Diversity)
- 核心问题:“我给用户推荐的这一页内容,是不是看起来都差不多?”
- 定义:多样性衡量的是单次推荐列表内部,物品之间互不相似的程度。它的目标是避免推荐结果的同质化。
- 一个比喻:健康的饮食
- 如果一个营养师给你推荐的“健康餐”是:
[西兰花, 芥蓝, 西芹, 菜花],虽然都是健康蔬菜,但过于单调。 - 一个好的推荐应该是:
[西兰花, 鸡胸肉, 糙米饭, 苹果],种类丰富,营养均衡。推荐系统也应如此。
- 如果一个营养师给你推荐的“健康餐”是:
如何度量多样性?
- Intra-List Similarity (ILS / 列表内相似度):这是最常用的指标。
- 计算方式:
- 在一个推荐列表(比如Top-10)中,取出所有的物品对(比如
C(10,2)=45对)。 - 计算每一对物品之间的相似度(可以用物品 Embedding 的余弦相似度,或者类目、标签的 Jaccard 相似度等)。
- 将所有这些相似度值求一个平均,就得到了 ILS。
- 在一个推荐列表(比如Top-10)中,取出所有的物品对(比如
- 解读:ILS 的值越高,代表列表内的物品越相似,多样性就越差。因此,我们通常用
Diversity = 1 - ILS来表示多样性,这个值越高越好。
- 计算方式:
- 类目/标签多样性 (Category/Tag Diversity):
- 计算方式:一个更简单、更可解释的方法。直接统计一个推荐列表(比如Top-10)中,出现了多少个独一无二的物品类目或标签。
- 解读:不重复的类目/标签数量越多,说明推荐的内容来源越广泛,多样性就越好。
3.2. 新颖性 (Novelty)
- 核心问题:“我推荐的东西,对用户来说有多大的‘惊喜感’?”
- 定义:新颖性衡量的是推荐结果对于某个特定用户来说,有多么的**“新奇”、“出乎意料”。它关注的是物品与用户历史行为**之间的差异性。
- 与多样性的关键区别:
- 多样性:是列表内的物品互相之间有多不一样。
- 新颖性:是列表内的物品与用户的过去有多不一样。
- 例子:给一个科幻迷推荐10部他都没看过的、不同题材的冷门科幻电影,这个列表多样性很高,但新颖性可能并不高(因为还是在他熟悉的领域内)。如果此时推荐了一部高质量的历史纪录片并被他喜欢了,这才叫高新颖性。
如何度量新颖性?
- 推荐列表的平均流行度 (Mean Popularity):
- 计算方式:计算推荐列表中所有物品的平均流行度(比如,平均被多少用户消费过)。
- 解读:平均流行度越低,说明推荐的物品越小众,因此新颖性就越高。
- 平均自信息 (Mean Self-Information):
- 计算方式:这是对平均流行度的一种更优雅的数学表达。一个物品
i的流行度(即它被消费的概率)为p(i),那么它的自信息就是log₂(p(i))。越流行的物品,p(i)越高,自信息就越低。推荐列表的新颖性,就是列表中所有物品的平均自信息。 - 解读:推荐的物品越冷门、越小众,这个值就越高,代表新颖性越好。
- 计算方式:这是对平均流行度的一种更优雅的数学表达。一个物品
3.3. 覆盖率 (Coverage)
核心问题:“我的推荐系统,有没有‘雨露均沾’?全站有多少比例的物品曾经得到过推荐的机会?”
定义:覆盖率是一个系统级的宏观指标,它衡量的是在一段时间内,推荐系统能够推荐出的不重复物品的总数,占整个物品库总数的比例。
为什么覆盖率很重要?
平台生态健康:高覆盖率意味着平台上的长尾物品、新晋内容创作者/商家有被发现的机会,而不是让所有流量都集中在少数几个头部爆款上。这对于维持一个健康、有活力的创作者/商家生态至关重要。
用户长期体验:高覆盖率是实现新颖性和多样性的基础。如果系统来来回回只能推荐那一小撮东西,用户的长期体验必然会下降。
如何度量覆盖率?
物品空间覆盖率 (Item-Space Coverage):
计算方式:
- 选定一个时间窗口(比如一周)。
- 统计在这个窗口内,至少被推荐给过任意一个用户的、所有不重复的物品总数。
- 用这个总数,除以平台总的物品库数量。

基尼系数 (Gini Coefficient) / 熵 (Entropy):
- 这两个指标可以衡量曝光分布的均衡性。
- 基尼系数越低,或熵越高,说明推荐系统给予每个物品的曝光机会越公平、越均匀,而不是集中在少数爆款上。


