关于前端:Flink-强化学习搭建实时推荐系统

3次阅读

共计 8261 个字符,预计需要花费 21 分钟才能阅读完成。

简介: 如何依据用户反馈作出疾速及时的实时举荐?

现在的举荐零碎,对于实时性的要求越来越高,实时举荐的流程大抵能够概括为:举荐零碎对于用户的申请产生举荐,用户对举荐后果作出反馈 (购买 / 点击 / 来到等等),举荐零碎再依据用户反馈作出新的举荐。这个过程中有两个值得关注的中央:

  • 这可被视为是一个举荐零碎和用户一直交互、相互影响的过程。
  • 举荐零碎须要对用户反馈作出疾速及时的响应。

这两点本篇别离通过强化学习和 Flink 来实现,而在此之前先理解一些背景概念。

强化学习

强化学习畛域的出名教材《Reinforcement Learning: An Introduction》开篇就写道:

当咱们思考学习的实质的时候,脑中首先联想到的可能就是在与环境一直交互中学习。当一个婴儿在游玩、挥动手臂或是旁顾周围时,并没有任何老师教它,但它的确能间接感知到周围环境的变动。

强化学习的次要过程是构建一个智能体,使之在与环境交互的过程中一直学习,以期取得最大的冀望处分。它是一种十分通用的学习范式,能够用于对各种各样问题的建模,比方游戏、机器人、主动驾驶、人机交互、举荐、衰弱护理等等。其与监督学习的次要不同点在于:强化学习依据提早的反馈通过一直试错 (trial-and-error) 进行学习,而监督学习则是每一步都有明确的反馈信息进行学习。

下图反映了一个举荐智能体 (recommender agent) 与环境进行互动的过程。这里将用户 (user) 视为环境,用户的行为数据作为状态 (state) 输出到智能体中,智能体据此作出相应的动作 (action),即举荐相应的物品给用户,用户对此举荐的反馈如点击 / 不点击、购买 / 不购买等可视为新一轮的处分。从这里能够看出,举荐可被认为是一个动静序列决策过程,举荐物品对用户产生影响,进而用户的反馈反过来影响举荐零碎的决策自身,这样的过程会一直延续下去造成一个序列。

“决策”这个词实际上很能代表强化学习自身的特点。构想当一个人在做决策的时候,很多时候须要对瞬息万变的局势进行评估并疾速作出相应的抉择,而另一方面,作出的决定须要思考长期的指标而非仅仅是短期收益。而这两点恰好是简直所有用强化学习做举荐零碎的论文中都会提到的对于传统举荐办法的问题,行将举荐视为动态预测的过程以及只重视短期收益等等。当然论文里这么说次要是为了凸显本人的成绩,但理论的状况应该远不是这么简略。

强化学习的最终目标是学习出一个策略 ????(????|????) 来最大化冀望处分。策略 (policy) 指的是智能体如何依据环境状态 ???? 来决定下一步的动作 ????,对应到举荐的场景中就是依据用户过往行为记录来决定下一步举荐的物品。

对于如何通过训练失去最优策略,目前支流有两类办法: on-policy 和 off-policy。不同于监督学习的须要事后人工收集数据并标注,强化学习的数据来源于一直地与环境进行互动,继而用收集来的数据更新模型。所以在这个过程中有两个局部与策略相干,一是与环境互动时须要应用策略,二是训练时更新策略。On-policy 指的是环境互动的策略和训练时更新的策略是同一个策略,相应地 off-policy 则是互动和更新时应用的是不同的策略。如下左图为 on-policy,下中图为 off-policy (下右图为 offline 办法,后文再述)。

On-policy 的思维比拟直观,相当于一个智能体在环境中边试错边学习,然而其次要问题是样本利用率低,进而训练效率低。应用了一个策略与环境进行交互获得数据进而更新模型后,就产生了一个新的策略,那么旧策略交互得来的数据可能就不遵从新策略的条件散布了,所以这些数据不能再应用会被抛弃。

Off-policy 则缓解了这个问题,次要通过将之前策略收集来的数据通过一个教训回放池 (experience replay buffer) 储存起来,而后从中采样数据进行训练。那么 off-policy 类办法为什么能应用旧策略产生的数据进行训练?既然数据分布不同导致新旧数据不能放一起训练,那就调整数据分布使之靠近就能够了,所以 Off-policy 类的算法广泛采纳了重要性采样的思维对不同数据施加不同的权重,后文介绍 YouTube 的举荐零碎时会提到,到那时再说。

那么本篇的强化学习办法实用于哪一种呢?这其实不大好说。我没有能互动的环境,只有静态数据集,所以 off-Policy 看上去更适宜一些,但即便是 off-policy 的办法通常也须要与环境进行交互一直产生新数据用于训练。因而本篇的办法属于 batch reinforcement learning,或称 offline reinforcement learning,不过我偏向于应用 batch 这个词,因为 offline 和 off-policy 很容易混同。上右图显示的就是 batch (offline) reinforcement learning,其特点是一次性收集完一批数据后就只用这批数据进行训练,在正式部署之前不再与环境作任何交互。

咱们晓得深度学习近年来在图像和 NLP 畛域获得了很大的停顿,一大起因是算力和数据的爆炸式增长。然而对于支流的深度强化学习算法来说,须要一直与环境进行交互来获取数据,这通常意味着须要边训练边收集数据。许多畛域是无奈像传统强化学习那样有条件频繁与环境进行交互的,存在老本太高或者安全性太低的起因,甚至会引发伦理问题,典型的例子如无人驾驶和医疗。

所以这时候人们天然会去想,训练强化学习时也收集一堆固定的数据,而后一直反复利用,不再收集新的,仿照深度学习那样在固定数据集上鼎力出奇观,这样是否可行呢?因而 batch reinforcement learning 近年来受到越来越多学术界和工业界的关注,被宽泛认为是实现强化学习大规模利用到理论的一个有效途径。而举荐零碎就很适宜这种模式,因为间接线上摸索交互代价太大,影响用户体验,但收集用户行为日志却绝对容易且数据量大。

Flink

另一方面,举荐零碎作为一个零碎,光有算法必定是不行的。上文提到 batch reinforcement learning 无需与环境互动,仅靠数据集就能训练,那么在训练完模型真正上线当前就须要与环境交互了,而这个过程中须要有两头载体,用于疾速取得信息、荡涤原始数据并转化成模型可输出的格局。在本篇中这个前道工序咱们次要应用 Flink。Flink 官网上的自我介绍是”数据流上的有状态计算 (Stateful Computations over Data Streams)“:

换言之随着数据的一直流入,其能够保留和拜访之前的数据和两头后果,当达到特定的条件后一并计算。对于咱们的强化学习模型来说,须要累计肯定的用户行为能力作为模型输出作举荐,所以须要在 Flink 中实时保留之前的行为数据,这就要用到 Flink 弱小的状态治理性能。

另外,离线训练应用的深度学习框架是 PyTorch,这个不像 Tensorflow 那样部署不便,所以这里采纳近年来风行的 FastAPI 做成 api 服务,在 Flink 中获取满足条件的特色后间接调用服务进行推理,产生举荐后存到数据库中,服务器在下次用户申请时可间接从数据库中调用举荐后果。整体架构见下图,残缺代码和流程见:

FlinkRL:
https://github.com/massquantity/flink-reinforcement-learning
DBRL:https://github.com/massquantity/DBRL

上面介绍应用的三种算法,限于篇幅,这里仅仅大抵介绍原理,欲了解细节可参阅原论文。上面是次要符号表:

YouTube Top-K (REINFORCE)

这个办法次要参考 YouTube 2018 年发表的论文 Top-K Off-Policy Correction for a REINFORCE Recommender System。论文作者在这个视频中声称这个办法获得了近两年来的最大增长,说实话我是有点狐疑的。在论文最初的试验局部提到,这个强化学习模型只是作为泛滥召回模型之一,而后所有的召回物品再通过一个独立的排序模块后举荐给用户,文中也没说这个排序模块用的是什么模型,所以这外面的空间就比拟大了。

论文中应用了 policy gradient 畛域最古老的 REINFORCE 算法,并就其具体业务情景做了一些改变,这里咱们先看 REINFORCE 的根本框架。

假设执行的是随机策略,智能体在环境中互动产生的一个轨迹为 ????=(????0,????0,????1,????1,????1,⋯,????????−1,????????−1,????????,????????)。在深度强化学习中个别应用神经网络来参数化策略 ????,个别会在环境中采样多个轨迹,那么该策略的冀望总回报为:

其中 ???? 是神经网络的参数,????(????) 为轨迹 ???? 的总回报,因为轨迹带有随机性,所以咱们心愿最大化冀望回报来取得最优的策略 ????∗:

REINFORCE 的思维,或者说整个 policy gradient 的思维,和监督学习中的很多算法必由之路,即通过梯度回升 (降落) 法求参数 ????,把 (1.1) 式当成指标函数,那么一旦有了梯度,就能够用这个相熟的式子进行优化了:

间接求 ????(????????) 的梯度异样艰难,然而通过 policy gradient 定理,咱们能够失去一个近似解:

其中 ????????=∑|????|????′=????????????′−????????(????????′,????????′),意为 ???? 时刻采取的动作取得的最终回报只与之后取得的处分无关,而与之前的处分无关。对于 policy gradient 定理的证实见附录 A。

原始的 REINFORCE 算法是 on-policy 的,亦即线上交互和理论优化的是同一个策略,然而论文中说他们线上交互的是不同的策略,甚至是多种不同策略的混合体。这样就导致了数据分布不统一,如果间接应用 REINFORCE 会产生微小的 bias。论文中通过重要性采样把算法革新成 off-policy 的:

为理论的交互策略,这个式子的推导也能够间接通过 policy gradient 得出,具体见附录 B。接下来通过一系列的衡量,作者认为上面这个式子比拟正当地均衡了偏差与方差:

次要的不同就是采样是沿着 ???? 的轨迹进行,并在每一步 ???? 中加了重要性权重 ????????(????????|????????)????(????????|????????),而这个权重绝对很容易计算。

论文中思考的另外一个问题是,之前都是思考的动作只有一个,即只举荐一个物品,但事实中往往是一次性举荐 ???? 个物品给用户,如果 ???? 个物品同时思考就会组合爆炸。论文中假如同时展现 ???? 个不反复物品的总处分等于每个物品的处分之和,这样就能够转化为单个物品的优化,同时作者说这个假如成立的前提是用户对举荐列表中每个物品的察看是独立的。

YouTube 在 2019 年发表过另外一篇用强化学习做举荐的论文 (Reinforcement Learning for Slate-based Recommender Systems: A Tractable Decomposition and Practical Methodology),和 2018 年中的办法相比,次要的不同是应用了 on-policy 的 SARSA 算法,而且是用在了排序而不是召回阶段。

这篇论文中同样对举荐的 ???? 个物品作了某种假如:假如一个举荐列表中用户只会生产其中一个物品,如果用户生产完后又返回到这个举荐列表生产第二个物品,则这个行为会被视为另外的事件,在日志中离开记录。实际上这两个假如的实质就在于用户面对 ???? 个物品的列表只会关注其中一个而不论其余,然而理论很多时候用户会对多个感兴趣,然而生产完一个后就把残余几个忘了。极其状况是举荐了 10 个全副都感兴趣,生产了一个后有些事来到了或者陷入一直点击循环生产,这样原来的另外 9 个感兴趣的就都被当成负样本解决了。

到这里咱们能够看到,两篇论文都必须作出一些假如的根本原因在于应用的算法输入的都是离散型动作,即单个物品,然而举荐的场景不像个别的强化学习利用只须要输入一个动作就行了。所以不得不作出一些看上去很顺当的假如,而前面介绍的两个算法输入的都是连续型动作,则会有另外的解决办法。

接下来仍然沿着下面的假如走,???? 个就转化为单个物品了,联合重要性权重后,(1.3) 式可转化为:

式中次要是用 ????????(????????|????????) 代替了原来的 ????????(????????|????????),因为 ???? 个物品是各自独立从策略 ???????? 中采样的,则 ????????(????????|????????)=1−(1−????????(????????|????????))???? 示意 ???? 时刻物品 ???? 呈现在最终的 ???? 个物品的列表中的概率,因为 (1−????????(????????|????????))???? 示意 ???? 次都没有被采样到的概率。

能够看到 (1.3) 式和 (1.4) 式的惟一差异是多了一个乘子 : ∂????(????????|????????)∂????(????????|????????)=????(1−????????(????????|????????))????−1。因而咱们只有采样一个轨迹,在每一步 ???? 由神经网络计算出 ????????(????|????),????(????|????) (这两个理论就是 softmax 输入的概率),再整合计算折扣回报 ????????=∑|????|????′=????????????′−????????(????????′,????????′) 后,就能相应地实现算法了,最终的代码见:

https://github.com/massquantity/DBRL/blob/master/dbrl/models/youtube_topk.py

DDPG

就举荐的场景来说,离散型动作是比拟天然的想法,每个动作就对应每个物品。然而事实中物品数量可能至多有百万级,意味着动作空间很大,用 softmax 计算复杂度很高。下面 YouTube 的论文中应用 sampled softmax 来缓解这个问题,而这里咱们能够换个思路,让策略输入一个间断的向量 ????∈ℝ????,再将 ???? 与每个物品的 embedding 点乘再排序来取得举荐列表,在线上则能够应用高效的最近邻搜寻来获取相应物品。对于连续型动作而言,DDPG 是比拟通用的抉择,在我看过的举荐相干的论文里应用 DDPG 是最多的,比方京东的两篇 1,阿里的一篇[1],华为的一篇[1]。

DDPG 全称 Deep Deterministic Policy Gradient,是一种实用于连续型动作的 off-policy 算法。不同于上文的 REINFORCE,其应用的是确定性策略,顾名思义对于雷同的状态 ???? 会产生惟一的动作 ????,所以这里咱们用 ????(????) 来示意。而因为是确定性策略,不存在动作 ???? 的概率分布,也就不须要重要性采样了。

DDPG 采纳 Actor-Critic 框架,Actor 为具体的策略,其输出为状态 ????,输入动作 ????。Critic 用于评估策略的好坏,其输出为 (????+????) 拼接而成的向量,输入为一个标量。Actor 和 Critic 都能够用神经网络来参数化,假如 Actor 网络为 ????(????|????????),Critic 网络为 ????(????,????|????????),则 Actor 和 Critic 的指标函数和梯度别离为:

那么算法的外围就是通过梯度回升 (降落) 优化这两个指标函数来求得最终的参数,进而失去最优策略。DDPG 其余的一些实现细节如 target network、soft update 等等这里不再赘述,因为咱们应用的是固定的数据集,因此只有将数据转化成 DDPG 算法能够输出的格局,再像监督学习那样分 batch 训练就行了,不必再与环境作交互,最终的代码见:

https://github.com/massquantity/DBRL/blob/master/dbrl/models/ddpg.py

BCQ

BCQ 算法全称 Batch-Constrained Deep Q-Learning,出自论文 Off-Policy Deep Reinforcement Learning without Exploration。BCQ 能够看作是对 DDPG 在 batch (offline) 场景的革新版本,如前文所述,batch (offline) reinforcement learning 指的是在固定的数据集上进行学习,不再与环境进行交互。论文作者指出在这种条件下以后风行的的 off-policy 算法如 DQN、DDPG 等可能成果不会很好,起因次要出在会产生 extrapolation error。

Extrapolation error 次要源于数据集中状态 ???? 和动作 ???? 组合的散布和以后策略中状态 - 动作组合散布的不统一,即采样的策略和以后策略差异很大,从而使得 Critic 对于值函数的预计不准,进而使得学习生效。以上文中 DDPG 的 Critic 网络的指标函数 (扭转了一些符号) 为例:

因为 ????′ 自身是一个神经网络,如果 ????′(????′) 最终输入了一个不在数据集内的动作,那么很可能导致 ????′(????′,????′(????′)) 对于该状态 - 动作组合的估值不准,那么就学不到好的策略了。如下图 (起源) 就显示了如果动作 ???? 在行为策略 ???? 的散布之外,会有可能对 ???? 值产生过高的预计,导致后续谬误一直累计。

我在理论训练 DDPG 的时候的确碰到过相似状况,Critic 的损失有时候会达到 1e8 这样夸大的级别,不管再怎么调小学习率都没用。起初发现可能的起因,最开始是将用户之前交互过的多个物品向量均匀起来作为状态 ???? 的表白,然而均匀过后的向量就可能不会长得和任何单个物品向量很像了,也即远离了原来的数据分布。那么 ????′(????) 输入的动作 ???? 天然也和数据集中的动作相去甚远,这样一环传一环以致最终 ???? 值爆炸,而起初改为物品向量间接拼接后就没这种状况了。

另外作者也提到,DQN、DDPG 这样常见的 off-policy 算法中并没有思考 extrapolation error,为什么它们在正统强化学习工作中很无效呢?因为是这些算法实质上采纳的是 growing batch learning 的训练方法:在用一批数据离线训练一段时间后,仍然会用训练好的策略去环境中收集新数据用于训练,这样采样来的数据实际上和现有策略差异不大,因此 extrapolation error 能够忽略不计。然而在齐全 offline 训练的状况下,数据集很可能是应用齐全不同的策略收集而来的,因此这种时候 extrapolation error 的影响就比较显著了。

所以问题的外围是如何防止生成一个莫名其妙的状态 - 动作组合从而导致 extrapolation error?论文中的办法是用一个生成模型 (generative model) 来生成和数据集中类似的状态 - 动作组合,再用一个扰动模型 (perturbation model) 对生成的动作增加一些噪声来减少多样性。其中生成模型应用的是变分自编码器 (variational auto-encoder, VAE),扰动模型就是一个一般的全连贯网络,输出为生成出的动作 ????,输入为范畴在 [−Φ,Φ] 内的新动作,Φ 为动作的最大值,对于连续型动作咱们个别设定一个下限防止输入太大的动作值。

这两个模型合起来可视为 BCQ 算法应用的策略,即 Actor,而 Critic 的局部和 DDPG 差异不大,残缺代码见:

https://github.com/massquantity/DBRL/blob/master/dbrl/models/bcq.py

Appendix A: Policy Gradient 定理

由 (1.1) 式可知指标函数为:

Appendix B: 重要性采样 (Importance Sampling)

设理论的交互策略 ???? 的轨迹散布为 ????????(????),对 (A.2) 式利用重要性采样:

之后就和附录 A 的推导一样了。

原文链接
本文为阿里云原创内容,未经容许不得转载。

正文完
 0