【王树森推荐系统公开课】笔记07(双塔模型:正负样本、双塔模型:线上召回和更新)
正样本:曝光而且有点击。简单负样本全体物品。batch内负样本。困难负样本:被召回,但是被排序淘汰。错误:曝光、但是未点击的物品做召回的负样本。离线存储:把物品向量b存入向量数据库。完成训练之后,用物品塔计算每个物品的特征向量b。把几亿个物品向量b存入向量数据库(比如 Milvus、Faiss、HnswLib向量数据库建索引,以便加速最近邻查找。线上召回:查找用户最感兴趣的 k 个物品。给定用户
1 双塔模型:正负样本
1.1 正样本
-
正样本:曝光而且有点击的用户—物品二元组。(用户对物品感兴趣)。
-
问题:少部分物品占据大部分点击,导致正样本大多是热门物品。
-
解决方案:过采样冷门物品,或降采样热门物品。
-
过采样(up-sampling):一个样本出现多次。
-
降采样(down-sampling):一些样本被抛弃。
-
1.2 如何选择负样本?
简单负样本:全体物品
-
未被召回的物品,大概率是用户不感兴趣的。
-
未被召回的物品 ≈ 全体物品
几亿个物品里边只有几千个被召回,也就是说几乎所有的物品都没有被召回。
-
从全体物品中做抽样,作为负样本。
-
均匀抽样 or 非均匀抽样?
均匀抽样:对冷门物品不公平
-
正样本大多是热门物品。
-
如果均匀抽样产生负样本,负样本大多是冷门物品。
非均匀抽样:目的是打压热门物品
-
负样本抽样概率与热门程度(点击次数)正相关。
-
。
简单负样本:Batch 内负样本
正样本
负样本
-
一个 batch 内有 n 个正样本。
-
一个用户和 n−1 个物品组成负样本。
-
这个 batch 内一共有
个负样本。
-
都是简单负样本。(因为第一个用户不喜欢第二个物品。)
Batch 内负样本存在一个问题
-
一个物品出现在 batch 内的概率 ∝ 点击次数。
-
物品成为负样本的概率本该是 ∝ (点击次数)^0.75,但在这里是 ∝ 点击次数。
-
热门物品成为负样本的概率过大。
一个物品成为负样本的概率越大,模型对这个物品打压就越狠。
对负样本应该打压,但这里打压的太狠了,这样会造成偏差。
参考文献:
Xinyang Yi et al. Sampling-Bias-Corrected Neural Modeling for Large Corpus Item Recommendations. In RecSys, 2019.
该文献讲了如何修正偏差
如何修正偏差
- 物品
被抽样到的概率:
∝ 点击次数
- 预估用户对物品
的兴趣:
- 做训练的时候,调整为:
这样可以纠偏,避免过分打压热门物品。
训练结束之后,在线上做召回的时候,还是用原本的余弦相似度
,线上召回的时候不用做这种调整
困难负样本
-
困难负样本:
-
被粗排淘汰的物品(比较困难)。
-
精排分数靠后的物品(非常困难)。
-
-
对正负样本做二元分类:
-
全体物品(简单)分类准确率高。
-
被粗排淘汰的物品(比较困难)容易分错。
-
精排分数靠后的物品(非常困难)更容易分错。
-
训练数据
-
混合几种负样本。
-
50%的负样本是全体物品(简单负样本)。
-
50%的负样本是没通过排序的物品(困难负样本)。
常见的错误
很多人以为可以把曝光但是没有点击的物品作为负样本,其实这是错误的。
1.3 选择负样本的原理
召回的目标:快速找到用户可能感兴趣的物品。
-
全体物品(easy):绝大多数是用户根本不感兴趣的。
-
被排序淘汰(hard):用户可能感兴趣,但是不够感兴趣。
-
有曝光没点击(没用):用户感兴趣,可能碰巧没有点击。
有曝光没点击可以作为排序的负样本,不能作为召回的负样本。
这是工业界的共识,是通过反复做实验得出的结果。
1.4 总结
-
正样本:曝光而且有点击。
-
简单负样本:
-
全体物品。
-
batch内负样本。
-
-
困难负样本:被召回,但是被排序淘汰。
-
错误:曝光、但是未点击的物品做召回的负样本。
2 双塔模型:线上召回和更新
2.1 线上召回
离线存储
在训练好模型之后,开始线上服务之前,先用右边的物品塔提取物品的特征。
向量数据库存储特征向量和物品ID的二元组,用作最近邻查找。
线上召回
用户塔不要事先计算和存储向量,而是当用户发起推荐请求的时候,调用神经网络在线上现算一个特征向量 ,然后把向量
作为 query,去数据库中做检索查找最近邻。
总结:双塔模型的召回
-
离线存储:把物品向量 b 存入向量数据库。
-
完成训练之后,用物品塔计算每个物品的特征向量 b。
-
把几亿个物品向量 b 存入向量数据库(比如 Milvus、Faiss、HnswLib)。
-
向量数据库建索引,以便加速最近邻查找。
-
-
线上召回:查找用户最感兴趣的 k 个物品。
-
给定用户 ID 和画像,线上用神经网络算用户向量 a。
-
最近邻查找:
-
把向量 a 作为 query,调用向量数据库做最近邻查找。
-
返回余弦相似度最大的 k 个物品,作为召回结果。
-
-
接下来这些物品会跟 ItemCF、Swing、UserCF 等召回通道的结果融合,然后经过排序,最终展示给用户。
思考
事先存储物品向量 b,线上现算用户向量 a,why?
-
每做一次召回,用到一个用户向量 a,几亿物品向量 b。(线上算物品向量的代价过大。)
-
用户兴趣动态变化,而物品特征相对稳定。(可以离线存储用户向量,但不利于推荐效果。)
2.2 模型更新
全量更新
全量更新:在每天今天凌晨,用前一天的数据训练模型。
-
在昨天模型参数的基础上做训练。(不是随机初始化)
-
用昨天的数据,训练 1 epoch,即每天数据只用一遍。
-
发布新的用户塔神经网络和物品向量,供线上召回使用。
-
全量更新对数据流、系统的要求比较低。
全量更新不需要实时的数据流,对生成训练数据的速度没有要求,延迟一两个小时也没有关系。
全量更新对系统的要求也很低,每天做一次全量更新,所以只需要把神经网络和物品向量每天发布一次就够了
增量更新
增量更新:做 online learning 更新模型参数。
-
用户兴趣会随时发生变化。
-
实时收集线上数据,做流式处理,生成 TFRecord 文件。
-
对模型做 online learning,增量更新 ID Embedding 参数。(不更新神经网络其他部分的参数。)
-
发布用户 ID Embedding,供用户塔在线计算用户向量。
只有在做全量更新的时候才会更新全连接层的参数。
全量更新 vs 增量更新
问题:能否只做增量更新,不做全量更新?
只做增量更新当然要比既做全量又做增量简单,工程实现会更容易,训练消耗的机器资源也会更少。
实验后发现只做增量效果不好,最好还是既做全量又做增量。
效果不好的原因:
-
小时级数据有偏;分钟级数据偏差更大。
-
全量更新:random shuffle 一天的数据,做 1 epoch 训练。
-
增量更新:按照数据从早到晚的顺序,做 1 epoch 训练。
-
随机打乱优于按顺序排列数据,全量训练优于增量训练。
做全量训练的时候,要随机排列数据,也就是 random shuffle,这样是为了消除偏差。
3 总结
双塔模型
-
用户塔、物品塔各输出一个向量,两个向量的余弦相似度作为兴趣的预估值。
-
三种训练的方式:pointwise、pairwise、listwise。
-
正样本:用户点击过的物品。
-
负样本:全体物品(简单)、被排序淘汰的物品(困难)。
召回
-
做完训练,把物品向量存储到向量数据库,供线上最近邻查找。
-
线上召回时,给定用户 ID、用户画像,调用用户塔现算用户向量 a。
-
把 a 作为 query,查询向量数据库,找到余弦相似度最高的 k 个物品向量,返回 k 个物品 ID。
更新模型
-
全量更新:今天凌晨,用昨天的数据训练整个神经网络,做 1 epoch 的随机梯度下降。
-
增量更新:用实时数据训练神经网络,只更新 ID Embedding,锁住全连接层。
-
实际的系统:
-
全量更新 & 增量更新相结合。
-
每隔几十分钟,发布最新的用户 ID Embedding,供用户塔在线计算用户向量(这样的好处是,可以捕捉到用户最新的兴趣点)。
-
更多推荐
所有评论(0)