白话文理解机器学习之推荐系统及协同过滤算法

       最近在学习机器学习推荐系统时发现,网上所看到的代码并不是真正地运用了协同过滤算法(也在git上找过两篇,写了很多看不太懂故而自己琢磨了一番),多数为通过计算两个用户所观看电影的相似度来预测,而机器学习课程中吴恩达所讲的协同过滤并不是这样,本篇博客仔细讲讲两者区别,并讲讲推荐系统。

       先看这么个例子:

白话文理解机器学习之推荐系统及协同过滤算法

其中行为用户,列为商品,1~5数字代表该用户对该菜的评价,0为该用户未评价,需要值得推荐给相应的用户。

方法1:基于内容,也是网上大多数的方法,通过计算用户之间的相似度,找到邻居,再根据邻居中评价过但该用户没有吃过的好菜进行推荐,意思就是假设Ed用户来到某餐厅,经过上两次的评价发现该用户并不喜欢烤牛肉和手撕猪肉,商家觉得如果此次推荐的菜品还是不符合Ed的口味,那么可能就要永远流失该用户了,该餐厅只有5个菜,有6个人做出过点评,那么Ed对应的向量为[0,0,0,2,2],此时根据算法应该在其余的5个用户中找到相似度最高的邻居,普遍三种计算距离的算法:欧氏距离,余弦相似度,皮尔森系数,一般采用余弦相似度或皮尔森系数计算,如果控制最近邻居个数为2,那么会找到Peter和Tracy,再假设Peter向量为 [3 5 0 3 3],Tracy的向量为[4 0 0 1 1],那么此时可以找到Ed没有吃过的菜系鳗鱼饭,日式炸鸡排,寿司饭,根据Peter和Tracy中评价过的鳗鱼饭和日式炸鸡排的评价值来计算,有两种方法:

          1)、所有邻居评价过的菜的评价值*该邻居与预测用户的距离相似度的和取相应的平均值,鳗鱼饭:(3*Peter相似度+4*Tracy相似度)/ 2 ,日式炸鸡排:5*Peter相似度,再比较他们的大小;

          2)、就是在1的基础上不算平均值,比如你也可以认为10个用户都中高分评价比5个用户高分评价可靠些,所以也可以不去平均值。

以上数据小推荐只有两者的比较,实际上大数据的情况下可以通过设阈值来推荐自己设定的推荐个数。

其次发现在本章图片中Peter和Tracy并没有评价过鳗鱼饭,日式炸鸡排,寿司饭,故而就会陷入推荐空值,这也是该方法的缺点,当然大数据下不会出现这种情况,即使出现也可以通过基于流行度来进行推荐,但该方法还有一个致命的缺点就是无法预测出该用户对于某类商品的评价值。

方法2:吴恩达所讲的协同过滤算法, 也就是构建n*m的矩阵,如上图,通过w*x来拟合出n*m维矩阵中各个位置的值,通过迭代最小化均方根误差,以上图为例,w:[用户数,feature_size],x:[菜数,feature_size],feature_size是隐语义维度,就相当于神经网络中的隐藏层中的神经元个数,从这里也可以看出,既然是拟合已给出的评价值,那么有两种方式来写w*x,

          1)、先构建n*m维的的矩阵,相应位置上未评价的值赋值为0

          2)、既然没有评价过再去计算只会消耗服务器资源,通常矩阵的存储方式为三元组的形式,这里0不存储,那么直接对三元组遍历相乘再去拟合就可以,两者实际上是一样的,但走了不同的路而已。以上两者的我的电脑上训练时消耗资源的比较(用公共数据集moivelens):1)耗内存325M,时间37s,因为可以直接通过Index去寻找值,2)耗内存214M,时间107s,综合而言应该选用2)的方式来计算

         总结一下协同过滤算法和基于用户相似度两种方法,协同过滤用法广,预测较为精确,缺点耗时慢,占内存,基于内容度优点速度快,内存小,缺点适用范围小。 但服务器上将模型训练好后只需要预测即可,模型在夜晚更新就行,所以综合而言协同过滤更优。当然还有什么基于流行度,这个过于简单不在考虑范围。

         注:你或许还在网上看到过SVD矩阵分解+协同过滤,事实上只适用于基于内容的推荐系统,而不适用于协同过滤,为什么呢,因为基于内容只是计算两者向量的相似度,向量是n*1的,你压缩乘m*1都可以,但其实不太需要,因为本来速度就很快了。而协同过滤中w,x都是n个用户权重,x是m个电影的特征,压缩哪一维都不合适,因为还要索引对应位置上的值进行索引。

        以下是提供代码下载链接(包含数据集,手写的三种推荐系统(基于内容1,协同过滤2)):

3种方式实现推荐系统