协同过滤推荐算法及应用
Posted 朱培
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了协同过滤推荐算法及应用相关的知识,希望对你有一定的参考价值。
1. CF协同过滤推荐算法原理1.1 概述
什么是协同过滤 (Collaborative Filtering, 简称 CF)? 首先想一个简单的问题,如果你现在想看个电影,但你不知道具体看哪部,你会怎么做? 大部分的人会问问周围的朋友,看看最近有什么好看的电影推荐,而我们一般更倾向于从口味比较类似的朋友那里得到推荐。这就是协同过滤的核心思想。 协同过滤算法又分为基于用户的协同过滤算法和基于物品的协同过滤算法1.2 案例需求
如下数据是各用户对各文档的偏好:用户 / 文档 | 文档 A | 文档 B | 文档 C | 文档 D |
用户 A | √ | √ | 推荐? | 推荐? |
用户 B | √ | √ | √ | |
用户 C | √ | √ | √ | |
用户 D | √ | √ |
1.3 算法分析
1.3.1 基于用户相似度的分析
直觉分析: “ 用户A/B ” 都喜欢物品A和物品B,从而 “ 用户A/B ” 的口味最为相近 因此,为 “ 用户A ” 推荐物品时可参考 “ 用户B ” 的偏好,从而推荐D这种就是基于用户的协同过滤算法UserCF指导思想
1.3.2 基于物品相似度的分析
直觉分析:物品组合(A,D)被同时偏好出现的次数最多,因而可以认为A/D两件物品的相似度最高,从而,可以为选择了A物品的用户推荐D物品这种就是基于物品的协同过滤算法ItemCF指导思想
1.4 算法要点
1.4.1、指导思想
这种过滤算法的有效性基础在于: 1、用户偏好具有相似性,即用户可分类。这种分类的特征越明显,推荐准确率越高 2、物品之间具有相似性,即偏好某物品的人,都很可能也同时偏好另一件相似物品1.4.2、两种CF算法适用的场景
什么情况下使用哪种算法推荐效果会更好? 不同环境下这两种理论的有效性也不同,应用时需做相应调整。- 如豆瓣上的文艺作品,用户对其的偏好程度与用户自身的品位关联性较强;适合UserCF
- 而对于电子商务网站来说,商品之间的内在联系对用户的购买行为影响更为显著。
1.5 算法实现
总的来说,要实现协同过滤,需要一下几个步骤:- 收集用户偏好
- 找到相似的用户或物品
- 计算推荐
1.5.1 收集用户偏好
用户有很多方式向系统提供自己的偏好信息,而且不同的应用也可能大不相同,下面举例进行介绍:用户行为 | 类型 | 特征 | 作用 |
评分 | 显式 | 整数量化值[0,n] | 可以得到精确偏好 |
投票 | 显式 | 布尔量化值0|1 | 可以得到精确偏好 |
转发 | 显式 | 布尔量化值0|1 | 可以得到精确偏好 |
保存书签 | 显式 | 布尔量化值0|1 | 可以得到精确偏好 |
标记书签Tag | 显式 | 一些单词 | 需要进一步分析得到偏好 |
评论 | 显式 | 一些文字 | 需要进一步分析得到偏好 |
点击流 | 隐式 | 一组点击记录 | 需要进一步分析得到偏好 |
页面停留时间 | 隐式 | 一组时间信息 | 噪音偏大,不好利用 |
购买 | 隐式 | 布尔量化值0|1 | 可以得到精确偏好 |
1.5.2 原始偏好数据的预处理
- 用户行为识别/组合
- 喜好程度加权
- 数据减噪和归一化。
- 减噪:用户行为数据是用户在使用应用过程中产生的,它可能存在大量的噪音和用户的误操作,我们可以通过经典的数据挖掘算法过滤掉行为数据中的噪音,这样可以是我们的分析更加精确。
- 归一化:如前面讲到的,在计算用户对物品的喜好程度时,可能需要对不同的行为数据进行加权。但可以想象,不同行为的数据取值可能相差很大,比如,用户的查看数据必然比购买数据大的多,如何将各个行为的数据统一在一个相同的取值范围中,从而使得加权求和得到的总体喜好更加精确,就需要我们进行归一化处理。最简单的归一化处理,就是将各类数据除以此类中的最大值,以保证归一化后的数据取值在 [0,1] 范围中。
- 形成用户偏好矩阵
1.5.3 找到相似用户或物品
当已经对用户行为进行分析得到用户喜好后,我们可以根据用户喜好计算相似用户和物品,然后基于相似用户或者物品进行推荐,这就是最典型的 CF 的两个分支:基于用户的 CF 和基于物品的 CF。这两种方法都需要计算相似度,下面我们先看看最基本的几种计算相似度的方法。1.5.4 相似度的计算
相似度的计算,现有的几种基本方法都是基于向量(Vector)的,其实也就是计算两个向量的距离,距离越近相似度越大。 在推荐的场景中,在用户 - 物品偏好的二维矩阵中,我们可以将一个用户对所有物品的偏好作为一个向量来计算用户之间的相似度,或者将所有用户对某个物品的偏好作为一个向量来计算物品之间的相似度。 CF的常用方法有三种,分别是欧式距离法、皮尔逊相关系数法、余弦相似度法。 为了测试算法,给出以下简单的用好偏好数据矩阵: 行表示三名用户,列表示三个品牌,对品牌的喜爱度按照1~5增加。用户 | 苹果 | 小米 | 魅族 |
zhangsan | 5 | 5 | 2 |
Lisi | 3 | 5 | 4 |
wangwu | 1 | 2 | 5 |
-
欧氏距离法
def OsDistance(vector1, vector2): sqDiffVector = vector1-vector2 sqDiffVector=sqDiffVector**2 sqDistances = sqDiffVector.sum() distance = sqDistances**0.5 return distance |
(2)皮尔逊相关系数
两个变量之间的相关系数越高,从一个变量去预测另一个变量的精确度就越高,这是因为相关系数越高,就意味着这两个变量的共变部分越多,所以从其中一个变量的变化就可越多地获知另一个变量的变化。如果两个变量之间的相关系数为1或-1,那么你完全可由变量X去获知变量Y的值。 · 当相关系数为0时,X和Y两变量无关系。 · 当X的值增大,Y也增大,正相关关系,相关系数在0.00与1.00之间 · 当X的值减小,Y也减小,正相关关系,相关系数在0.00与1.00之间 · 当X的值增大,Y减小,负相关关系,相关系数在-1.00与0.00之间 当X的值减小,Y增大,负相关关系,相关系数在-1.00与0.00之间 相关系数的绝对值越大,相关性越强,相关系数越接近于1和-1,相关度越强,相关系数越接近于0,相关度越弱。 在python中用函数corrcoef实现,具体方法见参考资料(3)余弦相似度
通过测量两个向量内积空间的夹角的余弦值来度量它们之间的相似性。0度角的余弦值是1,而其他任何角度的余弦值都不大于1;并且其最小值是-1。从而两个向量之间的角度的余弦值确定两个向量是否大致指向相同的方向。两个向量有相同的指向时,余弦相似度的值为1;两个向量夹角为90 ° 时,余弦相似度的值为0;两个向量指向完全相 反的方向时,余弦相似度的值为-1。在比较过程中,向量的规模大小不予考虑,仅仅考虑到向量的指向方向。余弦相似度通常用于两个向量的夹角小于90 ° 之内,因此余弦相似度的值为0到1之间。
def cosSim(inA,inB): num = float(inA.T*inB) denom = la.norm(inA)*la.norm(inB) return 0.5+0.5*(num/denom) |
1.5.3 计算推荐
UserCF基于用户相似度的推荐
计算推荐的过程其实就是KNN算法的计算过程ItemCF基于物品相似度的推荐
算法思路 1. 构建物品的同现矩阵 2. 构建用户对物品的评分矩阵 3. 通过矩阵计算得出推荐结果 推荐结果=用户评分矩阵*同现矩阵 实质:计算各种物品组合的出现次数2. CF协同过滤算法Python实战
2.1 电影推荐需求
根据一个用户对电影评分的数据集来实现基于用户相似度的协同过滤算法推荐,相似度的算法采用 皮尔逊相关系数法 数据样例如下: 用户ID:电影ID:评分:时间1::1193::5::978300760 1::661::3::978302109 1::914::3::978301968 1::3408::4::978300275 1::2355::5::978824291 1::1197::3::978302268 1::1287::5::978302039 1::2804::5::978300719 1::594::4::978302268 1::919::4::978301368 |
2.2 算法实现
本案例使用的数据分析包为pandas,Numpy和matplotlib2.2.1 数据规整
首先将评分数据从ratings.dat中读出到一个DataFrame 里:>>> import pandas as pd >>> from pandas import Series,DataFrame >>> rnames = ['user_id','movie_id','rating','timestamp'] >>> ratings = pd.read_table(r'ratings.dat',sep='::',header=None,names=rnames) >>> ratings[:3] user_id movie_id rating timestamp 0 1 1193 5 978300760 1 1 661 3 978302109 2 1 914 3 978301968 [3 rows x 4 columns] |
>>> data = ratings.pivot(index='user_id',columns='movie_id',values='rating') #形成一个透视表 >>> data[:5] |
可以看到这个表相当得稀疏,填充率大约只有 5%,接下来要实现推荐的第一步是计算 user 之间的相关系数
2.2.2 相关度测算
DataFrame对象有一个很亲切的方法: .corr(method='pearson', min_periods=1) 方法,可以对所有列互相计算相关系数。 其中: method默认为皮尔逊相关系数, min_periods参数,这个参数的作用是设定计算相关系数时的最小样本量,低于此值的一对列将不进行运算。这个值的取舍关系到相关系数计算的准确性,因此有必要先来确定一下这个参数。2.2.3 min_periods 参数测定
测定这样一个参数的基本方法:- 统计在 min_periods 取不同值时,相关系数的标准差大小,越小越好;
- 在 data中挑选一对重叠评分最多的用户,用他们之间的相关系数的标准差去对整体标准差做点估计。
>>> foo = DataFrame(np.empty((len(data.index),len(data.index)),dtype=int),index=data.index,columns=data.index) #print(empt.shape): (6040, 6040) >>> for i in foo.index: for j in foo.columns: foo.ix[i,j] = data.ix[i][data.ix[j].notnull()].dropna().count() |
>>> for i in foo.index: foo.ix[i,i]=0 #先把对角线的值设为 0 >>> ser = Series(np.zeros(len(foo.index))) >>> for i in foo.index: ser[i]=foo[i].max() #计算每行中的最大值 >>> ser.idxmax() #返回ser的最大值所在的行号 4169 >>> ser[4169] #取得最大值 998 >>> foo[foo==998][4169].dropna() #取得另一个 user_id 424 4169 Name: user_id, dtype: float64 |