矩阵乘法的Mapreduce实现过程

MapReduce实现矩阵的乘法

在学习pageRank算法时看到这么一个小小的编程应用。并且一直自诩只要有原理就能写出代码(只是时间问题),矩阵乘法的原理很简单,基本上理工科生(只要学过线性代数或者相关课程)都知道。但是从来没有想过通过并行计算的方式来完成矩阵乘法。

这里矩阵的知识就不啰嗦了,矩阵的乘积记作为P=M*N。则P中的元素

简单粗暴的讲,就是左矩阵M的行依次与右矩阵的列元素对应相乘,然后再相加。

可能说到mapreduce算法可能都会想到map用来整理数据(这里指的就是矩阵中的元素),然后送至reduce中计算。说起来是挺简单的,但是从无到有的过程还是不容易的。关键是key值的设计,可以说一个key的设计是编程成功的一半。

下面详细的道来设计过程。

相信大家都关注到了<k,v>对里面的M: 和N:字样。这个得郑重声明一下,其实不用也可以,但是value值这样设置后很容易维护和调试代码(具体的可以参看以下陆嘉恒的《hadoop实战》关于单表关联的章节),因为能清晰看出元素的出处。必须要说明的是M:和N:后面的数字特别重要,M:y的y表示元素对应的列号;N:x的x表示元素对应的行号。这样说明之后是不是思路就清晰了,把这样的<k,v>上传给reduce,reduce收到的是〈k, list(v)〉,源代码的System.out.print("tuple=="
+ MN[0] + ":" + MN[1] +"\t");就能看得明白map的内容。List(v)就是如下的样子。

到了,这里map过程就结束了,下面就是reduce的过程。刚才说了那个x/y很重要,现在就体现出来了,起到标志位的作用。在一个list里面标志位相同的元素相乘就是,再相加就是对应结果。是不是小有成就感。

下面来简单的谈谈MR程序的实现。MR框架还是比较简单,相信初上手的时候都会拿wordcount程序入门,下面就是就是从hadoop自带的wordcount里面抽取出来的MR框架。


publicclass wordCount {

publicstaticclass mulMapperextends
Mapper<Object, Text, Text, Text> {

publicvoid map(Object key, Text value, Context context)

throws IOException, InterruptedException {

}

}

publicstaticclass mulReducerextends
Reducer<Text, Text, Text, Text> {

publicvoid reduce(Text key, Iterable<Text> values, Context context)

throws IOException, InterruptedException {

}

}

publicstaticvoid main(String[] args)throws
Exception {

Configuration conf =
new
Configuration();

String[] otherArgs =
new
GenericOptionsParser(conf, args)

.getRemainingArgs();

if (otherArgs.length != 2) {

System.err.println("Usage: wordcount <in> <out>");

System.exit(2);

}

//对重复出现的目录处理

FileSystem fs = FileSystem.get(URI.create(otherArgs[1]), conf);

Path inpath = new Path(otherArgs[0]);

Path outpath = new Path(otherArgs[1]);

Job job = new Job(conf,"word count");

job.setJarByClass(Multi.class);

job.setMapperClass(mulMapper.class);

// job.setCombinerClass(mulReducer.class);

job.setReducerClass(mulReducer.class);

job.setOutputKeyClass(Text.class);

job.setOutputValueClass(Text.class);

FileInputFormat.addInputPath(job, inpath);

FileOutputFormat.setOutputPath(job, outpath);

System.exit(job.waitForCompletion(true) ? 0 : 1);

}

}

具体的编程就不讲了,可以根据自己的理解去实现。如果感觉有困难,参考文献后面给出来完整的MR程序代码。

祝你好运!!

参考文献

[1]. 黄宜华, 苗凯翔. 深入理解大数据---大数据处理与编程实践[M].北京:机械工业出版社. 2014

[2]. 陆嘉恒. Hadoop实战[M]. 北京:机械工业出版社. 2012

以下是完整的MR代码。


package org.apache.test;

import java.io.IOException;

import java.net.URI;

import org.apache.hadoop.conf.Configuration;

import org.apache.hadoop.fs.FileSystem;

import org.apache.hadoop.fs.Path;

import org.apache.hadoop.io.Text;

import org.apache.hadoop.mapreduce.Job;

import org.apache.hadoop.mapreduce.Mapper;

import org.apache.hadoop.mapreduce.Reducer;

import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;

import org.apache.hadoop.mapreduce.lib.input.FileSplit;

import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

import org.apache.hadoop.util.GenericOptionsParser;

publicclass Multi {

publicstaticclass mulMapperextends
Mapper<Object, Text, Text, Text> {

private Textmap_key =
new Text();

private Textmap_value =
new Text();

privateintline1 = 0;

// m*n

publicvoid map(Object key, Text value, Context context)

throws IOException, InterruptedException {

int rowM = 2;//
左矩阵的行数

int colM = 2;//
左矩阵的列数

introwN = 2;
// 右矩阵德行数

int colN = 3;//
右矩阵的列数

// System.out.println("再执行一次");

FileSplit filesplit = (FileSplit) context.getInputSplit();

String fileName = filesplit.getPath().getName();

// System.out.println(fileName);

if (fileName.contains("n")) {

String[] line = value.toString().split(" ");

for (int j = 0; j < rowM; j++) {

for (int
i = 0; i < colN; i++) {

int val = Integer.parseInt(line[i]);

map_key.set(j +"," + i);

map_value.set("N" +":"
+ line1 +
"," + val);

System.out.println("N:"
+map_key +
"\t" + map_value);

context.write(map_key,map_value);

}

}

}
elseif
(fileName.contains("m")) {

String[] line = value.toString().split(" ");

for (int i = 0; i < colN; i++) {

for (int
j = 0; j < colM; j++) {

int val = Integer.parseInt(line[j]);

map_key.set(line1 +","
+ i);

map_value.set("M" +":"
+ j + "," + val);

System.out.println("M:"
+map_key +
"\t" + map_value);

context.write(map_key,map_value);

}

}

}

line1++;

}

}

publicstaticclass mulReducerextends
Reducer<Text, Text, Text, Text> {

publicvoid reduce(Text key, Iterable<Text> values, Context context)

throws IOException, InterruptedException {

finalint[] M =newint[2];

finalint[] N =newint[2];

int sum = 0;

System.out.println("按key值小到大输出:");

for (Text val : values) {

String[] MN = val.toString().split(":");

String[] except_value = MN[1].toString().split(",");

System.out.print("tuple==" + MN[0] +":" + MN[1] +"\t");

//                                  
System.out.println(MN[1]);

if (MN[0].equals("M"))

M[Integer.parseInt(except_value[0])] = Integer

.parseInt(except_value[1]);

else

N[Integer.parseInt(except_value[0])] = Integer

.parseInt(except_value[1]);

}

for (int i = 0; i
< M.length; i++) {

sum += M[i] * N[i];

}

System.out.print("sum=" + sum);

System.out.println();

//                         context.write(key, new Text(Integer.toString(sum)));

context.write(new Text(),new
Text("\t"+Integer.toString(sum)));

}

}

publicstaticvoid main(String[] args)throws
Exception {

Configuration conf =new Configuration();

String[] otherArgs =new GenericOptionsParser(conf, args)

.getRemainingArgs();

if (otherArgs.length != 2) {

System.err.println("Usage: matrix <in> <out>");

System.exit(2);

}

//对重复出现的目录处理

FileSystem fs = FileSystem.get(URI.create(otherArgs[1]), conf);

Path inpath =new Path(otherArgs[0]);

Path outpath =new Path(otherArgs[1]);

if (fs.exists(outpath)) {

System.out.println(outpath);

System.out.println("输出目录已经存在,现在删除...重建目录");

fs.delete(outpath,true);

}

Job job =
new
Job(conf,"multiplication");

job.setJarByClass(Multi.class);

job.setMapperClass(mulMapper.class);

// job.setCombinerClass(mulReducer.class);

job.setReducerClass(mulReducer.class);

job.setOutputKeyClass(Text.class);

job.setOutputValueClass(Text.class);

FileInputFormat.addInputPath(job, inpath);

FileOutputFormat.setOutputPath(job, outpath);

System.exit(job.waitForCompletion(true) ? 0 : 1);

}

}

时间: 2024-11-08 20:55:46

矩阵乘法的Mapreduce实现过程的相关文章

矩阵乘法的MapReduce实现

对于任意矩阵M和N,若矩阵M的列数等于矩阵N的行数,则记M和N的乘积为P=M*N,其中mik 记做矩阵M的第i行和第k列,nkj记做矩阵N的第k行和第j列,则矩阵P中,第i行第j列的元素可表示为公式(1-1): pij=(M*N)ij=∑miknkj=mi1*n1j+mi2*n2j+--+mik*nkj (公式1-1) 由公式(1-1)可以看出,最后决定pij是(i,j),所以可以将其作为Reducer的输入key值.为了求出pij分别需要知道mik和nkj,对于mik,其所需要的属性有矩阵M,

【甘道夫】MapReduce实现矩阵乘法--实现代码

之前写了一篇分析MapReduce实现矩阵乘法算法的文章:[甘道夫]Mapreduce实现矩阵乘法的算法思路 为了让大家更直观的了解程序执行,今天编写了实现代码供大家参考. 编程环境: java version "1.7.0_40" Eclipse Kepler Windows7 x64 Ubuntu 12.04 LTS Hadoop2.2.0 Vmware 9.0.0 build-812388 输入数据: A矩阵存放地址:hdfs://singlehadoop:8020/wordsp

hadoop矩阵乘法

引言 何为大矩阵?Excel.SPSS,甚至SAS处理不了或者处理起来非常困难,需要设计巧妙的分布式方法才能高效解决基本运算(如转置.加法.乘法.求逆)的矩阵,我们认为其可被称为大矩阵.这意味着此种矩阵的维度至少是百万级的.经常是千万级的.有时是亿万级的.举个形象的栗子.至2012年12月底,新浪微博注册用户数超5亿,日活跃用户4629万[1],如果我们要探索这4000多万用户可以分成哪些类别,以便深入了解用户共同特征,制定精准营销策略,势必要用到聚类相关的算法(比如新浪大牛张俊林就利用聚类算法

矩阵乘法的Strassen算法详解

题目描述 请编程实现矩阵乘法,并考虑当矩阵规模较大时的优化方法. 思路分析 根据wikipedia上的介绍:两个矩阵的乘法仅当第一个矩阵B的列数和另一个矩阵A的行数相等时才能定义.如A是m×n矩阵和B是n×p矩阵,它们的乘积AB是一个m×p矩阵,它的一个元素其中 1 ≤ i ≤ m, 1 ≤ j ≤ p. 值得一提的是,矩阵乘法满足结合律和分配率,但并不满足交换律,如下图所示的这个例子,两个矩阵交换相乘后,结果变了: 下面咱们来具体解决这个矩阵相乘的问题. 解法一.暴力解法 其实,通过前面的分析

POJ2778 DNA Sequence Trie+矩阵乘法

题意:给定N个有A C G T组成的字符串,求长度为L的仅由A C G T组成的字符串中有多少个是不含给定的N个字符串的题解: 首先我们把所有的模式串(给定的DNA序列)建Trie,假定我们有一个匹配串,并且在匹配过程到S[i]这个字符时匹配到了Trie上的某个节点t,那么有两种可能: 匹配失败:t->child[S[i]]为空,跳转到t->fail,因此t->fail一定不能是某个模式串的结尾: 匹配成功:跳转到t->child[S[i+1]],因此t->child[S[i

codevs1281 矩阵乘法 快速幂 !!!手写乘法取模!!! 练习struct的构造函数和成员函数

对于这道题目以及我的快速幂以及我的一节半晚自习我表示无力吐槽,, 首先矩阵乘法和快速幂没必要太多说吧,,嗯没必要,,我相信没必要,,实在做不出来写两个矩阵手推一下也就能理解矩阵的顺序了,要格外注意一些细节,比如快速幂时ans矩阵的初始化方式,快速幂的次数,矩阵乘法过程中对临时矩阵的清零,最后输出结果时的初始矩阵...矩阵快速幂好理解但是细节还是有点小坑的.. 下面就是满满的槽点,,高能慎入!!! 对于这个题目要求矩阵过程中对m取模,结果对g取模,我表示难以接受,,上来没看清题直接wa19个点,另

我们可以推测矩阵乘法最优解的时间复杂度么?

矩阵乘法的定义为: 按照定义,一个简单的方阵乘法伪代码如下: int A[48,48],B[48,48],C[48,48] for i in 1 to 48 for j in 1 to 48 for k in 1 to 48 C[i,j]+=B[i,k]*A[k,j] 三层嵌套,时间复杂度为O(n3),n为方阵的边长. 由于矩阵乘法的广泛运用,如何优化矩阵乘法运算,有重要的意义.在不考虑矩阵的疏密程度下,如何有效减少矩阵乘法中算术乘法的使用次数是一个主要的优化方向. 最早的矩阵乘法优化算法,是由

学习心得:《十个利用矩阵乘法解决的经典题目》from Matrix67

本文来自:http://www.matrix67.com/blog/archives/tag/poj大牛的博文学习学习 节选如下部分:矩阵乘法的两个重要性质:一,矩阵乘法不满足交换律:二,矩阵乘法满足结合律经典题目1 给定n个点,m个操作,构造O(m+n)的算法输出m个操作后各点的位置.操作有平移.缩放.翻转和旋转    这 里的操作是对所有点同时进行的.其中翻转是以坐标轴为对称轴进行翻转(两种情况),旋转则以原点为中心.如果对每个点分别进行模拟,那么m个操作总共耗时 O(mn).利用矩阵乘法可

用矩阵乘法优化递推

(有关矩阵乘法的基本规则请自行搜索) 引例:求斐波那契数列的第 n 项 mod 1000000007 的值,n <= 1018. 分析:斐波那契数列的递推式为 f(n) = f(n-1)+f(n-2),直接循环求出 f(n) 的时间复杂度是 O(n),对于题目中的数据范围显然无法承受.很明显我们需要对数级别的算法. 由于 f(n) = 1*f(n-1) + 1*f(n-2) 这样的形式很类似于矩阵的乘法,所以我们可以先把这个问题复杂化一下,将递推求解 f(n) 与 f(n-1) 的过程看作是某两