🎯2021.03.04 召回-负例的艺术(wip)
Mar 4, 2021
| 2023-3-20
0  |  0 分钟
type
Post
status
Published
date
Mar 4, 2021
slug
2021.03.04 召回-负例的艺术
summary
2021.03.04 召回-负例的艺术
tags
推荐
召回
样本
category
算天算地系列
icon
password
召回是负例选择的艺术,如何根据场景选择合适的召回负例,是决定召回效果的关键。目前的实践来看负例一般有以下几个选项:随机负例,真实负例,in-batch负例,级联负例。

1. 随机负例

首先一个众所周知的实践结果是只用“真实负例+正例”的效果非常差,远不如“随机负例+正例”。
为什么呢?一般认为是训练空间和预测空间的不一致导致的:能展现在用户面前的“真实负例”毕竟是少数,而召回模型面临的是超大规模的候选集,如果大部分的广告或者内容这个模型都从未见过,那显然会有泛化性能的问题。
从另一个角度来看,通过粗排和精排层层筛选展现在用户面前的内容都已经是相对优秀的内容,这部分内容相对于召回的海量候选,算得上是困难样本,两者的分布差异巨大,只用困难样本训练必然导致召回模型过拟合于困难样本,就难以泛化到全量候选中的简单样本。
召回的作用是海选,需要有比较强大的泛化能力,需要让召回模型见到各种各样的样本,因此随机样本正是起到了这样的作用。正样本与随机样本的比例需要通过实验来确定,一般来说在 1:5 到 1:10 的水平比较合适。
“随机负例”也不是真的就全候选完全随机,而且也不是一定就好用,实践中,还需要考虑很多的问题,一般来说,使用“随机负例”有以下几类问题。

1.1 模型更新速度问题

由于正例与“随机负例”的比例是固定的,因此在建模比较稀疏的目标时,由于很少有正例,也就很少会去采负例,这样模型中这个目标的更新就会非常慢。比如假设有一个点击召回只用随机负例,如果一个用户对推荐给他的内容都不满意,一直在刷,从不点击,那点击召回模型就不会更新,也不可能学到用户的这个兴趣点。为解决这个问题,还是需要适当地补充一点其他的负例,比如真实负例。

1.2 高热打压问题

负例中高热内容占比比较大,随机负例采样会导致这部分内容被打压,影响效果,需要做一些降采样的操作,这个问题在 facebook 的论文中也有提及。
 
 
基于Popularity随机选择负例
越流行的item,如果没被用户点击看过,则更可能对于该用户来说是一个真实的负例。
 

2. 真实负例

即曝光未点击样本。
只用“真实负例”,确实会导致 sample selection bias 问题,即召回 serving 时的样本空间和 training 时的样本空间不一致,解法参考上文 1. 随机负例 部分。
FB 的文章里也提到,“真实负例”无论怎么用都没有什么作用,那是否真的就得一棒子打死呢?这个也得看场景,FB 文章的场景是搜索,搜索就存在很多 doc 确实曝光了,但可能位置偏后,用户根本没注意到的问题,这种情况还存在于双列的场景,曝光未点击的样本,用户是否不喜欢,是有比较大的噪声的。而对于单列沉浸式的场景,比如抖音,这种噪声就小不少,“真实负例”的价值也就更大一些。因此,不能盲目否定,需要根据优化的场景来判断。
“真实负例”相比“随机负例”,还是 hard 不少,在某些场景,可以帮模型学到更好的排序能力。比如“真实负例”可以一定程度上解决只用“随机负例”造成的稀疏目标模型更新速度问题,参考上文 1.1 模型更新速度问题

3. in-batch 负例

一定程度解决 sample selection bias 问题
 
 
 

4. hard 负例挖掘

4.1 级联负例

级联负例是个比较大的话题,它的出现是通过缓解召回和排序不一致的问题 (这个问题还有其他解法,比如直接增加一路级联召回,扩大召回和进粗排的条数等),来提升召回的效果。
  • 为什么会有召回和排序不一致?
    • 目标导向不一致:因为召回往往是单目标建模 (最近也不断听到业内有公司开始尝试多目标召回),而排序往往是多目标建模后融合排序,因此在整个打分导向上是存在不一致的;
    • 侧重点不一致:召回模块只要能召回 top item 即可,而排序需要对 item 做准确的排序;
  • 不一致会带来什么问题?
    • 某路召回的内容不被排序模块认可,一直展示不出去,而这种信息却没有让召回模型学到,导致这一路持续在召回但一直无法得到展示;
    • 被排序认可的内容却一直得不到召回;
“级联负例”通过从粗排或者精排排序靠后的样本里进行采样作为召回的负例。什么叫靠后,怎么进行采样,采样多少样本,也都是有讲究的,具体的做法往往根据优化场景的不同而不同,且需要大量的实验进行测试。目前业界的一些做法:
  • 百度 Mobius 的做法:用上一版本的召回模型筛选出"没那么相似"的 <user,doc>对,作为额外负样本,训练下一版本召回模型。
  • FB 的做法:与百度 Mobius 的做法相似,FB 的做法是:采用上一版模型召回位置在101~500上的item 作为 hard negative (负样本还是以 easy negative 为主,文章中经验值是 easy:hard = 100:1),参考
    🎯
    2022.11.16 再读 fb embedding-based 召回的老文章
值的提一句的是,如果你是从粗排和精排靠后的样本进行采样得到“级联负例”,那么不同 rank 位置的样本,采样概率理论上需要不一样,因为 rank 位置越靠后,是真正负样本的概率就越大,所以rank 位置越靠后,采样为“级联负例”的概率应该越大,才能使得不同位置的采样的犯错概率期望一样。在具体实践中,可以对展示内容的 rank 值分段进行统计,得到不同 rank 值分段的正样本率,然后,按这个正样本率的倒数 (归一化) 对这个分段进行采样,使得每个 rank 分段采样的犯错期望是一样的。比如:
粗排“级联负例”:粗排排序 500 < rank < 1000,按 10% 概率采样(假设这个段的正例率为 90%),rank > 1000 按 90% 概率采样(假设这个段的正例率为 10%),每次请求采样 10 个作为负例;精排“级联负例”:精排排序 50 < rank < 100,按 20% 概率采样,rank > 100 按 80% 概率采样,每次请求采样 2 个作为负例。粗排“级联负例”和精排“级联负例”的比例大致和粗排/精排条数一致即可。另外,在为某一路召回增加“级联负例”时,只用增加这一路召回被采样到的“级联负例”即可,其他召回路的“级联负例”大概率不会有什么效果,毕竟那是人家的错误。
关于所谓级联召回
正样本可以选择精排的 top n,负样本可以从进入粗排的里面随机挑,并搭配一些全局随机负例等等。具体的细节和效果全看具体场景炼丹的结果。

4.2 业务 hard 负例

以 airbnb 为例
  • 增加与正样本同城的房间作为负样本,增强了正负样本在地域上的相似性,加大模型学习难度;
  • 增加“被房主拒绝”作为负样本,增强了正负样本在“匹配用户兴趣爱好”上的相似性,加大模型学习难度
 
百度的文章:Sample Optimization For Display Advertising
算天算地系列
  • 推荐
  • 召回
  • 样本
  • 2021.12.01 读《中国为什么有前途》2021.01.09 怎么算投资回报率
    Catalog