这期内容当中小编将会给大家带来有关mapreduce中怎么实现矩阵相乘,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。
设,,那么
矩阵乘法要求左矩阵的列数与右矩阵的行数相等,的矩阵,与的矩阵相乘,结果为的矩阵。
现在我们来分析一下,哪些操作是相互独立的(从而可以进行分布式计算)。很显然,的计算和的计算是互不干扰的;事实上,中各个元素的计算都是相互独立的。这样,我们在Map阶段,可以把计算所需要的元素都集中到同一个key中,然后,在Reduce阶段就可以从中解析出各个元素来计算;的其他元素的计算同理。
我们还需要注意,会被、……的计算所使用,会被、……的计算所使用。也就是说,在Map阶段,当我们从HDFS取出一行记录时,如果该记录是的元素,则需要存储成个<key, value>对,并且这个key互不相同;如果该记录是的元素,则需要存储成个<key, value>对,同样的,个key也应互不相同;但同时,用于计算的、存放、……和、……的<key, value>对的key应该都是相同的,这样才能被传递到同一个Reduce中。
经过以上分析,整个计算过程设计为:
(1)在Map阶段,把来自表的元素,标识成条<key, value>的形式。其中,;把来自表的元素,标识成条<key, value>形式,其中,。
于是乎,在Map阶段,我们实现了这样的战术目的:通过key,我们把参与计算的数据归为一类。通过value,我们能区分元素是来自还是,以及具体的位置。
(2)在Shuffle阶段,相同key的value会被加入到同一个列表中,形成<key, list(value)>对,传递给Reduce,这个由Hadoop自动完成。
(3)在Reduce阶段,有两个问题需要自己问问:
当前的<key, list(value)>对是为了计算的哪个元素?
list中的每个value是来自表或表的哪个位置?
第一个问题可以从key中获知,因为我们在Map阶段已经将key构造为形式。第二个问题,也可以在value中直接读出,因为我们也在Map阶段做了标志。
接下来我们所要做的,就是把list(value)解析出来,来自的元素,单独放在一个数组中,来自的元素,放在另一个数组中,然后,我们计算两个数组(各自看成一个向量)的点积,即可算出的值。
示例矩阵和相乘的计算过程如下图所示:
其中map阶段:
public static class MatrixMap extends Mapper<Object, Text, Text, Text>{ private int sum3 = 0; //存放矩阵a的行数 private int sum4 = 0; //存放矩阵b的行数 @Override protected void map(Object key, Text value, Context context) throws IOException, InterruptedException { String[] lines = value.toString().split(","); String url = ((FileSplit)context.getInputSplit()).getPath().toString(); //取出文件路径名,判断数据来源分别增加其行数 if(url.contains("matrix3")) sum3++; if(url.contains("matrix4")) sum4++; for(int m = 0; m < lines.length; m++){ // 遍历矩阵列数,分别与行数组成key为(i,k),value为(a,j,v)的数据输出 if(url.contains("matrix3") && lines.length == matrix_j){ for (int i = 1; i <= matrix_k; i++){ context.write(new Text(sum3+","+i), new Text("a,"+(m+1)+","+lines[m])); } }else if(url.contains("matrix4") && lines.length == matrix_k){ for (int i = 1; i <= matrix_i; i++){ context.write(new Text(i+","+(m+1)), new Text("b,"+sum4+","+lines[m])); } } } } }
reduce阶段:
public static class MatrixReduce extends Reducer<Text, Text, Text, Text>{ private Map<Integer, Integer> matrix_a; private Map<Integer, Integer> matrix_b; @Override protected void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException { matrix_a = new HashMap<Integer, Integer>(); matrix_b = new HashMap<Integer, Integer>(); for(Text value : values){ //循环分辨values中值是矩阵a或是b的,并存入map集合a和b中 String line = value.toString(); if(line.startsWith("a,")){ String[] lines = line.split(","); if(lines.length == 3) matrix_a.put(Integer.parseInt(lines[1]), Integer.parseInt(lines[2])); }else{ String[] lines = line.split(","); if(lines.length == 3) matrix_b.put(Integer.parseInt(lines[1]), Integer.parseInt(lines[2])); } } int a_value = 0; int b_value = 0; int result = 0; //分别取出a和b集合中,计算结果放入result中 for(int i = 1; i <= matrix_j; i++){ if(matrix_a.get(i) != null && matrix_b.get(i) != null){ a_value = matrix_a.get(i); b_value = matrix_b.get(i); result += a_value * b_value; } } context.write(key, new Text(result+"")); } }
主程序:
public static void run(String time, Configuration conf) throws IOException, ClassNotFoundException, InterruptedException{ // 需求输出文件路径 String outpath = VALUE_FSNAME+ "/data/test_out/zk/matrix-"+time; // 需求输入文件路径 String input1 = VALUE_FSNAME+"/data/test_in/matrix3"; String input2 = VALUE_FSNAME+"/data/test_in/matrix4"; File jarFile = EJob.createTempJar("bin"); @SuppressWarnings("deprecation") Job job = new Job(conf, "Test-Matrix"); job.setJarByClass(TestMatrix1.class); job.setMapperClass(MatrixMap.class); job.setReducerClass(MatrixReduce.class); job.setOutputKeyClass(Text.class); job.setOutputValueClass(Text.class); job.setNumReduceTasks(1); job.setInputFormatClass(TextInputFormat.class); job.setOutputFormatClass(TextOutputFormat.class); FileInputFormat.addInputPaths(job, input1+","+input2);; FileOutputFormat.setOutputPath(job, new Path(outpath)); // 提交job if (job.waitForCompletion(true)) { System.err.println("计算完成!"); } else { System.err.println("error!请检查程序!"); } }
最后,大家请看一下原始数据:
matrix1:
1,2,3 4,5,0 7,8,9 10,11,12
matrix2:
10,15 0,2 11,9
上述就是小编为大家分享的mapreduce中怎么实现矩阵相乘了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注亿速云行业资讯频道。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。