Mahout笔记--代码分析

本文介绍了Mahout推荐系统的实现原理及评估方法,包括基于用户的推荐、基于物品的推荐等多种算法,并详细展示了如何通过Mahout进行推荐系统精确度的评估。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

推荐系统介绍——Mahout笔记之一


  Mahout有很多推荐的实现,各有特点,在这里一并记录。 
    GenericUserBasedRecommender: 基于用户的推荐,用户数量相对较少时速度较快。 
    GenericItemBasedRecommender:基于物品的推荐,物品数量较少时速度较快,外部提供了物品相似度数据后会更加有效率。 
    SlopeOneRecommender:基于slope-one算法(想想那个填空的表格吧)的推荐,在线推荐或更新比较快,需要先下大量的预处理运算。物品数量相对较少时使用比较合适。 
    SVDRecommender:效果不错,和slope-one一样,事先需要大量的预处理运算。 
    KnnItemBasedRecommender:基于最近邻算法的推荐器,物品数量较小时表现良好。 
    TreeClusteringRecommender:基于聚类的推荐器,在线推荐较快,同时也需要事先大量预处理运算,用户数量相对较少时表现良好。


准备开始看Mahout in action~
Mahout是Java写的知名推荐系统工具之一,看的目的不是使用Mahout,目的是通过这份资料了解Mahout是怎么做的。

首先看第二章,推荐系统介绍。
Mahout可以处理的User ID和Item ID需要是整数,打分(Preference)可以是任意数值,大的数值代表更喜欢。
输入文件需要是csv格式,每行三个数字分别代表:User ID, Item ID, Preference
例如

1,101,5.0
2,101,2.0

代表1号用户给101号物品打5.0分,2号用户给101号物品打2.0分。
有了数据文件,就可以利用Mahout写一个简单的推荐系统代码了。

DataModel model = new FileDataModel(new File("intro.csv"));
//建立DataModel对象存储数据文件
UserSimilarity similarity = new PearsonCorrelationSimilarity(model);
//计算用户相似度矩阵
UserNeighborhood neighborhood = new NearestNUserNeighborhood (2, similarity, model);
//对每个用户找出2个最相似用户
Recommender recommender =
 new GenericUserBasedRecommender(model, neighborhood, similarity);
//建立UserCF推荐系统
List<RecommendedItem> recommendations = recommender.recommend(1, 1);
//为用户1推荐1个Item

以上是一个简单例子,留个印象,可以先不用纠结。
然后就是需要一个推荐系统精确度衡量标准,衡量标准有MAE(误差绝对值的平均值)和RMSE(误差平方求平均再开根)等。
可以同样看一个简单例子,Mahout衡量推荐系统精确度的

RandomUtils.useTestSeed();
//用来使得每次随机都一样,仅限用于测试,不要在实际中使用
DataModel model = new FileDataModel(new File("intro.csv"));
RecommenderEvaluator evaluator = new AverageAbsoluteDifferenceRecommenderEvaluator();
//使用MAE作为衡量标准,如果用RMSE则是 RMSRecommenderEvaluator
RecommenderBuilder builder = new RecommenderBuilder() {
  @Override
  public Recommender buildRecommender(DataModel model) throws TasteException {
    UserSimilarity similarity = new PearsonCorrelationSimilarity (model);
    UserNeighborhood neighborhood = new NearestNUserNeighborhood (2, similarity, model);
    return new GenericUserBasedRecommender (model, neighborhood, similarity);
  }
};
double score = evaluator.evaluate(builder, null, model, 0.7, 1.0);
//随机使用70%数据做为训练,另外30%作为测试,
//最后一个参数1.0表示使用全部的数据,如果数据太大,
//可以只用一部分数据去近似衡量推荐系统准确度,
//在仅有小改动之后做部分数据测试比较快捷。

然后除了这种精确度衡量方式,Mahout还提供其他方式。这主要是因为:在实际推荐系统中,很多情况下并没有必要准确预测打分,而只需要对待推荐物品排序,由最好到最差,就足够了。另外还有一个原因是,对于部分问题,输入数据是布尔类型的,也即我们只知道用户是否偏好,但是没有打分。
Mahout提供了精确率(Precision)和召回率(recall)两种方案:精确率是指推荐排名前列中,有多少是好的推荐(good recommendation);召回率是指好的推荐中,有多少个排在推荐排名前列。
这样我们还需要定义什么是好的推荐。
先来看看代码:

RecommenderIRStatsEvaluator evaluator = new GenericRecommenderIRStatsEvaluator ();
IRStatistics stats = evaluator.evaluate(
    recommenderBuilder, null, model, null, 2, //推荐2个,计算准确率和召回率
    GenericRecommenderIRStatsEvaluator.CHOOSE_THRESHOLD, 
    1.0);
System.out.println(stats.getPrecision());//输出准确率
System.out.println(stats.getRecall()); //输出召回率

假设有这样的一组数据

5,101,4.0
5,102,3.0
5,103,2.0
5,104,4.0
5,105,3.5
5,106,4.0

再假设前三行出现在测试集中,则由于101物品的分数高,所以他是好的推荐(good recommendation),而102和103都是有效的,但不是好的。但是这又有一个问题,分数到多少算分数高?你可以传进一个参数自己指定一个阈值(threshold),也可以让系统指定。
系统指定阈值的方案为:计算用户打分的均值和标准差,则阈值=均值+标准差。这样通常有大约16%的打分被选中(假设打分呈正态分布)。
文中指出了这种方式存在的问题,推荐的物品其实并不必要是已知的才说明推荐得好。一个更复杂的情况是如果输入数据是布尔类型(只知道是否喜欢),则无法选择阈值,只能是从喜欢的物品中随机选择一些用于测试。
文中还使用了GroupLens数据实际测试做例子,这里就不关注了。

运行一个RecommenderIRStatsEvaluator

Mahout提供了一个简单的途径去计算推荐器的精度等值.

可以试着运行一下代码


RandomUtils.useTestSeed();   
DataModel model = new FileDataModel(new File("intro.csv"));   
   
RecommenderIRStatsEvaluator evaluator =   
  new GenericRecommenderIRStatsEvaluator();   
RecommenderBuilder recommenderBuilder = new RecommenderBuilder() {   
  @Override   
  public Recommender buildRecommender(DataModel model)    
      throws TasteException {   
    UserSimilarity similarity = new PearsonCorrelationSimilarity(model);   
    UserNeighborhood neighborhood =   
      new NearestNUserNeighborhood(2, similarity, model);   
    return    
      new GenericUserBasedRecommender(model, neighborhood, similarity);   
  }   
};   
IRStatistics stats = evaluator.evaluate(   
    recommenderBuilder, null, model, null, 2,    
    GenericRecommenderIRStatsEvaluator.CHOOSE_THRESHOLD,    
    1.0); A   
   
System.out.println(stats.getPrecision());   
System.out.println(stats.getRecall());    


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值