将笔记中的MAB问题转来博客。
本篇重点分享一下MAB问题的思考和一些解决算法。
Bandit算法常常用于解决EE问题和部分用户的冷启动问题。
推荐系统的使命是在物品和用户之间建立连接,为用户匹配到最佳物品
也有另一个理解:在某个时间某个位置为用户选择最好的物品
推荐就是选择
人为什么害怕选择?究其原因是因为人把每个选项看做独一无二的个体,错过不再来
推荐系统中的选择也是如此,一旦选择呈现给用户,如果不能得到用户的青睐,就失去了一个展示机会,甚至有可能起到负面作用(广告系统中尤甚)。
跳出来看这个问题,选择时不再是选择个体,而是选择类别,这样压力是不是小许多?
比如吧推荐选择具体物品上升到选择策略。如后台有三种推荐策略,按照内容相似推荐,按照好友相似推荐,按照热门推荐。每次选择一种策略,确定策略后再根据策略中的物品进行选择。
这就是Bandit算法的出发点
MAB问题
Bandit算法起源于赌博学,原始问题:一个赌徒摇老虎机,走进赌场一看,一排老虎机外表一模一样,但每个老虎机吐钱的概率不一样,它不知道老虎机吐钱概率分布,那么如何最大化收益?
这就是多臂赌博机问题(Multi-armed bandit problem)。
- 假设一个用户对不同类别内容感兴趣程度不同,当推荐系统初次见到用户时,怎么快速直到他对每类内容的感兴趣程度?这也是推荐系统经常面对的冷启动问题
- 假设系统中有若干广告库存,该给每个用户展示哪个广告才能获得最大点击收益,是不是每次都挑收益最好的那个?
- 算法工程师又设计出了新的策略或者模型,如何既能直到它和旧模型相比谁更可靠,又能控制风险?
这些问题都是关乎选择的问题,只要是关乎选择,都可以简化成一个MAB问题
前面文章提过,推荐系统有两个顽疾,1. 冷启动、2. 探索和利用。后者称EE问题(Exploit-Explore)针对这两个问题,Bandit可对症下药
重点关注EE:
探索:被不断探索用户新的兴趣,否则将和快就会出现大量重复推荐
利用:比较确定的兴趣,要重充分利用,进行实际推荐
Bandit算法
Bandit并不是指一个算法,而是指一类算法。
如何衡量选择的好坏?
答:Bandit算法的思想是:看看选择会带来多少遗憾,遗憾越少越好。在MAB问题里,用来衡量好坏的指标就是累积遗憾,R = Σ(ωopt - ωB(i))。ωopt表示每次宣导最好选择得到的收益, ω表示每次选择的实际收益。二者之差记为本次选择带来的遗憾,T次选择后,累积遗憾即为上式。
这个公式用来对比不同Bandit算法的效果,用不同的Bandit算法模拟相同次数,对比哪个算法累积遗憾增长更慢,就是效果好的算法。
Bandit算法的套路:小心翼翼的尝试,越确定某个选择好,就越多选择它;反之则越少选择。
如果一个选择的试验次数较少,不确定好坏,就多给一些选择机会,直到确定为止。简单来说,把选择机会多给“确定好的”和“还不确定的”。
Bandit算法中有几个关键元素:臂、回报、环境
- 臂:每次选择的候选项,如老虎机的摇臂
- 回报:就是选择一个臂之后得到的奖励,好比老虎机吐出来的金币
- 环境:就是决定每个臂不同的那些因素,统称为环境
对应到推荐系统中
- 臂:每次推荐要选择的候选池,可能是具体物品,可能是推荐策略,也可能是物品类别
- 回报:用户的回馈,喜欢则是正面回报,没有买账就是负面回报或零回报
- 环境:推荐系统当前面临的这个用户就是未知的环境
- 汤普森采样
数学基础简单,只需要一行代码就可以实现
原理:假设次选择是否产生收益,背后有一个起决定作用的概率分布,产生收益为p
每个臂背后绑定了一个概率分布,每次选择时,让每个臂的概率分布各自产生一个随机数(蒙特卡洛模拟),按照这个随机数排序,输出产生最大随机数那个臂对应的物品。
为什么可以这么做? 关键在于汤普森采样背后基于的是Beta分布
Beta分布:
有a和b两个参数,两个参数决定了分布形状。
- a+b的值越大,分布曲线就越集中,反之则越疏远(两边大中间小)
- 当a/(a+b)的值越大,分布集中位置的中心越靠近1,反之越靠近0,这样产生的随机数位置也相应更容易靠近1或0
因此,Beta分布总体有三种情况,曲线很窄靠近1、曲线很窄靠近0、曲线很宽
由此,若把Beta分布的参数a看做推荐后得到用户点击的次数,把b看做未得到用户点击的次数,如下:
- 取出每一个候选对应的a和b
- 为每个候选用a和b作为参数,用Beta分布产生一个随机数
- 按照随机数排序,输出最大值对应的候选
- 观察用户反馈,如果用户点击则将对应候选的a增加1,反之b增加1
因此在推荐系统中,为每个用户都保存一套参数,每个用户对应每个物品都保存一份a和b,一共2mn个
为什么有效?
- 如果候选被选中次数很多,那么a+b分布变窄,换句话说这个候选的收益已经确定,用它产生随机数,基本就在分布的中心位置附近,接近这个分布的平均收益
- 如果一个候选不但a+b很大,且a/(a+b)也很大,那么就是一个好的候选项,平均收益很好,每次选择占据优势,就进入利用阶段,反之则几乎再无出头之日
- 如果一个候选项的a+b很小,分布很宽,就是没有给充分的探索次数,此时不能确定好坏,那么这个较宽的分布有可能得到一个较大的随机数,在排序时被优先输出,给予次数做探索
Python实现:choice = np.argmax(pymc.rbeta(1)self.wins, 1 + self.trals - self.wins))
UCB算法
另一种常用的算法就是UCB(Upper Confidence Bound)置信区间上界。它也为每个臂评分,每次选择评分最高的候选臂输出,每次输出后观察用户的反馈,回来更新臂的参数
评分公式: score = xjt(拔) + √(2lnt / Tj,t)
加号前面是这个候选臂到目前的平均收益,反映了它的效果,后面叫做Bonus,本质上是均值的标准差,反映了候选臂的不稳定性,就是置信区间的上边界。t是目前总选择次数,Tj,t是每个臂被选择的次数
观察这个公式,如果一个候选的选择次数很少,即Tjt很小,那么Bonus就大,选择评分高,输出有优势,这个Bonus反应了一个候选的收益置信区间的宽度,Bonus越大,候选的平均收益置信区间越宽,越不确定,越需要更多的选择机会。反之若左边平均收益很大,也会在选择时有优势。
这个评分和汤普森采样的思想是一样的:
- 以每个候选的平均收益作为基准进行选择
- 对于选择次数不足的选项给予照顾
- 倾向于选择那些已经确定收益较好的候选
Epsilon算法
这是一个朴素算法,简单有效,类似模拟退火,做法如下:
- 先选择一个(0,1)之间较小的数,叫做Epsilon,这也是算法命名来历
- 每次以概率Epsilon对所有候选臂中随机选择一个,以1-Epsilon概率选择平均收益最大的
简单粗暴的方法,Epsilon的值可以控制对探索和利用的权衡程度,这个值越接近0,探索上就越保守
与这种做法类似的:先试几次,等每个臂都统计到收益后,就一直选择均值最大的臂
效果对比
以模拟次数为自变量,随着时间的推移,根据遗憾值的累积程度,效果从坏到好如下:
- 完全随机:不顾用户反馈的做法
- 朴素选择:认准一个效果好的一直推
- Epsilon贪婪算法:每次以小概率尝试新的,大概率选择效果好的,随时间推移趋近朴素选择
- UCB:每次基于机会较少的一些倾向
- 汤普森采样:用Beta分布管理每一个候选的效果
实验表明:UCB和汤普森采样对于遗憾值的控制效果显著优秀
冷启动
用Bandit算法来部分解决冷启动问题:
- 用分类或Topic来表示每个用户兴趣,我们可以通过几次实验,来刻画新用户细目中对每个Topic的感兴趣概率
- 这里如果用户对某个Topic感兴趣,就表示我们得到了收益,如果推给他不感兴趣Topic,推荐系统产生遗憾值
- 当一个新用户来了,针对这个用户,用汤普森采样为每一个Topic采样一个随机数,排序后输出采样值Top N的推荐item。注意这里一次选择了Top N个候选臂
- 等待用户反馈,没有反馈则更新对应Topic的b值,点击了则更新a
总结
Bandit算法是一种走一步看一步的推荐算法,它把用户看做一个多变的环境,待推荐物品就如同老虎机的摇臂,如果推荐了符合用户心意的,就好比摇出了金币。
Bandit算法大家族中,有汤普森采样、UCB、Epsilon贪婪算法等,效果总体汤普森采样和UCB占优
思考:Bandit算法不足
- 探索过程可能带来用户体验下降的情况,使得用户惰于反馈,系统将越来越差
- 如何实际环境中衡量算法好坏?遗憾值度量往往存在于实验环境中
- 收敛速度是一个问题
- 汤普森采样的参数存储较大,实际使用中可能受限