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
|
|
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