Mahout推荐算法编程实践

时间:2022-12-07 16:09:36

Mahout推荐算法编程实践


引言Taste是曾经风靡一时的推荐算法框架,后来被并入Mahout中,Mahout的部分推荐算法基于Taste实现。下文介绍基于Taste实现最常用的UserCF和ItemCF。本文不涉及UserCF和ItemCF算法的介绍,这方面网上资料很多,本文仅介绍如何基于Mahout编程实现。

步骤一:构建数据模型UserCF和ItemCF算法的输入数据是用户偏好,用户偏好数据可以有两种形式:
  • 包含用户对目标评分的【用户ID,itemID,评分】 
  • 不包含评分的【用户ID,itemID】 
推荐算法的第一步是基于数据源构建数据模型,Taste构建数据模型的数据源可以有很多,比如JDBC,文件等。下面仅介绍最常用的文件数据源:
  • 用户偏好数据包含评分 
示例代码:DataModel dm = new FileDataModel(new File("E:\\testdata\\3columns")); 
  • 用户偏好数据不包含评分 
示例代码:DataModel dm = new  GenericBooleanPrefDataModel(GenericBooleanPrefDataModel.toDataMap(new FileDataModel(new File("E:\\testdata\\2columns"))));
步骤二:指定距离(相似度)计算方法创建好数据模型后,第二步需要指定一种计算“距离”的方法,因为在后续的步骤中需要计算user或item之间的“距离”。Taste提供的计算距离的方法很多,以下仅介绍常用的方法:
  • 用户偏好数据包含评分    
欧氏距离:EuclideanDistanceSimilarity皮尔森距离:PearsonCorrelationSimilarity余弦距离:UncenteredCosineSimilarity
  • 用户偏好数据不包含评分   
曼哈顿距离:CityBlockSimilarity对数似然距离: LogLikelihoodSimilarity
示例代码:UserSimilarity us = new  CityBlockSimilarity(dm);ItemSimilarity is  = new  CityBlockSimilarity(dm); 

步骤三(仅UserCF需要):选择近邻算法如果选择使用UserCF算法做推荐,则在完成相似度计算方法的指定后,需要指定近邻算法。Mahout推荐算法编程实践
  • NearestNUserNeighborhood 
指定距离最近的N个用户作为邻居。示例:UserNeighborhood unb = new NearestNUserNeighborhood(10, us, dm);三个参数分别是: 邻居的个数,用户相似度,数据模型    
  • ThresholdUserNeighborhood 
指定距离最近的一定百分比的用户作为邻居。
示例:UserNeighborhood unb = new ThresholdUserNeighborhood(0.2, us, dm); 
三个参数分别是: 阀值(取值范围0到1之间),用户相似度,数据模型

步骤四:创建推荐器实施推荐算法的最后一步就是创建推荐引擎,Taste为UserCF和ItemCF算法,针对有用户评分和没用户评分的情况,分别提供了推荐器:
  • 用户偏好数据包含评分   
示例代码:UserCF:Recommender re = new  GenericUserBasedRecommender(dm, unb, us);ItemCF:Recommender re = new  GenericItemBasedRecommender(dm, is);
  • 用户偏好数据不包含评分   
示例代码:UserCF:Recommender re = new  GenericBooleanPrefUserBasedRecommender(dm, unb, us);ItemCF:Recommender  re = new  GenericBooleanPrefItemBasedRecommender(dm, is);
题外话:
通过召回率和查准率的测试, CityBlockSimilarity + UserCF 的推荐效果最好。
示例代码:用户偏好数据不包含评分 + CityBlockSimilarity + UserCF
  • 用户偏好数据 
1,1011,1021,1032,1012,1022,1032,1043,1013,1043,1053,1074,1014,1034,1044,1065,1015,1025,1035,1045,1055,106
  • 代码 
import java.io.File;import java.util.List;import org.apache.mahout.cf.taste.impl.model.GenericBooleanPrefDataModel;import org.apache.mahout.cf.taste.impl.model.file.FileDataModel;import org.apache.mahout.cf.taste.impl.neighborhood.NearestNUserNeighborhood;import org.apache.mahout.cf.taste.impl.recommender.GenericBooleanPrefUserBasedRecommender;import org.apache.mahout.cf.taste.impl.similarity.CityBlockSimilarity;import org.apache.mahout.cf.taste.model.DataModel;import org.apache.mahout.cf.taste.neighborhood.UserNeighborhood;import org.apache.mahout.cf.taste.recommender.RecommendedItem;import org.apache.mahout.cf.taste.recommender.Recommender;import org.apache.mahout.cf.taste.similarity.UserSimilarity;public class UserCFRecommender {     public  static  void main(String[] args)  throws Exception {        // 创建数据模型,不包含用户评分        DataModel dm =  new GenericBooleanPrefDataModel(                GenericBooleanPrefDataModel                        .toDataMap( new FileDataModel( new File("E:\\testdata\\2columns"))));        // 使用曼哈顿距离计算相似度        UserSimilarity us =  new CityBlockSimilarity(dm);
        //指定NearestNUserNeighborhood作为近邻算法        UserNeighborhood unb =  new NearestNUserNeighborhood(10, us, dm);                // 构建不包含用户评分的UserCF推荐器        Recommender re =  new GenericBooleanPrefUserBasedRecommender(dm, unb, us);                // 输出推荐结果,为1号用户推荐5个商品        List<RecommendedItem> list = re.recommend(1, 5);         for (RecommendedItem recommendedItem : list) {            System. out.println(recommendedItem.getItemID()+" : "+recommendedItem.getValue());   
        }    }}