collaborative filtering (CF):协同过滤


一:定义

根据一组用户的的喜好去推荐和预测其它用户的的未知喜好选择

二:分类

内存依赖,模型依赖,混合CF

(1) 基于内存的协同过滤。这种类型的协同过滤的思想是假设人与人之间的行为具有某种程度的相似性,也就是说行为类似的顾客会购买相类似的产品。基于内存的推荐算法推荐速度快,能反映最新的商品评分。但是由于算法需要将整个用户数据库调入内存,因此产生推荐非常耗时,而且推荐实时性难以保证。

(2) 基于模型的协同过滤。此算法首先通过聚类,贝叶斯网络,关联规则或者机器学习方法来构建使用者兴趣模型,进而利用此模型来产生推荐。由于建立的模型比原始数据集要小的多,因此算法的实时性问题得到很大的改善。但是该模型并不能反映最新的数据库情况,因为在建立模型后,数据库的商品以及评分信息可能已经出现较大变化,因此为了保证模型的有效性,必须周期性地对模型进行更新。协同过滤技术依据所使用的事物之间的关联性,可分为基于用户的协同过滤与基于项目的协同过滤两种:①基于用户的协同过滤:其

核心思想是假设人与人之间的行为具有某种程度的相似性,即购买行为类似的顾客,会购买相类似的产品。②基于项目的协同过滤:其主要假设是项目与项目间具有某种程度的关联,即顾客在购买时,其所购买的产品通常具有关联性,如顾客在购买电子游戏机时,还会购买电池及游戏卡带或者游戏软件。

三:协同过滤算法存在的主要问题:

(1)数据稀疏型问题:在系统初期,用户稀少或者评分信息稀少,难以找到相似用户集,导致推荐效果大大降低。

(2)算法的实时型问题:当用户数目增大到一定程度,推荐结果的计算时间是算法实时性的巨大挑战。如果系统过长时间无响应,网站将会失去客户。

(3)新用户的“冷启动”问题:在数据稀疏的极端情况下,一个新的项目首次出现,没有用户对他做过评价,那么基于用户的协同过滤算法根本无法进行。

四:CF算法的缺点:

数据稀疏:出现新的商品和新的用户的时候,直到有些用户评估了新商品才可以推荐,但是由于没有历史评估,所以顾客不可能给新商品很好的评价。解决方法:SVD,减少一些不重要的商品和用户,但是有用的推荐信息会丢失掉了。混合协同过滤算法使用大容量的分类信息去解决数据稀疏问题。也可以使用内容过滤和协同过滤。或者使用概率模型区解决数据稀疏问题。

可扩展性:用户和商品的增长已经使得CF的复杂度增加。SVD可以解决可扩展性问题,但是,必须经历昂贵的矩阵分解过程,当新的集合加入到数据库中的时候,使用折叠投影技术,不用从0开始。基于内存的CF算法:比如:item-basedPearson correlation CF可以解决可扩张性问题,不是计算所有商品之间的相似性,仅仅计算被同一个客户都选过的商品,在他们之间计算相似性;simple Bayesian CF algorithm,通过观察到的评估信息做预测。

同义性: 不同名字和不同实体但相似的商品之间的趋势,许多系统不能看到他们之间的相似性,所以选择了不同的对待他们。同义性,降低了推荐系统的性能。原来尝试解决同义词问题的方法是:取决于智能或者自动词库匹配,或者同义词库的构建。缺陷是:增加的词汇可能有不同的意思,那样推荐系统的性能就可能下降了。

SVD技术:特别是潜力语义索引(LSI),可以解决同义词问题。SVD构建一个term和document的矩阵库和构建一个语义空间(term和document紧密相关的),SVD应许重点显示数据中的主要关联模式,而不重要的或者次要的忽略显示。LSI方法在高召回级别的(精度比较低)是比较有影响力的,但是在低召回级别的却是不那么起作用。

灰色群体: 这些群体的趋向可能会发生变化,不是一直是一种类型的人。相对来说黑色群体,他们的趋向很特别,不会猜测到,所以推荐系统不适和该人群,作为推荐系统,我们接受这个失败。

四:计算相似度方法

  1. 相似度计算:

item-based CF algorithms: 计算物品i和物品j之间的相似度,在那些对i和j物品都做了评价的基础上的用户计算i和j的相似度。

a user-based CF algorithm:都同时评价了相同物品的用户进行相似度计算,计算两个用户i和j之间的相似度

  1. 计算相似度的方法:

相关相似度计算方法:

User-based algorithm:

  

表示用户u对商品i的评分; 表示用户u的平均评分;I表示用户u和用户v共同评分的项目。

item-based algorithm:

 

 

表示用户u对商品i的评分; 表示商品i的平均评分;U表示对商品i和商品j共同评分的用户

  1. 3.       Vector Cosine-Based Similarity:向量余弦相似性 

 

该方法将客户评分看作是n维项目空间上的向量,如果客户对项目没有进行评分,则将客户对该项目的评分设为0。客户间的相似度通过向量间的余弦夹角 予以度量。

4.  欧几里德距离

Sim_distance(prefs,person1,person2)

   Si[N]; // 代表person1和person2共同评价的商品

   For item in prefs[person1]

      If item in prefs[person2]

         Si[item]=1;

      Else

       Si[item]=0;

End for

If len(si)=0

    Return 0;

Sum_of_squares=sum(pow(prefs[person1][item]-prefs[person2][item],2) for item in prefs[person1] if item in prefs[person2]))

Return 1/(1+sqrt(sum_of_squares))

6.  皮尔逊相关度评价

皮尔逊相关度评价算法首先找出两位评论者都曾评价过的物品,然后计算两者的评分综合与平方和,并求的评分的乘机之和。

算法:

Sim_pearson(prefs, p1,p2)

//记录双方都曾评价过的物品列表

  Si[N]; //记录两者共同评价过的商品

  For item in prefs[p1]

     If item in prefs[p2]

          Si[item]=1;

  N=len(si)

If n=0

   Return 1

//对所有的偏好求和

Sum1=sum([prefs[p1][it] for it in si])

Sum2=sum([prefs[p2][it] for it in si])

// 求平方和

Sum1sq=sum([pow(prefs[p1][it],2) for it in si])

Sum2sq=sum([pow(prefs[p2][it],2) for it in si])

//求成绩之和

pSum=sum(prefs[p1][it]*prefs[p2][it] for it in si)

//计算皮尔逊评价值

Num=psum-(sum1*sum2/n)

Den=sqrt((sum1sq-pow(sum1,2)/n)*( sum2sq-pow(sum2,2)/n))

If den==0

Return 0;

   R=num/den

   Return r

 

  1. 产生推荐:

根据最近邻居集的评价,通过一定推荐算法为目标用户产生推荐,本文采用了平均加权法。平均加权法对目标用户a还为进行评分项目i的预测评分的计算为:

 

其中,sim(a,n)表示用户a与用户n的相似度,Rn,j表示最近邻居集中用户n对项目j的评分,Ra,Ri分别表示用户a和用户n对项目的评价均值。平均加权法综合考虑了用户对所有项目的评分情况,适用于用户评价过的项目数较多的情况,若用户评价过的项目数较少时,个别项目的评分会对平均评分产生较大影响,产生的结果就不够准确。

 

五:CF推荐系统的4个过程

CF推荐系统包括4个过程:数据表示,建立最近邻居集,产生推荐,性能评估。

 

(1) 数据标识:

客户评分数据可用一个m×n阶客户-项目评估矩阵R(m,n)表示,其中第i行第j列的元素r(i,j)代表客户i对项目j的评分。

(2) 最近邻居的建立:

 最近邻居的建立是CF推荐系统的核心。设客户i和客户j的相似度为sim(i,j)。对一个客户c,寻找C的最近邻居集,即要产生客户C的按相似度降序排列的邻居集合Nc={n1,n2,…,nk},c Nc,其中,sim(c,nl)≥sim(c,n2)≥…≥sim(c,nk)。

在CF推荐系统中,度量客户i和客户j之间相似度的方法是:首先得到客户i和客户j共同评分的所有项目,然后通过不同的相似度方法计算客户i和客户j之间的相似度。传统的CF推荐算法通常采用相关相似度和余弦相似度两种度量方法。

(3)产生推荐:

预测型推荐和TOP-N型推荐。

预测型推荐:产生一个预测值R(a,j),R(a,j)表示目标客户a对商品j的预测评分值,其值域范围由客户a决定。

Top-N型推荐: 产生一个目标客户a最喜欢的N个商品的集合,即Top-N推荐集,记作TPa={tp1,tp2,...,tpN},该集合中的每一个商品通常包含的是目标客户a没有购买的,但是值得给客户推荐的商品。

(4) 性能评估

为了评价CF推荐系统算法的性能,一般采用平均绝对偏差MAE(Mean Absolute Error)进行度量。对于测试样本中的一对评分值的真实-预测值对(pi,qi),取两者的绝对误差作偏差,即|pi-qi|。设测试样本中共有N对这样的数据对,则定义MAE为:

 

在CF推荐系统中,MAE越小,算法质量越高。

六:CF算法一些改进

1.相关相似性改进

当用户评分数据不完整时,两个用户共同评分的项目集自然更小。在比较小的项目集上的评分相似性,不能用以确定它们的相似性的高低。同时,由于只是在用户共同评分过的项目的交集上度量用户之间的相似性,可能丢弃大量可利用的信息,因此得到的最近邻居也不够准确。

 

相似度计算法公式修正为:

 

改进后的算法如下:

输入:用户-项目评价矩阵R,邻居个数N,目标用户U,目标项目I

输出:预测用户评价分数P,推荐集R。

 

开始

   For 每个U in 所有的用户

      For 每个I which U rate

         If U rate item  //如果u参与了对item项的评分

            Put  item into user[]

                则把item放到用户与U共同选择的集合项目中

        End if

     Next item

     Compute sim(u,v)

  Next U

Select top N user from all users

For  i=1 to N

   If user rate item1

     Ri,j=score(i,j)

   Else

Ri,j=avg(相同类商品的平均评分)

   End if

Sum=sum+sim(u,v)*(Rb,j-avg(u))

Next i

K=1/sim(u,v);

P=avg(u)+k*sum

End

2 稀疏性问题的解决

传统的方法,是大部分方法的核心思想都是对稀疏矩阵进行刚性的值填充,并没有考虑到用户个性相似的客观事实。

本文提出一种改进策略,首先在最近邻居集里计算目标用户与最近邻居之间的相似度,针对每个最近邻用户都产生一个预测值,即:

 

     

 

                                 

 

  

                      

表示目标客户a的最近邻居集内的用户i对项目y的预测值,Pi,y表示用户i对项目y的评价值,sim(i,a)表示目标用户a与最近邻居集内的用户i的相似度,Pa,Pi分别表示目标用户和最近邻居集内用户i的评价均值。由此形成一个虚拟的预测评价矩阵,然后在这个虚拟预测评价矩阵基础进行加权均值预测

在得到每个相似用户对项目y的预测值的基础上,通过下式计算可得到最后的目标用户对项目y的预测值。

 

七:推荐算法:

1.  寻找和自己兴趣相似的人

// 寻找与自己有相似品味的影评者

Def topMathches(prefs, person, n=5,similarity=sim_pearson):

   Scores=[(similarity(prefs,person,other),other) for other in prefs if other!=person]

//对列表进行排序,评价值最高者排在最前面

Scores.sort()

Scores.reverse()

Return scores[0:n];

 

2. 推荐物品

如果单纯的用上面的方法找到和自己品味相同的人,然后再从他看过的,但是自己没有看过的影片中,推荐给自己,这样太随意了。因为也许有些影片,这些评论者还未对其评论过,恰恰这些影片是自己喜欢的;还有一种可能就是,我们也许找到一个热衷某部影片的古怪评论者,而根据topMatches所返回的结果,所有其他的评论者都不看好这部影片。

为了解决上述问题,我们须要通过一个加权的平均值来为影片打分,评论者的评分结果因此形成了先后的排名。为此,我们须要取得所有其他评论者的评价结果,借此得到相似度后,在乘以他们为每部影片所给的评价值。

 

改进之后的加权值推荐算法:

Def getRecommendations(prefs,person,similarity=sim_pearson)

Totals={};

simSums={};

for other in prefs:

//不要和自己做比较

  If other==person

      Continue;

  Else

     Sim=similarity(prefs,person,other)

  End if

  If sim<=0

     Continue;

  For item not in prefs[person] or prefs[person][item]==0

      //相似度*评价值

      Totals.setdefault(item,0)

      Totals[item]+=prefs[other][item]*sim

    //相似度之和

    simSums.setdefault(item,0)

    simSums[item]+=sim

 end for

End for

//建立一个归一化的列表

Rankings=[(total/simSums[item],item) for item, total in totals.items()]

//返回经过排序的列表

Rankings.sort()

Rankings.reverse()

Return rankings

Exit

3. 匹配物品

上述的是计算用户之间的相似度,如果我们现在计算物品之间的相似度,同样可以使用上述方法,只是我们需要将人员与物品对换即可。

Def transformPrefs(prefs):

Result={}

For person in prefs:

   For item in prefs[person]:

     Result.setdefault(item,{})

     //将物品与人员对调

     Result[item][person]=prefs[person][item]

End for

Return result

  1. 构造数据集

//对于选出来的最受欢迎的url链接,选出标记最受欢迎链接的用户

Def initializeUserDict(tag,count=5):

   User_dict={}

   //获取前count个最受欢迎的链接张贴记录

   For p1 in get_popular(tag=tag)[0: count]:

      // 查找所有张贴该链接的用户

      For p2 in get_urlposts(p1[‘herf’]):

        User=p2[‘user’]

        User_dict[user]={}

      End for

  End for

Return user_dict

 

接下来,对于上述选出来的用户,接下来的算法是要求出这些用户所标记的所有链接:

Def fillItems(user_dict):

   All_items={};

   For user in user_dict:

     For I in range(3):

       Try:

        Posts=get_userposts(user)

        Break;

      Except:

        Print “fail”

      For post in posts:

         url=post[‘href’]

         user_dict[user][url]=1.0

         all_items[url]=1

      end for

end for

//用0填充缺少的项

   For ratings in user_dict.values():

       For item  in all_items:

         If  item not in ratings:

            Ratings[item]=0.0

       End for

   End for

  1. 基于物品的过滤

物品间的比较不会像用户间的比较那么频繁变化

1)  构造物品比较数据集

构造一个包含相近物品的完整数据集,之后推荐的时候,就可以直接使用了,无须再重复计算了。

Def calculateSimilarItems(prefs,n=10)

   //建立字典,已给出与这些物品最为相近的所有其他物品

Result={};

//以物品为中心对偏好矩阵实施倒置处理

itemPrefs=transformPrefs(prefs)

c=0

for item in itemPrefs:

  c+=1

  if c%100==0 : print “%d /%d” % (c,len(itemPrefs))

  //寻找最为相近的物品

  Scores=topMatches(itemPrefs,item,n=n,similarity=sim_distance)

  Result[item]=scores

End for

     Return result

 

2)  获得推荐

Def getRecommendedItems(prefs,itemMatch,user):

   userRatings=prefs[user]

   scores={}

   totalSim={}

   //循环遍历由当前用户评分的物品

   For(item, rating) in userRatings.items():

     //循环遍历与当前物品相近的物品

     For(similarity, item2) in itemMatch[item]:

        //如果该用户已经对当前物品做过评价,则将其忽略

         If item2 in userRatings: continue

        //评价值与相似度的加权之和

        Scores.setdefault(item2,0)

        Scores[item2]+=similarity*rating

        // 全部相似度之和

        totalSim.setdefault(item2,0)

        totalSim[item2]+=similarity

end for

end for

//将每个合计值除以加权和,求出平均值

Rankings=[(score/totalSim[item],item) for item, score in scores.items()]

//按最高值到最低值的顺序,返回评分结果

Rankings.sort()

Ranking.reverse()

      Return rankings

 

7 基于用户过滤还是基于物品过滤

对于稀疏的数据集,基于物品的过滤方法通常要优于基于用户的过滤方法,而对于秘籍数据集而言,两者的效果几乎是一样的。

基于用户的过滤更加易于实现,而且无需额外步骤,因此它通常更适合用户规模较小的变化非常频繁的内存数据集。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值