hadoop学习-Netflix电影推荐系统

1、推荐系统概述

电子商务网站是推荐系统应用的重要领域之一,当当网的图书推荐,大众点评的美食推荐,QQ好友推荐等等,推荐无处不在。

从企业角度,推荐系统的应用可以增加销售额等等,对于用户而言,系统仿佛知道我们的喜好并给出推荐也是非常美妙的事情。

推荐算法分类:

按数据使用划分:

  • 协同过滤算法:UserCF, ItemCF, ModelCF
  • 基于内容的推荐: 用户内容属性和物品内容属性
  • 社会化过滤:基于用户的社会网络关系

按模型划分:

  • 最近邻模型:基于距离的协同过滤算法
  • Latent Factor Mode(SVD):基于矩阵分解的模型
  • Graph:图模型,社会网络图模型


本文采用协同过滤算法来实现电影推荐。下面介绍下基于用户的协同过滤算法UserCF和基于物品的协同过滤算法ItemCF原理。

基于用户的协同过滤算法UserCF

基于用户的协同过滤,通过不同用户对物品的评分来评测用户之间的相似性,基于用户之间的相似性做出推荐。简单来讲就是:给用户推荐和他兴趣相似的其他用户喜欢的物品。

hadoop学习-Netflix电影推荐系统_第1张图片

更多关于算法实现可参考Mahout In Action这本书

基于物品的协同过滤算法ItemCF
基于item的协同过滤,通过用户对不同item的评分来评测item之间的相似性,基于item之间的相似性做出推荐。简单来讲就是:给用户推荐和他之前喜欢的物品相似的物品。
用例说明:

hadoop学习-Netflix电影推荐系统_第2张图片

更多关于算法实现可参考Mahout In Action这本书

目前商用较多采用该算法。

2、数据源

切入正题,本文采用的数据源是Netflix公司的电影评分数据。Netflix是一家以在线电影租赁为生的公司。他们根据网友对电影的打分来判断用户有可能喜欢什么电影,并结合会员看过的电影以及口味偏好设置做出判断,混搭出各种电影风格的需求。

Netflix数据下载:

完整数据集:http://www.lifecrunch.biz/wp-content/uploads/2011/04/nf_prize_dataset.tar.gz

3、算法模型 MapReduce实现

先看下数据格式;

1,101,5.0
1,102,3.0
1,103,2.5
2,101,2.0
2,102,2.5
2,103,5.0
2,104,2.0
3,101,2.0
3,104,4.0
3,105,4.5
3,107,5.0
4,101,5.0
4,103,3.0
4,104,4.5
4,106,4.0
5,101,4.0
5,102,3.0
5,103,2.0
5,104,4.0
5,105,3.5
5,106,4.0
每行3个字段,依次是用户ID,电影ID,用户对电影的评分(0-5分,每0.5为一个评分点!)

算法实现过程:

  1. 建立物品的同现矩阵
  2. 建立用户对物品的评分矩阵
  3. 矩阵计算推荐结果

1)建立物品的同现矩阵

按照用户选择,在每个用户选择的物品中,将两两同时出现的物品次数记录下来。

      [101] [102] [103] [104] [105] [106] [107]
[101]   5     3     4     4     2     2     1
[102]   3     3     3     2     1     1     0
[103]   4     3     4     3     1     2     0
[104]   4     2     3     4     2     2     1
[105]   2     1     1     2     2     1     1
[106]   2     1     2     2     1     2     0
[107]   1     0     0     1     1     0     1
该矩阵表示 ID为101 102的电影 同时被一个用户评分的次数为3。该矩阵是一个对称矩阵。

2)建立用户对物品的评分矩阵

按用户分组,找到每个用户所选的物品及评分

       3
[101] 2.0
[102] 0.0
[103] 0.0
[104] 4.0
[105] 4.5
[106] 0.0
[107] 5.0
表示ID为3的用户的评分数据

3)将以上2个矩阵相乘

      [101] [102] [103] [104] [105] [106] [107]              3         R
[101]   5     3     4     4     2     2     1               2.0       40.0
[102]   3     3     3     2     1     1     0               0.0       18.5
[103]   4     3     4     3     1     2     0               0.0       24.5
[104]   4     2     3     4     2     2     1       ×      4.0   =   40.0
[105]   2     1     1     2     2     1     1               4.5       26.0
[106]   2     1     2     2     1     2     0               0.0       16.5
[107]   1     0     0     1     1     0     1               5.0       16.5
R列分数最高的就是推荐结果;

这里为什么是2个矩阵相乘,结果的分数越高就是推荐结果呢。

简单分析如下:

当前ID为3的用户对ID为107的电影评分较高,可以理解为该用户喜欢这种类型的电影。

因此如果有一部电影和ID为107电影同时出现的次数越高,则可以理解为该电影和107电影比较类似,那么我们就可以将其推荐给用户3,也许他会喜欢。

这里同时出现的次数指的是很多用户都看过这2部电影,也就是我们说的这2部电影比较类似。

上面的矩阵中,我们可以看到104电影和107电影同时出现的次数为1,假设次数为10 ,那么R矩阵的结果会是:

 R
40.0
18.5
24.5
<span style="color:#ff0000;">85.0</span>
26.0
16.5
16.5
最大值变成85.0,那么我们可以推荐104电影给用户3观看。

以上是该算法的简单分析,详细原理介绍可以看Mahout In Action这本书

4、源代码实现

Recommend.java

[java] view plain copy
  1. import java.util.HashMap;  
  2. import java.util.Map;  
  3.   
  4. public class Recommend {  
  5.     public static void main(String[] args) throws Exception {  
  6.         Map<String, String> path = new HashMap<String, String>();  
  7.         path.put("data", args[0]);  
  8.         path.put("Step1Input", args[1]);  
  9.         path.put("Step1Output", path.get("Step1Input") + "/step1");  
  10.         path.put("Step2Input", path.get("Step1Output"));  
  11.         path.put("Step2Output", path.get("Step1Input") + "/step2");  
  12.         path.put("Step3Input1", path.get("Step1Output"));  
  13.         path.put("Step3Output1", path.get("Step1Input") + "/step3_1");  
  14.         path.put("Step3Input2", path.get("Step2Output"));  
  15.         path.put("Step3Output2", path.get("Step1Input") + "/step3_2");  
  16.   
  17.         path.put("Step5Input1", path.get("Step3Output1"));  
  18.         path.put("Step5Input2", path.get("Step3Output2"));  
  19.         path.put("Step5Output", path.get("Step1Input") + "/step5");  
  20.           
  21.         path.put("Step6Input", path.get("Step5Output"));  
  22.         path.put("Step6Output", path.get("Step1Input") + "/step6");   
  23.         Step1.step1Run(path);  
  24.         Step2.step2Run(path);  
  25.         Step3.step3Run1(path);  
  26.         Step3.step3Run2(path);  
  27.   
  28.         Step4_1.run(path);  
  29.         Step4_2.run(path);  
  30.         System.exit(0);  
  31.     }  
  32. }  

Step1.java

[java] view plain copy
  1. import java.io.IOException;  
  2. import java.util.Iterator;  
  3. import java.util.Map;  
  4.   
  5. import org.apache.hadoop.conf.Configuration;  
  6. import org.apache.hadoop.fs.Path;  
  7. import org.apache.hadoop.io.Text;  
  8. import org.apache.hadoop.mapreduce.Job;  
  9. import org.apache.hadoop.mapreduce.Mapper;  
  10. import org.apache.hadoop.mapreduce.Reducer;  
  11. import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;  
  12. import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;  
  13. import org.apache.hadoop.util.GenericOptionsParser;  
  14. import org.apache.hadoop.io.IntWritable;  
  15.   
  16. public class Step1 {  
  17.       
  18.     public static class MapClass   
  19.         extends Mapper<Object, Text, IntWritable, Text > {  
  20.           
  21.         public void map(Object key, Text value,  
  22.                         Context context ) throws IOException,  
  23.                         InterruptedException {  
  24.             String[] list = value.toString().split(",");  
  25.             context.write(new IntWritable(Integer.parseInt(list[0])),new Text(list[1] + ":" +list[2]));  
  26.         }  
  27.     }  
  28.       
  29.     public static class Reduce extends Reducer<IntWritable, Text, IntWritable, Text> {  
  30.           
  31.         private Text value = new Text();  
  32.         public void reduce(IntWritable key, Iterable<Text> values,  
  33.                            Context context) throws IOException,InterruptedException {  
  34.             StringBuilder sb = new StringBuilder();  
  35.             for (Text val : values) {  
  36.                 sb.append( "," + val.toString());  
  37.             }  
  38.             value.set(sb.toString().replaceFirst(","""));  
  39.             context.write(key, new Text(value));  
  40.         }  
  41.     }  
  42.       
  43.     public static void step1Run(Map<String, String> path) throws Exception {   
  44.         Configuration conf = new Configuration();  
  45.           
  46.         String input = path.get("data");  
  47.         String output = path.get("Step1Output");  
  48.         Job job = new Job(conf, "step1Run");  
  49.         job.setJarByClass(Step1.class);  
  50.         job.setMapperClass(MapClass.class);  
  51.         job.setCombinerClass(Reduce.class);  
  52.         job.setReducerClass(Reduce.class);  
  53.           
  54.         job.setOutputKeyClass(IntWritable.class);  
  55.         job.setOutputValueClass(Text.class);  
  56.         FileInputFormat.setInputPaths(job, new Path(input));  
  57.         FileOutputFormat.setOutputPath(job, new Path(output));  
  58.   
  59.         job.waitForCompletion(true);  
  60.     }  
  61. }  

Step2.java

[java] view plain copy
  1. import java.io.IOException;  
  2. import java.util.Iterator;  
  3. import java.util.Map;  
  4.   
  5. import org.apache.hadoop.conf.Configuration;  
  6. import org.apache.hadoop.fs.Path;  
  7. import org.apache.hadoop.io.Text;  
  8. import org.apache.hadoop.mapreduce.Job;  
  9. import org.apache.hadoop.mapreduce.Mapper;  
  10. import org.apache.hadoop.mapreduce.Reducer;  
  11. import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;  
  12. import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;  
  13. import org.apache.hadoop.util.GenericOptionsParser;  
  14. import org.apache.hadoop.io.IntWritable;  
  15.   
  16. public class Step1 {  
  17.       
  18.     public static class MapClass   
  19.         extends Mapper<Object, Text, IntWritable, Text > {  
  20.           
  21.         public void map(Object key, Text value,  
  22.                         Context context ) throws IOException,  
  23.                         InterruptedException {  
  24.             String[] list = value.toString().split(",");  
  25.             context.write(new IntWritable(Integer.parseInt(list[0])),new Text(list[1] + ":" +list[2]));  
  26.         }  
  27.     }  
  28.       
  29.     public static class Reduce extends Reducer<IntWritable, Text, IntWritable, Text> {  
  30.           
  31.         private Text value = new Text();  
  32.         public void reduce(IntWritable key, Iterable<Text> values,  
  33.                            Context context) throws IOException,InterruptedException {  
  34.             StringBuilder sb = new StringBuilder();  
  35.             for (Text val : values) {  
  36.                 sb.append( "," + val.toString());  
  37.             }  
  38.             value.set(sb.toString().replaceFirst(","""));  
  39.             context.write(key, new Text(value));  
  40.         }  
  41.     }  
  42.       
  43.     public static void step1Run(Map<String, String> path) throws Exception {   
  44.         Configuration conf = new Configuration();  
  45.           
  46.         String input = path.get("data");  
  47.         String output = path.get("Step1Output");  
  48.         Job job = new Job(conf, "step1Run");  
  49.         job.setJarByClass(Step1.class);  
  50.         job.setMapperClass(MapClass.class);  
  51.         job.setCombinerClass(Reduce.class);  
  52.         job.setReducerClass(Reduce.class);  
  53.           
  54.         job.setOutputKeyClass(IntWritable.class);  
  55.         job.setOutputValueClass(Text.class);  
  56.         FileInputFormat.setInputPaths(job, new Path(input));  
  57.         FileOutputFormat.setOutputPath(job, new Path(output));  
  58.   
  59.         job.waitForCompletion(true);  
  60.     }  
  61. }  

Step3.java

[java] view plain copy
  1. import java.io.IOException;  
  2. import java.util.Iterator;  
  3. import java.util.Map;  
  4.   
  5. import org.apache.hadoop.conf.Configuration;  
  6. import org.apache.hadoop.fs.Path;  
  7. import org.apache.hadoop.io.Text;  
  8. import org.apache.hadoop.mapreduce.Job;  
  9. import org.apache.hadoop.mapreduce.Mapper;  
  10. import org.apache.hadoop.mapreduce.Reducer;  
  11. import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;  
  12. import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;  
  13. import org.apache.hadoop.util.GenericOptionsParser;  
  14. import org.apache.hadoop.io.IntWritable;  
  15.   
  16. public class Step3 {  
  17.       
  18.     public static class Map1   
  19.         extends Mapper<Object, Text, IntWritable, Text> {  
  20.           
  21.         private IntWritable k = new IntWritable();  
  22.         private Text v = new Text();   
  23.         public void map(Object key, Text value,  
  24.                         Context context ) throws IOException,  
  25.                         InterruptedException {  
  26.             String[] list = value.toString().split("\\\t|,");  
  27.             for(int i = 1;i<list.length ; i++)  
  28.             {  
  29.                 String[] vector = list[i].split(":");  
  30.                 int nItemID = Integer.parseInt(vector[0]);  
  31.                 k.set(nItemID);  
  32.                 v.set(list[0] + ":" + vector[1]);  
  33.                 context.write(k,v);  
  34.             }  
  35.         }  
  36.     }  
  37.       
  38.     public static class Map2   
  39.         extends Mapper<Object, Text, Text, IntWritable > {  
  40.           
  41.         private IntWritable v = new IntWritable();  
  42.         private Text k = new Text();   
  43.         public void map(Object key, Text value,  
  44.                         Context context ) throws IOException,  
  45.                         InterruptedException {  
  46.             String[] list = value.toString().split("\\\t|,");  
  47.             k.set(list[0]);  
  48.             v.set(Integer.parseInt(list[1]));  
  49.             context.write(k,v);  
  50.         }  
  51.     }  
  52.   
  53.     public static void step3Run1(Map<String, String> path) throws Exception {   
  54.         Configuration conf = new Configuration();  
  55.           
  56.         String input = path.get("Step3Input1");  
  57.         String output = path.get("Step3Output1");  
  58.         Job job = new Job(conf, "step3Run1");  
  59.         job.setJarByClass(Step3.class);  
  60.         job.setMapperClass(Map1.class);  
  61.   
  62.         job.setOutputKeyClass(IntWritable.class);  
  63.         job.setOutputValueClass(Text.class);  
  64.         FileInputFormat.setInputPaths(job, new Path(input));  
  65.         FileOutputFormat.setOutputPath(job, new Path(output));  
  66.         job.waitForCompletion(true);  
  67.     }  
  68.       
  69.     public static void step3Run2(Map<String, String> path) throws Exception {   
  70.         Configuration conf = new Configuration();  
  71.           
  72.         //String[] otherArgs = new GenericOptionsParser(conf,args).getRemainingArgs();  
  73.         //if(otherArgs.length != 2){  
  74.         //  System.err.println("Usage: KPI <in> <out>");  
  75.         //  System.exit(2);  
  76.         //}  
  77.         String input = path.get("Step3Input2");  
  78.         String output = path.get("Step3Output2");  
  79.         Job job = new Job(conf, "step3Run2");  
  80.         job.setJarByClass(Step3.class);  
  81.         job.setMapperClass(Map2.class);  
  82.         //job.setCombinerClass(Reduce.class);  
  83.         //job.setReducerClass(Reduce.class);  
  84.           
  85.         //job.setInputFormat(KeyValueTextInputFormat.class);  
  86.         //job.setOutputFormat(TextOutputFormat.class);  
  87.         job.setOutputKeyClass(Text.class);  
  88.         job.setOutputValueClass(IntWritable.class);  
  89.         FileInputFormat.setInputPaths(job, new Path(input));  
  90.         FileOutputFormat.setOutputPath(job, new Path(output));  
  91.         job.waitForCompletion(true);  
  92.     }  
  93. }  
Step4_1.java
[java] view plain copy
  1. import java.io.IOException;  
  2. import java.util.HashMap;  
  3. import java.util.Iterator;  
  4. import java.util.Map;  
  5.   
  6. import org.apache.hadoop.conf.Configuration;  
  7. import org.apache.hadoop.fs.Path;  
  8. import org.apache.hadoop.io.IntWritable;  
  9. import org.apache.hadoop.io.LongWritable;  
  10. import org.apache.hadoop.io.Text;  
  11. import org.apache.hadoop.mapred.JobConf;  
  12. import org.apache.hadoop.mapreduce.Job;  
  13. import org.apache.hadoop.mapreduce.Mapper;  
  14. import org.apache.hadoop.mapreduce.Reducer;  
  15. import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;  
  16. import org.apache.hadoop.mapreduce.lib.input.FileSplit;  
  17. import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;  
  18. import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;  
  19. import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;  
  20.   
  21. public class Step4_1 {  
  22.   
  23.     public static class Step4_1_Mapper extends  
  24.             Mapper<Object, Text, Text, Text> {  
  25.   
  26.         private String flag;// A同现矩阵 or B评分矩阵  
  27.   
  28.         protected void setup(Context context) throws IOException, InterruptedException {  
  29.             FileSplit split = (FileSplit) context.getInputSplit();  
  30.             flag = split.getPath().getParent().getName();// 判断读的数据集  
  31.             // System.out.println(flag);  
  32.         }  
  33.   
  34.         public void map(Object key, Text values, Context context) throws IOException, InterruptedException {  
  35.             String[] tokens = values.toString().split("\\\t|,");  
  36.   
  37.             if (flag.equals("step3_2")) {// 同现矩阵  
  38.                 String[] v1 = tokens[0].split(":");  
  39.                 String itemID1 = v1[0];  
  40.                 String itemID2 = v1[1];  
  41.                 String num = tokens[1];  
  42.   
  43.                 Text k = new Text(itemID1);  
  44.                 Text v = new Text("A:" + itemID2 + "," + num);  
  45.   
  46.                 context.write(k, v);  
  47.   
  48.             } else if (flag.equals("step3_1")) {// 评分矩阵  
  49.                 String[] v2 = tokens[1].split(":");  
  50.                 String itemID = tokens[0];  
  51.                 String userID = v2[0];  
  52.                 String pref = v2[1];  
  53.   
  54.                 Text k = new Text(itemID);  
  55.                 Text v = new Text("B:" + userID + "," + pref);  
  56.   
  57.                 context.write(k, v);  
  58.             }  
  59.         }  
  60.     }  
  61.   
  62.     public static class Step4_1_Reducer extends Reducer<Text, Text, Text, Text> {  
  63.   
  64.         public void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {  
  65.   
  66.             Map<String, String> mapA = new HashMap<String, String>();  
  67.             Map<String, String> mapB = new HashMap<String, String>();  
  68.   
  69.             for (Text line : values) {  
  70.                 String val = line.toString();  
  71.   
  72.                 if (val.startsWith("A:")) {  
  73.                     String[] kv = val.substring(2).split("\\\t|,");  
  74.                     mapA.put(kv[0], kv[1]);  
  75.   
  76.                 } else if (val.startsWith("B:")) {  
  77.                     String[] kv = val.substring(2).split("\\\t|,");  
  78.                     mapB.put(kv[0], kv[1]);  
  79.                 }  
  80.             }  
  81.   
  82.             double result = 0;  
  83.             Iterator iter = mapA.keySet().iterator();  
  84.             while (iter.hasNext()) {  
  85.                 String mapk = (String) iter.next();// itemID  
  86.                 int num = Integer.parseInt(mapA.get(mapk));  
  87.                 Iterator iterb = mapB.keySet().iterator();  
  88.                 while (iterb.hasNext()) {  
  89.                     String mapkb = (String) iterb.next();// userID  
  90.                     double pref = Double.parseDouble(mapB.get(mapkb));  
  91.                     result = num * pref;// 矩阵乘法相乘计算  
  92.   
  93.                     Text k = new Text(mapkb);  
  94.                     Text v = new Text(mapk + "," + result);  
  95.                     context.write(k, v);  
  96.                 }  
  97.             }  
  98.         }  
  99.     }  
  100.   
  101.     public static void run(Map<String, String> path) throws IOException, InterruptedException, ClassNotFoundException {  
  102.         Configuration conf = new Configuration();  
  103.         String input1 = path.get("Step5Input1");  
  104.         String input2 = path.get("Step5Input2");  
  105.         String output = path.get("Step5Output");  
  106.   
  107.         Job job = new Job(conf,"Step4_1");  
  108.         job.setJarByClass(Step4_1.class);  
  109.   
  110.         job.setOutputKeyClass(Text.class);  
  111.         job.setOutputValueClass(Text.class);  
  112.   
  113.         job.setMapperClass(Step4_1_Mapper.class);  
  114.         job.setReducerClass(Step4_1_Reducer.class);  
  115.   
  116.         job.setInputFormatClass(TextInputFormat.class);  
  117.         job.setOutputFormatClass(TextOutputFormat.class);  
  118.   
  119.         FileInputFormat.setInputPaths(job, new Path(input1), new Path(input2));  
  120.         FileOutputFormat.setOutputPath(job, new Path(output));  
  121.   
  122.         job.waitForCompletion(true);  
  123.     }  
  124. }  


Step4_2.java

[java] view plain copy
  1. import java.io.IOException;  
  2. import java.util.HashMap;  
  3. import java.util.Iterator;  
  4. import java.util.Map;  
  5.   
  6. import org.apache.hadoop.conf.Configuration;  
  7. import org.apache.hadoop.fs.Path;  
  8. import org.apache.hadoop.io.IntWritable;  
  9. import org.apache.hadoop.io.LongWritable;  
  10. import org.apache.hadoop.io.Text;  
  11. import org.apache.hadoop.mapred.JobConf;  
  12. import org.apache.hadoop.mapreduce.Job;  
  13. import org.apache.hadoop.mapreduce.Mapper;  
  14. import org.apache.hadoop.mapreduce.Reducer;  
  15. import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;  
  16. import org.apache.hadoop.mapreduce.lib.input.FileSplit;  
  17. import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;  
  18. import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;  
  19. import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;  
  20.   
  21. public class Step4_2 {  
  22.   
  23.     public static class Step4_2_Mapper extends  
  24.             Mapper<Object, Text, Text, Text> {  
  25.   
  26.         public void map(Object key, Text values, Context context) throws IOException, InterruptedException {  
  27.             String[] tokens = values.toString().split("\\\t|,");  
  28.             Text k = new Text(tokens[0]);  
  29.             Text v = new Text(tokens[1]+","+tokens[2]);  
  30.             context.write(k, v);  
  31.         }  
  32.     }  
  33.   
  34.     public static class Step4_2_Reducer extends Reducer<Text, Text, Text, Text> {  
  35.   
  36.         public void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {  
  37.   
  38.             Map<String, Double> map = new HashMap<String, Double>();  
  39.   
  40.             for (Text line : values) {  
  41.                 String[] tokens = line.toString().split("\\\t|,");  
  42.                 String itemID = tokens[0];  
  43.                 Double score = Double.parseDouble(tokens[1]);  
  44.                   
  45.                  if (map.containsKey(itemID)) {  
  46.                      map.put(itemID, map.get(itemID) + score);// 矩阵乘法求和计算  
  47.                  } else {  
  48.                      map.put(itemID, score);  
  49.                  }  
  50.             }  
  51.               
  52.             Iterator<String> iter = map.keySet().iterator();  
  53.             while (iter.hasNext()) {  
  54.                 String itemID = iter.next();  
  55.                 double score = map.get(itemID);  
  56.                 Text v = new Text(itemID + "," + score);  
  57.                 context.write(key, v);  
  58.             }  
  59.         }  
  60.     }  
  61.   
  62.     public static void run(Map<String, String> path) throws IOException, InterruptedException, ClassNotFoundException {  
  63.         Configuration conf = new Configuration();  
  64.         String input = path.get("Step6Input");  
  65.         String output = path.get("Step6Output");  
  66.   
  67.         Job job = new Job(conf,"Step4_2");  
  68.         job.setJarByClass(Step4_2.class);  
  69.   
  70.         job.setOutputKeyClass(Text.class);  
  71.         job.setOutputValueClass(Text.class);  
  72.   
  73.         job.setMapperClass(Step4_2_Mapper.class);  
  74.         job.setReducerClass(Step4_2_Reducer.class);  
  75.   
  76.         job.setInputFormatClass(TextInputFormat.class);  
  77.         job.setOutputFormatClass(TextOutputFormat.class);  
  78.   
  79.         FileInputFormat.setInputPaths(job, new Path(input));  
  80.         FileOutputFormat.setOutputPath(job, new Path(output));  
  81.   
  82.         job.waitForCompletion(true);  
  83.     }  
  84. }  

以上代码还有很多需要完善的地方,下次再重新整理。
附上github地址: https://github.com/y521263/Hadoop_in_Action

参考资料:

http://blog.fens.me/hadoop-mapreduce-recommend/


你可能感兴趣的:(hadoop学习-Netflix电影推荐系统)