【上】王树森《小红书推荐系统公开课》- 课程笔记(推荐系统基础、召回、排序)

写在前面

本文为王树森老师《小红书推荐系统公开课》的课程笔记

由于篇幅较长,分为【上】【下】两篇文章来记录。其中【上】包括推荐系统基础、召回、排序,【下】包括特征交叉、行为序列、重排、物品冷启动、涨指标的方法

【上】部分,内容导航如下: 


(一)推荐系统基础

1、推荐系统的基础概念

打开小红书APP,默认打开 “发现” 页面,展示推荐系统分发给你的内容,即用户自己创作的笔记,将它们展示给其他用户,形成陌生人社交的社区 

小红书推荐系统的转化流程

推荐系统决定给用户曝光什么内容,用户自己决定是否点击、滑动到底、...

抖音没有曝光和点击,用户下滑一次只能看到一个视频 

短期消费指标

反映出用户对推荐是否满意

  • 点击率 = 点击次数 / 曝光次数
    • 越高说明推荐越精准
    • 不能作为唯一优化目标(标题党)
  • 点赞率 = 点赞次数 / 点击次数
    • 收藏率转发率同理
  • 阅读完成率 = 滑动到底次数 / 点击次数 * 归一化函数(跟笔记长度有关)
    • 笔记越长,完成阅读的比例就越低
    • 若没有归一化函数,对长笔记会不公平

短期消费指标容易竭泽而渔,用户很快会失去兴趣,不再活跃。故还需关注多样性(用户没看过的话题),有助于提高用户黏性,留住用户,让用户更活跃

北极星指标

衡量推荐系统好坏最重要的指标,根本标准

  • 用户规模:日活用户数DAU(只要今天登录了一次小红书就增加了一次DAU)、月活用户数MAU(只要这个月登录了一次小红书就增加了一次MAU)
  • 消费:人均使用推荐的时长、人均阅读笔记的数量
    • 通常与点击率涨跌一致。若矛盾,应以北极星指标为准,如增加多样性,点击率不一定涨,但时长可能变多
  • 发布:发布渗透率、人均发布量
    • 激励作者发布通常是由冷启动来负责

实验流程

  • 做离线实验不需要把算法部署到产品中,没有跟用户实际交互,没有占用线上流量
  • 离线实验结果没有线上实验结果可靠(北极星指标都是线上指标,只能通过线上实验获得
  • AB测试:把用户随机分成实验组和对照组,实验组用新策略,对照组用旧策略,对比两者的业务指标,判断新策略是否会显著优于旧策略。若是,可以加大流量,最终推全

2、推荐系统的链路

推荐系统的目标是从物品的数据库中选出几十个物品展示给用户

召回(几亿->几千)

从物品的数据库中快速取回一些物品

几十条召回通道,每条召回通道取回几十~几百个物品,一共取回几千个物品作为候选集

  • 召回通道:协同过滤、双塔模型、关注的作者等
  • 融合、去重、过滤(排除掉用户不喜欢的作者、笔记、话题等)

让排序决定该把哪些物品曝光给用户,以及展示的顺序。为了解决计算量的问题,将排序分为粗排和精排(二者非常相似,但精排模型更大,用的特征更多)

粗排(几千->几百)

规模较小的机器学习模型给几千个物品逐一打分,按照分数做排序和截断,保留分数最高的几百个物品送入精排(也会用一些规则,保证进入精排的笔记具有多样性)

  • 排序分为粗排和精排,平衡计算量和准确性
  • 召回和粗排是最大的漏斗

精排(几百->几百)

大规模深度神经网络给几百个物品逐一打分,做排序和截断(截断可选)

  • 精排相比粗排用的特征更多,计算量更大,模型打分更可靠
  • 把多个预估值做融合(比如加权和)得到最终的分数,分数决定会不会展示给用户,以及展示的位置

重排(几百->几十)

根据精排分数和多样性分数做随机抽样,得到几十个物品。用规则把相似内容打散,并插入广告和运营推广内容,根据生态要求调整排序,即为最终展示给用户的结果

  • 重排主要是做多样性抽样(如MMR、DPP)、规则打散、插入广告和运营内容
    • 做多样性抽样(比如MMR、DPP),从几百个物品中选出几十个
    • 用规则打散相似物品
    • 插入广告、运营推广内容,根据生态要求调整排序

整条链路上,召回和粗排是最大的漏斗(候选物品从几亿->几千->几百) 

3、AB测试

目的:

  • 离线实验的指标有提升,不代表线上实验也会有收益。判断新策略能带来多大的业务指标收益
  • 模型中有一些参数,需要用AB测试选取最优参数,如GNN网络的深度可以是1/2/3层

离线实验结果正向,下一步是做线上的小流量AB测试(一般10%用户)

随机分桶

若用户数量足够大,每个桶的DAU/留存/点击率等指标都是相等的

例:召回团队实现了一种GNN召回通道,离线实验结果正向。下一步是做线上的小流量A/B测试,考虑新的召回通道对线上指标的影响。模型中有一些参数,比如GNN的深度取值∈{1, 2, 3},需要用A/B测试选取最优参数

  • 1~3桶的GNN深度分别为1~3层,4号桶没有用GNN做召回
  • 计算每个桶的业务指标,比如DAU、人均使用推荐的时长、点击率等
  • 如果某个实验组指标显著优于对照组,则说明对应的策略有效,如2桶的业务指标与对照组的diff有显著性,说明2层的GNN召回通道是有效果的,值得推全(把流量扩大到100%,给所有用户都使用2层GNN召回通道)

分层实验

目标:解决流量不够用的问题

  • 信息流产品的公司有很多部门和团队,都需要做AB测试
    • 推荐系统(召回、粗排、精排、重排)
    • 用户界面
    • 广告
  • 如果把用户随机分成10组,1组做对照,9组做实验,那么只能同时做9组实验,无法满足产品迭代需求

分层实验:召回、粗排、精排、重排、用户界面、广告...(例如GNN召回通道属于召回层)

  • 同层互斥:GNN实验占了召回层的4个桶,其他召回实验只能用剩余的6个桶
    • 两个召回实验不会同时作用到同一个用户上
    • 避免一个用户同时被两个召回实验影响,若两个实验相互干扰,实验结果将变得不可控
  • 不同层正交:每一层独立随机对用户做分桶,每一层都可以独立用100%的用户做实验
    • 一个用户可以同时受一个召回实验和一个精排实验的影响,因为它们的效果不容易相互增强或抵消

互斥 vs 正交:

  • 如果所有实验都正交,则可以同时做无数组实验
  • 同类的策略(例如精排模型的两种结构)天然互斥,对于一个用户,只能用其中一种
  • 同类的策略(例如添加两条召回通道)效果会相互增强或相互抵消。互斥可以避免同类策略相互干扰
  • 不同类型的策略(例如添加召回通道、优化粗排模型)通常不会相互干扰,可以作为正交的两层

Holdout机制

  • 每个实验(召回、粗排、精排、重排)独立汇报对业务指标的提升
  • 公司考察一个部门(比如推荐系统)在一段时间内对业务指标总体的提升
  • 取10%的用户作为holdout桶(对照组),推荐系统使用剩余90%的用户做实验,两者互斥
  • 10% holdout桶 vs 90% 实验桶的diff(需要对指标做归一化)为整个部门的业务指标收益

  • 每个考核周期结束之后,清除holdout桶,让推全实验从90%用户扩大到100%用户
  • 重新随机划分用户,得到holdout桶和实验桶,开始下一轮考核周期
  • 新的holdout桶与实验桶各种业务指标的diff接近0
  • 随着召回、粗排、精排、重排实验上线和推全,diff会逐渐扩大 

实验推全

若业务指标的diff显著正向,则可以推全实验。如重排策略实验,取一个桶作为实验组,一个桶作为对照组,实验影响了20%用户,若观测到显著正向的业务收益,则可以推全

  • 把重排层实验关掉,把两个桶空出来给其他实验
  • 推全时新开一层,新策略会影响全部90%用户
  • 在小流量阶段,新策略会影响10%用户,会微弱提升实验桶和hold桶的diff
  • 推全后,新策略作用到90%用户上,diff会扩大9倍
  • 如ab测试发现新策略会提升点击率9个万分点,小流量实验只作用10%用户上,所以只能把跟holdout桶的diff提升1个万分点,推全后,理论上可以把diff提升到9个万分点,跟ab实验得到的结果一致

反转实验 

  • 有的指标(如点击、交互)立刻受到新策略影响,有的指标(留存)有滞后性,需要长期观测
  • 实验观测到显著收益后需要尽快推全新策略。目的是腾出桶供其他实验开展,或需要基于新策略做后续的开发
  • 用反转实验解决上述矛盾,既可以尽快推全,也可以长期观测实验指标
  • 在推全的新层中开一个旧策略的桶,可以把反转桶保留很久,长期观测实验指标
  • 一个考核周期结束之后,会清除holdout桶,会把推全新策略用到holdout用户上,不影响反转桶;当反转实验完成时,新策略会用到反转桶用户上,实验真正推全,对所有用户生效

  • 分层实验:同层互斥(不允许两个实验同时影响同一位用户)、不同层正交(实验有重叠的用户)
  • Holdout:保留10%的用户完全不受实验影响,可以考虑整个部门对业务指标的贡献
  • 实验推全:扩大到90%流量上,新建一个推全层,与其它层正交
  • 反转实验:为了在尽早推全新策略的同时还能长期观测各种指标,在新的推全层上,保留一个小的反转桶,反转桶使用旧策略。反转桶可以保留很久,长期观测新旧策略的diff

(二)召回

1、基于物品的协同过滤(ItemCF)

ItemCF的原理

我喜欢看《笑傲江湖》,《笑傲江湖》与《鹿鼎记》相似,我没看过《鹿鼎记》——> 给我推荐《鹿鼎记》

推荐系统如何知道《笑傲江湖》与《鹿鼎记》相似?

  • 基于知识图谱:
    • 两本书的作者相同,故两本书相似
  • 基于全体用户的行为:
    • 看过《笑傲江湖》的用户也看过《鹿鼎记》
    • 给《笑傲江湖》好评的用户也给《鹿鼎记》好评

ItemCF的实现

假设点击、点赞、收藏、转发四种行为各1分

算出来=3.2

逐一计算用户对候选物品的兴趣分数,返回分数高的topn个物品

物品相似度

两个物品的受众重合度越高,两个物品越相似

  • 例如,喜欢《射雕英雄传》和《神雕侠侣》的读者重合度很高,可以认为它们相似
相似度介于0~1,数值越大表示两个物品越相似

上述公式只要是喜欢就看作1,不喜欢就看作0,没有考虑用户喜欢的程度

集合v这部分用户占比越大,两个物品的相似度就越高 

考虑用户喜欢的程度,如点击、点赞、收藏、转发各自算1分,用户对物品的喜欢程度最多是4分

  • 分子表示同时喜欢两个物品的用户v(如果兴趣分数的取值是0或1,那么分子就是同时喜欢两个物品的人数)
  • 分母第一项表示用户对物品i1的兴趣分数,关于所有用户求连加,然后开根号
  • 把一个物品表示成一个向量,向量每个元素表示一个用户,元素的值就是用户对物品的兴趣分数,两个向量的夹角的余弦就是这个公式
相似度介于0~1

ItemCF的基本思想:根据物品的相似度做推荐

  • 如果用户喜欢物品Item1,而且物品Item1和Item2相似
  • 那么用户很可能喜欢物品Item2

预估用户对候选物品的兴趣:

计算两个物品的相似度:

  • 把每个物品表示为一个稀疏向量,向量每个元素对应一个用户
  • 相似度sim就是两个向量夹角的余弦

ItemCF召回的完整流程

为了能在线上实时推荐,必须要事先做离线计算,建立两个索引

事先做离线计算

建立 “用户->物品” 的索引

  • 记录每个用户最近点击、交互过的物品ID
  • 给定任意用户ID,可以找到他近期感兴趣的物品列表

建立 “物品->物品” 的索引

  • 计算物品之间两两相似度
  • 对于每个物品,索引它最相似的k个物品
  • 给定任意物品ID,可以快速找到它最相似的k个物品

线上做召回
  1. 给定用户ID,通过 “用户->物品” 的索引,找到用户近期感兴趣的物品列表(last-n)
  2. 对于last-n列表中每个物品,通过“物品->物品” 的索引,找到top-k相似物品
  3. 对于取回的相似物品(最多有nk个),用公式预估用户对物品的兴趣分数
  4. 返回分数最高的100个物品,作为推荐结果(即ItemCF召回通道的输出,会跟其他召回通道的输出融合起来并排序,最终展示给用户)

索引的意义在于避免枚举所有的物品

  1. 记录用户最近感兴趣的n=200个物品
  2. 取回每个物品最相似的k=10个物品
  3. 给取回的nk=2000个物品打分(用户对物品的兴趣)
  4. 返回分数最高的100个物品作为ItemCF通道的输出

用索引,离线计算量大(需要更新2个索引),线上计算量小(不需访问上亿个物品)

如果取回的物品ID有重复的,就去重,并把分数加起来

ItemCF的原理:

  • 用户喜欢物品i1,那么用户喜欢与物品i1相似的物品i2
  • 物品相似度:
    • 不是根据物品的内容判定物品相似,而是根据用户行为
    • 如果喜欢i1、i2的用户有很大的重叠,那么i1与i2相似

ItemCF召回通道:

  • 维护两个索引:
    • 用户->物品列表:用户最近交互过的n个物品
    • 物品->物品列表:相似度最高的k个物品
  • 线上做召回:
    • 利用两个索引,每次取回nk个物品
    • 预估用户对每个物品的兴趣分数:
    • 返回分数最高的100个物品,作为召回结果

2、Swing召回通道(ItemCF的变种) 

与ItemCF非常像,区别就是如何定义物品的相似度

ItemCF: 

ItemCF的问题:两篇笔记受众不同,但由于被分享到一个小圈子,导致很多用户同时交互过这两篇笔记。需要降低小圈子用户的权重

Swing模型即给用户设置权重,解决小圈子问题

α是个人工设置的参数;overlap为u1和u2的重叠,重叠大说明两个人是一个小圈子,对相似度的贡献应减小

Swing与ItemCF唯一的区别在于物品相似度

  • ItemCF:两个物品重合的用户比例高,则判定两个物品相似
  • Swing:额外考虑重合的用户是否来自一个小圈子
    • 同时喜欢两个物品的用户记作集合v
    • 对于v中的用户u1和u2,重合度记作overlap(u1, u2)
    • 两个用户重合度大,则可能来自一个小圈子,权重降低

3、基于用户的协同过滤(UserCF)

UserCF原理

有很多跟我兴趣非常相似的网友,其中某个网友对某笔记点赞、转发,而我没看过这篇笔记,那么可能给我推荐这篇笔记

推荐系统如何找到跟我兴趣非常相似的网友呢?

  • 点击、点赞、收藏、转发的笔记有很大的重合
  • 关注的作者有很大的重合

UserCF实现

0代表用户没有看过物品,或对物品不感兴趣

计算出=2.8

用户相似度

用户有共同的兴趣点,即喜欢的物品有重合

介于0-1,越接近1表示两个用户越相似

上述公式同等对待热门和冷门的物品,需降低热门物品的权重

物品越热门,n_l 越大,分子(即物品的权重)越小 

UserCF的基本思想:

  • 如果用户user1跟用户user2相似,而且user2喜欢某物品,那么用户user1也很可能喜欢该物品

预估用户user对候选物品item的兴趣:

计算两个用户的相似度:

  • 把每个用户表示为一个稀疏向量,向量每个元素对应一个物品
  • 如果用户对物品不感兴趣,向量元素为0;若感兴趣,元素为1,或1除以物品的热门程度
### 关于王树森深度强化学习代码实现 在深入探讨王树森教授有关深度强化学习的工作时,可以发现其研究重点在于通过行为克隆(Behavior Cloning)初始化策略网络之后,利用强化学习进一步优化该策略网络,使其能够更有效地执行特定任务[^2]。 下面是一个简化版的Python代码示例,展示了如何基于PyTorch框架构建并训练一个简单的神经网络模型来表示策略函数π(a|s),即给定状态s下采取行动a的概率分布: ```python import torch from torch import nn, optim import numpy as np class PolicyNet(nn.Module): def __init__(self, input_dim, hidden_dims, output_dim): super(PolicyNet, self).__init__() layers = [] last_dim = input_dim for dim in hidden_dims: layers.append(nn.Linear(last_dim, dim)) layers.append(nn.ReLU()) last_dim = dim layers.append(nn.Linear(last_dim, output_dim)) layers.append(nn.Softmax(dim=-1)) self.model = nn.Sequential(*layers) def forward(self, x): return self.model(x) def select_action(policy_net, state): state_tensor = torch.from_numpy(state).float().unsqueeze(0) probs = policy_net(state_tensor) m = torch.distributions.Categorical(probs) action = m.sample() return action.item(), m.log_prob(action) env_name = 'CartPole-v1' input_size = 4 hidden_sizes = [128] output_size = 2 policy_network = PolicyNet(input_size, hidden_sizes, output_size) optimizer = optim.Adam(policy_network.parameters(), lr=1e-3) for episode in range(100): total_reward = 0 log_probs = [] observation = env.reset() while True: chosen_action, log_prob = select_action(policy_network, observation) next_observation, reward, done, _ = env.step(chosen_action) total_reward += reward log_probs.append(log_prob) if done: break observation = next_observation optimizer.zero_grad() loss = -sum(log_probs) * (total_reward / sum([r != 0 for r in rewards])) loss.backward() optimizer.step() print(f'Episode {episode}: Total Reward={total_reward}') ``` 上述代码实现了基本的策略梯度算法,在每次迭代过程中收集轨迹数据,并据此更新参数以最大化预期回报。需要注意的是这只是一个非常基础的例子,实际应用中可能还需要考虑更多因素如奖励折扣、基线减法等技术细节。
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Cheer-ego

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值