SlopeOne推荐算法

       Slope One 算法 是一种基于评分的预测算法, 本质上也是一种基于项目的算法。与一般的基于项目的算法不同, 该算法不计算项目之间的相似度, 而是用一种简单的线性回归模型进行预测(可以扩展) 算法易于实现, 计算速度快, 可扩展性好, 同时对数据稀疏性有较好的适应性。
       例如下面表格里有3个用户对4个物品的评分
 
101
102
103
104
UserX 5
3.5
 
 
UserY
2
5
4
2
UserZ
4.5
3.5
1
4
      求物品两两之间的差值平均分:
        物品102和101:{(3.5-5)+(5-2)+(3.5-4.5)}/3=0.5/3
      物品103跟101:{(4-2)+(1-4.5)}/2=-1.5/2
      物品104跟101:{(2-2)+(4-4.5)}/2=-0.5/2
      物品103跟102:{(4-5)+(1-3.5)}/2=-3.5/2
      物品104跟102:{(2-5)+(4-3.5)}/2=-2.5/2
      物品104跟103:{(2-4)+(4-1)}/2=1/2
能得到下面表格
 
101
102
103
104
101
 
 
 
 
102
0.17
 
 
 
103
-0.75
-1.75
 
 
104
-0.25
-1.25
0.5
 
       OK,现在准备工作已经完成了,然后进行推荐,例如对X用户进行推荐,103和104个预测评分根据101、102的评分来的。
       X预测103评分={(-0.75+5)+(-1.75+3.5)}/2=(4.25+1.75)/2=3
       X预测104评分={(-0.25+5)+(-1.25+3.5)}/2=(4.75+2.25)/2=3.5
       那么给X用户推荐的顺序就是:先推荐104在推荐103
       实战经验:可以看出该算法对评分质量要求非常高,那么如果某一个物品的平均分高的话,那么该物品就非常容易被推荐。
       下面代码是基于Mahout的SlopeOne算法调用:
 
  1 import java.io.BufferedReader;
  2 
  3 import java.io.BufferedWriter;
  4 
  5 import java.io.File;
  6 
  7 import java.io.FileNotFoundException;
  8 
  9 import java.io.FileReader;
 10 
 11 import java.io.FileWriter;
 12 
 13 import java.io.IOException;
 14 
 15 import java.util.List;
 16 
 17 import org.apache.commons.cli2.OptionException;
 18 
 19 import org.apache.mahout.cf.taste.common.TasteException;
 20 
 21 import org.apache.mahout.cf.taste.impl.common.LongPrimitiveIterator;
 22 
 23 import org.apache.mahout.cf.taste.impl.model.file.FileDataModel;
 24 
 25 import org.apache.mahout.cf.taste.impl.recommender.CachingRecommender;
 26 
 27 import org.apache.mahout.cf.taste.impl.recommender.slopeone.SlopeOneRecommender;
 28 
 29 import org.apache.mahout.cf.taste.model.DataModel;
 30 
 31 import org.apache.mahout.cf.taste.recommender.RecommendedItem;
 32 
 33 
 34 public class App 
 35 
 36 {  
 37 
 38     static final String inputFile = "/mnt/new/ml-1m/ratings.dat";
 39 
 40     static final String outputFile = "/mnt/new/ml-1m/ratings.csv";
 41 
 42     
 43 
 44     public static void main( String[] args ) throws IOException, TasteException, OptionException
 45 
 46     {
 47 
 48         CreateCsvRatingsFile();    
 49 
 50        //创建模型数据源文件      
 51 
 52         File ratingsFile = new File(outputFile);  
 53 
 54         DataModel model = new FileDataModel(ratingsFile);
 55 
 56         // SlopeOne算法
 57 
 58         CachingRecommender cachingRecommender = new CachingRecommender(new SlopeOneRecommender(model));
 59 
 60         // 对所有用户进行推荐
 61 
 62         for (LongPrimitiveIterator it = model.getUserIDs(); it.hasNext();){
 63 
 64             long userId = it.nextLong();     
 65 
 66             // 对单个User进行推荐
 67 
 68             List<RecommendedItem> recommendations = cachingRecommender.recommend(userId, 10);
 69 
 70 
 71             // 该用户无推荐结果
 72 
 73             if (recommendations.size() == 0){
 74 
 75                 System.out.print("User ");
 76 
 77                 System.out.print(userId);
 78 
 79                 System.out.println(": no recommendations");
 80 
 81             }                 
 82 
 83             // 打印推荐信息
 84 
 85             for (RecommendedItem recommendedItem : recommendations) {
 86 
 87                 System.out.print("User ");
 88 
 89                 System.out.print(userId);
 90 
 91                 System.out.print(": ");
 92 
 93                 System.out.println(recommendedItem);
 94 
 95             }
 96 
 97         }                
 98 
 99     }
100 
101  
102     //读文件前1000行作为模型输入
103     private static void CreateCsvRatingsFile() throws FileNotFoundException, IOException {
104 
105 
106         BufferedReader br = new BufferedReader(new FileReader(inputFile));        
107 
108         BufferedWriter bw = new BufferedWriter(new FileWriter(outputFile));
109 
110 
111 
112         String line = null;
113 
114         String line2write = null;
115 
116         String[] temp;
117 
118 
119         int i = 0;
120 
121         while ((line = br.readLine()) != null && i < 1000)
122 
123         {
124 
125             i++;
126 
127             temp = line.split("::");
128 
129             line2write = temp[0] + "," + temp[1];
130 
131             bw.write(line2write);
132 
133             bw.newLine();
134 
135             bw.flush();
136 
137         }        
138 
139         br.close();
140 
141         bw.close();
142 
143     } 
144 
145 }

参考资料:1,Mahout cookbook;2,http://weibo.com/bicloud 网友写的SlopeOnePPT

posted @ 2014-02-18 10:30  kobeshow  阅读(4589)  评论(0编辑  收藏  举报