Make recommendations
电影推荐为例,有四个用户Alice、Bob、Carol和Dave去对五个电影进行从一星到五星的评分,其中表格里的问号"?"代表用户还未对该电影进行评分
对其中的符号进行定义:Nu代表user的数目,此处为4;Nm代表movie的数目,此处为5;通过r(i,j)=1表示出用户j已经对电影i进行了评分,没有评分的话为0;进一步,如果用户j已经对电影i进行了评分,y值就用来表达其ratings。在此处,用户2对于movie3的评分为4,故y(3,2)=4
因此对于推荐系统的框架下,解决问题的一种方法是查看用户未评分的电影并尝试预测用户如何评价这些电影,由此可以尝试向用户推荐他们更有可能评价为五颗星的东西,为达到这样的目标设计了一种算法,但是有一种特殊的假设就是我们可以访问有关电影的features or extra information,例如哪些电影是爱情电影,哪些是动作电影,从而去开发算法
构建算法(assume 可以访问额外的信息或特征)
在上面的基础上,n代表特征的数量,此处n=2,分别为romance和action,一般的表达形式就是:预测用户j对于电影i的评分(类似线性回归)w(j) * x(i) + b(j),不同于线性回归的是我们为每一个用户都构建一个线性回归模型,另外用m(j)来表示用户j评分的电影数量,定义好之后提出cost function
Cost function
这里的n表示X(i)中特征的数量(和w(j)中的数字数量一样),由于此处的m(j)是个常数,于是有没有这个常数不影响得到参数w和b,于是在之后的研究中可以消除它
但是如无法访问可以提供相关电影的额外信息或特征并希望做出预测,此时可以采用协同过滤算法
协同过滤算法
协同过滤算法就是从多个用户那里收集数据,利用用户之间的协作关系去预测其他用户的评分
现在,仅出于说明的目的,假设我们已经以某种方式学习到了四个用户的各自参数w和b,其中设b均为0,于是在后面的表达中进行简化(去掉b)
可以通过这样类似的方式去预测x(2)、x(3)等等,而这只是因为我们有四个用户的参数才允许我们尝试猜测appropriate的特征features(x1和x2),而在经典的linear 回归中只有一个用户所以没有足够的信息去figure out特征,而在协同过滤中有来自同一项目的多个用户
实际上如果要去学习x(2)、x(3)等参数,可以通过建立成本函数利用梯度下降去得到
而这些我们都在以参数w和b都已知的假设下做出的,事实上将两者结合起来:
而后通过梯度下降去最小化参数:
这样我们只采用了已知的(右上角的表格)信息,去学习到参数。
这里我们采用的是电影评分从1星到5星或者从0星到5星,而推荐系统的一个常见用例是我们有用户喜欢的是二进制标签,而不是要求明确的用户评级,接下来我们看一下现在的模型对二进制标签的概括。
协同过滤算法的TensorFlow实现
首先用一个example,其中b设定为0,成本函数J就是(f(x)-y)**也即(wx-1)**
通过定义w(w=tf.Variable(3.0)也即w=3.0)和学习率(α=0.01),利用tf.GradientTape()定义f(x)和cost function J,进一步得到了J对w的偏导数,由于tf.variable需要special funct to modify所以我们没有用w = w - α*偏导数的形式去更新w,而是利用assign_add去更新,从而找到w的最优值1(在图中的左方可以体现),无需去关心如何计算偏导数项,这是TensorFlow的强大功能Auto Diff(Auto Grad),在Pytorch中也支持这样的Auto Diff
现在我们可以自动计算导数,这样的话我们就不会局限于梯度下降,可以使用更强大的优化算法(如Adam),下图即为实现过程,通过keras指明优化器选择为Adam,定义成本函数,从而进行更新。
此处的zip函数在Python中的作用只是将数字重新排列为应用梯度函数的适当顺序的函数
二进制标签(就像你对视频 不是点赞就是不点赞)
在二值协同过滤中,我们有很多方法去定义什么是标签1,标签0和标签问号(“?”)
1表示用户参与后表达了购买或喜爱的意愿,0表示用户参加后没有表达购买或喜爱的意愿,?表示用户没有看到
对于之前的表示方式,很像一个线性回归,而在二进制标签的协同过滤算法中更像是一个logistic回归,采用了sigmod激活函数,其损失函数也采用了交叉熵损失函数,其中f(x)即为g(w*x+b)