推荐系统遇上深度学习(十三)--linUCB方法浅析及实现

上一篇中介绍了Bandit算法,并介绍了几种简单的实现,如 Epsilon-Greedy算法,Thompson sampling算法和UCB算法。

但是传统的实现方法存在很大的缺陷,主要是缺乏用附加信息刻画决策过程的机制。今天的文章就来介绍一种结合上下文信息的Bandit方法,LinUCB,它是Contextual bandits算法框架的一种。

本文的原文是雅虎的新闻推荐算法:https://arxiv.org/pdf/1003.0146.pdf。里面公式是真的挺多的,而且涉及到了两种linUCB算法,本文只介绍第一种方法。感兴趣的同学可以阅读原文。

LinUCB浅析

这里只简单介绍一下LinUCB算法的流程,真的是浅析,浅析!

在推荐系统中,通常把待推荐的商品作为MAB问题的arm。UCB是context-free类的算法,没有充分利用推荐场景的上下文信息,为所有用户的选择展现商品的策略都是相同的,忽略了用户作为一个个活生生的个性本身的兴趣点、偏好、购买力等因素,因而,同一个商品在不同的用户、不同的情景下接受程度是不同的。故在实际的推荐系统中,context-free的MAB算法基本都不会被采用。

与context-free MAB算法对应的是Contextual Bandit算法,顾名思义,这类算法在实现E&E时考虑了上下文信息,因而更加适合实际的个性化推荐场景。

在LinUCB中,每一个arm维护一组参数,用户和每一个arm的组合可以形成一个上下文特征(上下文特征的特征维度为d),那么对于一个用户来说,在每个arm上所能够获得的期望收益如下:

对于一个老虎机来说,假设收集到了m次反馈,特征向量可以写作Da(维度为md),假设我们收到的反馈为Ca(维度为m1),那么通过求解下面的loss,我们可以得到当前每个老虎机的参数的最优解:

这其实就是岭回归嘛,我们很容易得到最优解为:

既然是UCB方法的扩展,我们除了得到期望值外,我们还需要一个置信上界,但是,我们没法继续用Chernoff-Hoeffding Bound的定理来量化这个上界,幸运的是,这个上界已经被人找到了:

因此,我们推荐的item就能够确定了:

可以看到,我们在计算参数及最后推荐结果的时候,用到了以下几部分的信息:上下文特征x,用户的反馈c。而这些信息都是可以每次都存储下来的,因此在收集到了一定的信息之后,参数都可以动态更新,因此我们说LinUCB是一种在线学习方法

什么是在线学习?个人简单的理解就是模型的训练和更新是在线进行的,能够实时的根据在线上的反馈更新模型的参数。

好了,我们来看一下linUCB算法的流程吧:

上面的ba可以理解为特征向量x和反馈r的乘积。

是否觉得一头雾水,不用着急,我们通过代码来一步步解析上面的流程。

2、linUCB代码实战

本文的代码地址为:https://github.com/princewen/tensorflow_practice/blob/master/recommendation/Basic-Bandit-Demo/Basic-LinUCB.py

设定超参数和矩阵

首先我们设定一些超参数,比如α,正反馈和负反馈的奖励程度r1,r0,上下文特征的长度d

self.alpha = 0.25
self.r1 = 0.6
self.r0 = -16
self.d = 6  # dimension of user features

接下来,我们设定我们的几个矩阵,比如A和A的逆矩阵,b(x和r的乘积),以及参数矩阵:

self.Aa = {} # Aa : collection of matrix to compute disjoint part for each article a, d*d
self.AaI = {}  # AaI : store the inverse of all Aa matrix

self.ba = {}  # ba : collection of vectors to compute disjoin part, d*1
self.theta = {}

初始化矩阵

初始化矩阵对应上面的4-7步,A设置为单位矩阵,b设置为0矩阵,参数也设置为0矩阵,注意的是,每个arm都有这么一套矩阵:

def set_articles(self,art):
    for key in art:
        self.Aa[key] = np.identity(self.d) # 创建单位矩阵
        self.ba[key] = np.zeros((self.d,1))

        self.AaI[key] = np.identity(self.d)
        self.theta[key] = np.zeros((self.d,1))

计算推荐结果

计算推荐结果对应于上面的8-11步,我们直接根据公式计算当前的最优参数和置信上界,并选择最大的arm作为推荐结果。代码中有个小trick,及对所有的arm来说,共同使用一个特征,而不是每一个arm单独使用不同的特征:

def recommend(self,timestamp,user_features,articles):
    xaT = np.array([user_features]) # d * 1
    xa = np.transpose(xaT)

    AaI_tmp = np.array([self.AaI[article] for article in articles])
    theta_tmp = np.array([self.theta[article] for article in articles])
    art_max = articles[np.argmax(np.dot(xaT,theta_tmp) + self.alpha * np.sqrt(np.dot(np.dot(xaT,AaI_tmp),xa)))]

    self.x = xa
    self.xT = xaT

    self.a_max = art_max
    return self.a_max

更新矩阵信息

这对应于上面的12-13步,根据选择的最优arm,以及得到的用户反馈,我们更新A和b矩阵:

def update(self,reward):
    if reward == -1:
        pass
    elif reward == 1 or reward == 0:
        if reward == 1:
            r = self.r1
        else:
            r = self.r0

        self.Aa[self.a_max] += np.dot(self.x,self.xT)
        self.ba[self.a_max] += r * self.x
        self.AaI[self.a_max] = np.linalg.inv(self.Aa[self.a_max])
        self.theta[self.a_max] = np.dot(self.AaI[self.a_max],self.ba[self.a_max])

    else:
        # error

写到这里,本来应该就要结束了,可是脑子里又想到一个问题,为什么可以直接通过加法来更新A矩阵?其实是个很简单的问题,试着写出A矩阵中每个元素的计算公式来,问题就迎刃而解了!

结语

总结一下LinUCB算法,有以下优点(来自参考文献3,自己又增加了一条):
1)由于加入了特征,所以收敛比UCB更快(论文有证明);
2)特征构建是效果的关键,也是工程上最麻烦和值的发挥的地方;
3)由于参与计算的是特征,所以可以处理动态的推荐候选池,编辑可以增删文章;
4)特征降维很有必要,关系到计算效率。
5)是一种在线学习算法。

参考文献

1、https://arxiv.org/pdf/1003.0146.pdf
2、https://zhuanlan.zhihu.com/p/35753281
3、https://blog.csdn.net/legendavid/article/details/71082124
4、https://zhuanlan.zhihu.com/p/32382432

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容