协同过滤推荐算法与应用优选.docx

上传人:b****5 文档编号:11853746 上传时间:2023-04-06 格式:DOCX 页数:22 大小:230.43KB
下载 相关 举报
协同过滤推荐算法与应用优选.docx_第1页
第1页 / 共22页
协同过滤推荐算法与应用优选.docx_第2页
第2页 / 共22页
协同过滤推荐算法与应用优选.docx_第3页
第3页 / 共22页
协同过滤推荐算法与应用优选.docx_第4页
第4页 / 共22页
协同过滤推荐算法与应用优选.docx_第5页
第5页 / 共22页
点击查看更多>>
下载资源
资源描述

协同过滤推荐算法与应用优选.docx

《协同过滤推荐算法与应用优选.docx》由会员分享,可在线阅读,更多相关《协同过滤推荐算法与应用优选.docx(22页珍藏版)》请在冰豆网上搜索。

协同过滤推荐算法与应用优选.docx

协同过滤推荐算法与应用优选

机器学习算法day03_协同过滤推荐算法及应用

课程大纲

协同过滤推荐算法原理

协同过滤推荐算法概述

协同过滤推荐算法思想

协同过滤推荐算法分析

协同过滤推荐算法要点

协同过滤推荐算法实现

协同过滤推荐算法案例

案例需求

数据规整

参数设定

用Scikili机器学习算法库实现

算法检验

实现推荐

协同过滤推荐算法补充

计算距离的数学公式

协同过滤算法常见问题

课程目标:

1、理解协同过滤算法的核心思想

2、理解协同过滤算法的代码实现

3、掌握协同过滤算法的应用步骤:

数据处理、建模、运算和结果判定

4、

1.CF协同过滤推荐算法原理

1.1概述

什么是协同过滤(CollaborativeFiltering,简称CF)?

首先想一个简单的问题,如果你现在想看个电影,但你不知道具体看哪部,你会怎么做?

大部分的人会问问周围的朋友,看看最近有什么好看的电影推荐,而我们一般更倾向于从口味比较类似的朋友那里得到推荐。

这就是协同过滤的核心思想。

协同过滤算法又分为基于用户的协同过滤算法和基于物品的协同过滤算法

1.2案例需求

如下数据是各用户对各文档的偏好:

用户/文档

文档A

文档B

文档C

文档D

用户A

推荐?

推荐?

用户B

用户C

用户D

现在需要基于上述数据,给A用户推荐一篇文档

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算法适用的场景

什么情况下使用哪种算法推荐效果会更好?

不同环境下这两种理论的有效性也不同,应用时需做相应调整。

a.如豆瓣上的文艺作品,用户对其的偏好程度与用户自身的品位关联性较强;适合UserCF

b.而对于电子商务网站来说,商品之间的内在联系对用户的购买行为影响更为显著。

1.5算法实现

总的来说,要实现协同过滤,需要一下几个步骤:

1.收集用户偏好

2.找到相似的用户或物品

3.计算推荐

 

1.5.1收集用户偏好

用户有很多方式向系统提供自己的偏好信息,而且不同的应用也可能大不相同,下面举例进行介绍:

用户行为

类型

特征

作用

评分

显式

整数量化值[0,n]

可以得到精确偏好

投票

显式

布尔量化值0|1

可以得到精确偏好

转发

显式

布尔量化值0|1

可以得到精确偏好

保存书签

显式

布尔量化值0|1

可以得到精确偏好

标记书签Tag

显式

一些单词

需要进一步分析得到偏好

评论

显式

一些文字

需要进一步分析得到偏好

点击流

隐式

一组点击记录

需要进一步分析得到偏好

页面停留时间

隐式

一组时间信息

噪音偏大,不好利用

购买

隐式

布尔量化值0|1

可以得到精确偏好

1.5.2原始偏好数据的预处理

v用户行为识别/组合

在一般应用中,我们提取的用户行为一般都多于一种,关于如何组合这些不同的用户行为,比如,可以将用户行为分为“查看”和“购买”等等,然后基于不同的行为,计算不同的用户/物品相似度。

类似于当当网或者京东给出的“购买了该图书的人还购买了...”,“查看了图书的人还查看了...”

v喜好程度加权

根据不同行为反映用户喜好的程度将它们进行加权,得到用户对于物品的总体喜好。

一般来说,显式的用户反馈比隐式的权值大,但比较稀疏,毕竟进行显示反馈的用户是少数;同时相对于“查看”,“购买”行为反映用户喜好的程度更大,但这也因应用而异。

v数据减噪和归一化。

1 减噪:

用户行为数据是用户在使用应用过程中产生的,它可能存在大量的噪音和用户的误操作,我们可以通过经典的数据挖掘算法过滤掉行为数据中的噪音,这样可以是我们的分析更加精确。

2 归一化:

如前面讲到的,在计算用户对物品的喜好程度时,可能需要对不同的行为数据进行加权。

但可以想象,不同行为的数据取值可能相差很大,比如,用户的查看数据必然比购买数据大的多,如何将各个行为的数据统一在一个相同的取值范围中,从而使得加权求和得到的总体喜好更加精确,就需要我们进行归一化处理。

最简单的归一化处理,就是将各类数据除以此类中的最大值,以保证归一化后的数据取值在[0,1]范围中。

v形成用户偏好矩阵

一般是二维矩阵,一维是用户列表,另一维是物品列表,值是用户对物品的偏好,一般是[0,1]或者[-1,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

(1)欧氏距离法

就是计算每两个点的距离,比如Nike和Sony的相似度  。

数值越小,表示相似度越高。

defOsDistance(vector1,vector2):

sqDiffVector=vector1-vector2

sqDiffVector=sqDiffVector**2

sqDistances=sqDiffVector.sum()

distance=sqDistances**0.5

returndistance

(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之间。

    

defcosSim(inA,inB):

num=float(inA.T*inB)

denom=la.norm(inA)*la.norm(inB)

return0.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和matplotlib

2.2.1数据规整

首先将评分数据从ratings.dat中读出到一个DataFrame里:

>>>importpandasaspd

>>>frompandasimportSeries,DataFrame

>>>rnames=['user_id','movie_id','rating','timestamp']

>>>ratings=pd.read_table(r'ratings.dat',sep=':

:

',header=None,names=rnames)

>>>ratings[:

3]

user_idmovie_idratingtimestamp

0111935978300760

116613978302109

219143978301968

[3rowsx4columns]

ratings表中对我们有用的仅是user_id、movie_id和rating这三列,因此我们将这三列取出,放到一个以user为行,movie为列,rating为值的表data里面。

>>>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.3min_periods参数测定

测定这样一个参数的基本方法:

v统计在min_periods取不同值时,相关系数的标准差大小,越小越好;

但同时又要考虑到,我们的样本空间十分稀疏,min_periods定得太高会导致出来的结果集太小,所以只能选定一个折中的值。

这里我们测定评分系统标准差的方法为:

v在data中挑选一对重叠评分最多的用户,用他们之间的相关系数的标准差去对整体标准差做点估计。

在此前提下对这一对用户在不同样本量下的相关系数进行统计,观察其标准差变化。

首先,要找出重叠评分最多的一对用户。

我们新建一个以user为行列的方阵foo,然后挨个填充不同用户间重叠评分的个数:

>>>foo=DataFrame(np.empty((len(data.index),len(data.index)),dtype=int),index=data.index,columns=data.index)

#print(empt.shape):

(6040,6040)

>>>foriinfoo.index:

forjinfoo.columns:

foo.ix[i,j]=data.ix[i][data.ix[j].notnull()].dropna().count()

这段代码特别费时间,因为最后一行语句要执行4000*4000=1600万遍;

找到的最大值所对应的行列分别为424和4169,这两位用户之间的重叠评分数为998:

>>>foriinfoo.index:

foo.ix[i,i]=0#先把对角线的值设为0

>>>ser=Series(np.zeros(len(foo.index)))

>>>foriinfoo.index:

ser[i]=foo[i].max()#计算每行中的最大值

>>>ser.idxmax()#返回ser的最大值所在的行号

4169

>>>ser[4169]#取得最大值

998

>>>foo[foo==998][4169].dropna()#取得另一个user_id

4244169

Name:

user_id,dtype:

float64

把424和4169的评分数据单独拿出来,放到一个名为test的表里,另外计算了一下这两个用户之间的相关系数为0.456,还算不错,另外通过柱状图了解一下他俩的评分分布情况:

>>>data.ix[4169].corr(data.ix[424])

0.45663851303413217

>>>test=data.reindex([424,4169],columns=data.ix[4169][data.ix[424].notnull()].dropna().index)

>>>test

movie_id2610111217...

424444415...

4169344425...

>>>test.ix[424].value_counts(sort=False).plot(kind='bar')

>>>test.ix[4169].value_counts(sort=False).plot(kind='bar')

对这俩用户的相关系数统计,我们分别随机抽取20、50、100、200、500和998个样本值,各抽20次。

并统计结果:

>>>periods_test=DataFrame(np.zeros((20,7)),columns=[10,20,50,100,200,500,998])

>>>foriinperiods_test.index:

forjinperiods_test.columns:

sample=test.reindex(columns=np.random.permutation(test.columns)[:

j])

periods_test.ix[i,j]=sample.iloc[0].corr(sample.iloc[1])

>>>periods_test[:

5]

102050100200500998

0-0.3067190.7090730.5043740.3769210.4771400.4269380.456639

10.3866580.6075690.4347610.4719300.4372220.4307650.456639

20.5074150.5858080.4406190.6347820.4905740.4367990.456639

30.6281120.6282810.4523310.3800730.4720450.4442220.456639

40.7925330.6415030.4449890.4992530.4264200.4412920.456639

[5rowsx7columns]

>>>periods_test.describe()

102050100200500#998略

count20.00000020.00000020.00000020.00000020.00000020.000000

mean0.3468100.4647260.4588660.4501550.4675590.452448

std0.3985530.1817430.1038200.0936630.0364390.029758

min-0.4443020.0873700.1923910.2421120.4122910.399875

25%0.1745310.3209410.4347440.3756430.4392280.435290

50%0.4871570.5252170.4766530.4688500.4725620.443772

75%0.6386850.6166430.5198270.5008250.4873890.465787

max0.8509630.7090730.5920400.6347820.5460010.513486

[8rowsx7columns]

从std这一行来看,理想的min_periods参数值应当为200左右(标准差和均值、极值最接近)。

2.2.3算法检验

为了确认在min_periods=200下本推荐算法的靠谱程度,最好还是先做个检验。

具体方法为:

在评价数大于200的用户中随机抽取1000位用户,每人随机提取一个评价另存到一个数组里,并在数据表中删除这个评价。

然后基于阉割过的数据表计算被提取出的1000个评分的期望值,最后与真实评价数组进行相关性比较,看结果如何。

>>>check_size=1000

>>>check={}

>>>check_data=data.copy()#复制一份data用于检验,以免篡改原数据

>>>check_data=check_data.ix[check_data.count(axis=1)>200]#滤除评价数小于200的用户

>>>foruserinnp.random.permutation(check_data.index):

movie=np.random.permutation(check_data.ix[user].dropna().index)[0]

check[(user,movie)]=check_data.ix[user,movie]

check_data.ix[user,movie]=np.nan

check_size-=1

ifnotcheck_size:

break

>>>corr=check_data.T.corr(min_periods=200)

>>>corr_clean=corr.dropna(how='all')

>>>corr_clean=corr_clean.dropna(axis=1,how='all')#删除全空的行和列

>>>check_ser=Series(check)#这里是被提取出来的1000个真实评分

>>>check_ser[:

5]

(15,593)4

(23,555)3

(33,3363)4

(36,2355)5

(53,3605)4

dtype:

float64

接下来要基于corr_clean给check_ser中的1000个用户-影片对计算评分期望。

计算方法为:

对与用户相关系数大于0.1的其他用户评分进行加权平均,权值为相关系数

>>>result=Series(np.nan,index=check_ser.index)

>>>foruser,movieinresult.index:

#这个循环看着很乱,实际内容就是加权平均而已

prediction=[]

ifuserincorr_clean.index:

corr_set=corr_clean[user][corr_clean[user]>0.1].dropna()#仅限大于0.1的用户

else:

continue

forotherincorr_set.index:

ifnotnp.isnan(data.ix[other,movie])andother!

=user:

#注意bool(np.nan)==True

prediction.append((data.ix[other,movie],corr_set[other]))

ifprediction:

result[(user,movie)]=sum([value*weightforvalue,weightinprediction])/sum([pair[1]forpairinprediction])

>>>result.dropna(inplace=True)

>>>len(result)#随机抽取的1000个用户中也有被min_periods=200刷掉的

862

>>>result[:

5]

(23,555)3.967617

(33,3363)4.073205

(36,2355)3.903497

(53,3605)2.948003

(62,1488)2.606582

dtype:

float64

>>>result.corr(check_ser.reinde

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工程科技 > 兵器核科学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1