mahout推荐算法——协同过滤推荐算法(java代码实现)

来源:互联网 发布:黑龙江统计局数据库 编辑:程序博客网 时间:2024/06/06 06:13

什么是协同过滤

协同过滤是利用集体智慧的一个典型方法。要理解什么是协同过滤 (Collaborative Filtering, 简称 CF),首先想一个简单的问题,如果你现在想看个电影,但你不知道具体看哪部,你会怎么做?大部分的人会问问周围的朋友,看看最近有什么好看的电影推荐,而我们一般更倾向于从口味比较类似的朋友那里得到推荐。这就是协同过滤的核心思想。

协同过滤一般是在海量的用户中发掘出一小部分和你品位比较类似的,在协同过滤中,这些用户成为邻居,然后根据他们喜欢的其他东西组织成一个排序的目录作为推荐给你。当然其中有一个核心的问题:

  • 如何确定一个用户是不是和你有相似的品位?
  • 如何将邻居们的喜好组织成一个排序的目录?

协同过滤相对于集体智慧而言,它从一定程度上保留了个体的特征,就是你的品位偏好,所以它更多可以作为个性化推荐的算法思想。可以想象,这种推荐策略在 Web 2.0 的长尾中是很重要的,将大众流行的东西推荐给长尾中的人怎么可能得到好的效果,这也回到推荐系统的一个核心问题:了解你的用户,然后才能给出更好的推荐。


协同过滤的步骤是:
  创建数据模型 —> 用户相似度算法—>用户近邻算法 —>推荐算法。
  基于用户的协同过滤算法在Mahout库中已经模块化了,通过4个模块进行统一的方法调用。首先,创建数据模型(DataModel),然后定义用户的相似度算法(UserSimilarity),接下来定义用户近邻算法(UserNeighborhood ),最后调用推荐算法(Recommender)完成计算过程。而基于物品的协同过滤算法(ItemCF)过程也是类似的,去掉第三步计算用户的近邻算法就行了。

计算推荐

经过前期的计算已经得到了相邻用户和相邻物品,下面介绍如何基于这些信息为用户进行推荐。基于协同过滤的推荐算法可以分为基于用户的 CF 和基于物品的 CF,下面我们深入介绍这两种方法的计算方法

基于用户的 CF(User CF)

基于用户的 CF 的基本思想相当简单,基于用户对物品的偏好找到相邻邻居用户,然后将邻居用户喜欢的推荐给当前用户。计算上,就是将一个用户对所有物品的偏好作为一个向量来计算用户之间的相似度,找到 K 邻居后,根据邻居的相似度权重以及他们对物品的偏好,预测当前用户没有偏好的未涉及物品,计算得到一个排序的物品列表作为推荐。图 2 给出了一个例子,对于用户 A,根据用户的历史偏好,这里只计算得到一个邻居 - 用户 C,然后将用户 C 喜欢的物品 D 推荐给用户 A。

图 2.基于用户的 CF 的基本原理
图 2 基于用户的 CF 的基本原理

基于物品的 CF(Item CF)

基于物品的 CF 的原理和基于用户的 CF 类似,只是在计算邻居时采用物品本身,而不是从用户的角度,即基于用户对物品的偏好找到相似的物品,然后根据用户的历史偏好,推荐相似的物品给他。从计算的角度看,就是将所有用户对某个物品的偏好作为一个向量来计算物品之间的相似度,得到物品的相似物品后,根据用户历史的偏好预测当前用户还没有表示偏好的物品,计算得到一个排序的物品列表作为推荐。图 3 给出了一个例子,对于物品 A,根据所有用户的历史偏好,喜欢物品 A 的用户都喜欢物品 C,得出物品 A 和物品 C 比较相似,而用户 C 喜欢物品 A,那么可以推断出用户 C 可能也喜欢物品 C。

图 3.基于物品的 CF 的基本原理
图 3 基于物品的 CF 的基本原理

Java代码:

UserCF:

package com.pt;import org.apache.mahout.cf.taste.common.TasteException;import org.apache.mahout.cf.taste.impl.common.LongPrimitiveIterator;import org.apache.mahout.cf.taste.impl.model.file.*;  import org.apache.mahout.cf.taste.impl.neighborhood.*;  import org.apache.mahout.cf.taste.impl.recommender.*;  import org.apache.mahout.cf.taste.impl.similarity.*;  import org.apache.mahout.cf.taste.model.*;   import org.apache.mahout.cf.taste.recommender.*;  import org.apache.mahout.cf.taste.similarity.*;  import java.io.*;  import java.util.*;  public class UserCF {    final static int NEIGHBORHOOD_NUM = 2;//临近的用户个数    final static int RECOMMENDER_NUM = 3;//推荐物品的最大个数    public static void main(String[] args) throws IOException, TasteException {        String file = "src/data/testCF.csv";        DataModel model = new FileDataModel(new File(file));//数据模型        UserSimilarity user = new EuclideanDistanceSimilarity(model);//用户相识度算法        NearestNUserNeighborhood neighbor = new NearestNUserNeighborhood(NEIGHBORHOOD_NUM, user, model);        //用户近邻算法        Recommender r = new GenericUserBasedRecommender(model, neighbor, user);//用户推荐算法        LongPrimitiveIterator iter = model.getUserIDs();///得到用户ID        while (iter.hasNext()) {            long uid = iter.nextLong();            List<RecommendedItem> list = r.recommend(uid, RECOMMENDER_NUM);            System.out.printf("uid:%s", uid);            for (RecommendedItem ritem : list) {                System.out.printf("(%s,%f)", ritem.getItemID(), ritem.getValue());            }            System.out.println();        }    }} 

ItemCF:

package com.pt;import java.io.File;import java.io.IOException;import java.util.List;import org.apache.mahout.cf.taste.common.TasteException;import org.apache.mahout.cf.taste.impl.common.LongPrimitiveIterator;import org.apache.mahout.cf.taste.impl.model.file.FileDataModel;import org.apache.mahout.cf.taste.impl.recommender.GenericItemBasedRecommender;import org.apache.mahout.cf.taste.impl.similarity.EuclideanDistanceSimilarity;import org.apache.mahout.cf.taste.model.DataModel;import org.apache.mahout.cf.taste.recommender.RecommendedItem;import org.apache.mahout.cf.taste.recommender.Recommender;import org.apache.mahout.cf.taste.similarity.ItemSimilarity;public class ItemCF {final static int RECOMMENDER_NUM = 3;//推荐物品的最大个数public static void main(String[] args) throws IOException, TasteException {String file = "src/data/testCF.csv";        DataModel model = new FileDataModel(new File(file));//数据模型        ItemSimilarity item=new EuclideanDistanceSimilarity(model);//用户相识度算法        Recommender r=new GenericItemBasedRecommender(model,item);//物品推荐算法        LongPrimitiveIterator iter =model.getUserIDs();        while(iter.hasNext()){        long uid=iter.nextLong();        List<RecommendedItem> list = r.recommend(uid, 1);        System.out.printf("uid:%s",uid);        for (RecommendedItem ritem : list) {                System.out.printf("(%s,%f)", ritem.getItemID(), ritem.getValue());            }            System.out.println();        }}}

数据集:

第一列:userid;第二列:itemid;第三列评分。

1,101,5.01,102,3.01,103,2.52,101,2.02,102,2.52,103,5.02,104,2.03,101,2.53,104,4.03,105,4.53,107,5.04,101,5.04,103,3.04,104,4.54,106,4.05,101,4.05,102,3.05,103,2.05,104,4.05,105,3.55,106,4.0 


原创粉丝点击