矩阵乘法的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,所在行数i、所在列数k,和其本身的数值大小mik;同样对于nkj,其所需要的属性有矩阵N,所在行数k、所在列数j,和其本身数值大小nkj,这些属性值可由Mapper处理得到

Map函数:对于矩阵M中的每个元素mik ,产生一系列的key-value对<(i,j),(M,k,mik)>,其中,k=1,2……直到矩阵N的总列数,对于矩阵N的每个元素nkj,产生一系列的key-value对,<(i,j),(N,k,nkj)>,其中i=1,2……直到矩阵M的总行数

Reduce函数:对于每个键(i,j)相关联的值(M,k,mik)及(N,k,nkj),根据相同的k值将mik和nkj分别放入不同的数组中,然后将两者的第k个元素抽取出来分别相乘,再累加,即可得到pij的值

有M和N两个文件分别存放两个矩阵,文件内容的每一行的形式是“行号,列号\t元素值”,本例中,使用shell脚本生成数据

代码1-2

[email protected]:/data# cat matrix
#!/bin/bash
for i in `seq 1 $1`
do
        for j in `seq 1 $2`
        do
                s=$(($RANDOM % 100))
                echo -e "$i,$j\t$s" >> M_$1_$2
        done
done

for i in `seq 1 $2`
do
        for j in `seq 1 $3`
        do
                s=$(($RANDOM%100))
                echo -e "$i,$j\t$s" >> N_$2_$3
        done
done

代码1-3,执行matrix脚本,生成一个2行3列和3行3列的矩阵,并在HDFS下新建一个data文件夹,将生成的两个矩阵放入data文件夹下

代码1-3

[email protected]:/data# ./matrix 2 3 3
[email protected]:/data# cat M_2_3
1,1     6
1,2     84
1,3     40
2,1     51
2,2     37
2,3     97
[email protected]:/data# cat N_3_3
1,1     97
1,2     34
1,3     95
2,1     93
2,2     10
2,3     70
3,1     71
3,2     24
3,3     47
[email protected]:/data# hadoop fs -mkdir /data
[email protected]:/data# hadoop fs -put /data/M_2_3 /data/
[email protected]:/data# hadoop fs -put /data/N_3_3 /data/
[email protected]:/data# hadoop fs -ls -R /data
-rw-r--r--   1 root supergroup         41 2017-01-07 11:57 /data/M_2_3
-rw-r--r--   1 root supergroup         63 2017-01-07 11:57 /data/N_3_3

矩阵乘法Mapper类程序如代码1-4

代码1-4

package com.hadoop.mapreduce;

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.lib.input.FileSplit;

public class MatrixMapper extends Mapper<LongWritable, Text, Text, Text> {

	private int columnN = 0;
	private int rowM = 0;
	private Text mapKey = new Text();
	private Text mapValue = new Text();

	protected void setup(Context context) throws IOException, InterruptedException {
		Configuration conf = context.getConfiguration();
		columnN = Integer.parseInt(conf.get("columnN"));
		rowM = Integer.parseInt(conf.get("rowM"));
	};

	protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
		FileSplit file = (FileSplit) context.getInputSplit();
		String fileName = file.getPath().getName();
		String line = value.toString();
		String[] tuple = line.split(",");
		if (tuple.length != 2) {
			throw new RuntimeException("MatrixMapper tuple error");
		}
		int row = Integer.parseInt(tuple[0]);
		String[] tuples = tuple[1].split("\t");
		if (tuples.length != 2) {
			throw new RuntimeException("MatrixMapper tuples error");
		}
		if (fileName.contains("M")) {
			matrixM(row, Integer.parseInt(tuples[0]), Integer.parseInt(tuples[1]), context);
		} else {
			matrixN(row, Integer.parseInt(tuples[0]), Integer.parseInt(tuples[1]), context);
		}

	};

	private void matrixM(int row, int column, int value, Context context) throws IOException, InterruptedException {
		for (int i = 1; i < columnN + 1; i++) {
			mapKey.set(row + "," + i);
			mapValue.set("M," + column + "," + value);
			context.write(mapKey, mapValue);
		}
	}

	private void matrixN(int row, int column, int value, Context context) throws IOException, InterruptedException {
		for (int i = 1; i < rowM + 1; i++) {
			mapKey.set(i + "," + column);
			mapValue.set("N," + row + "," + value);
			context.write(mapKey, mapValue);
		}
	}

}

矩阵乘法Reducer类程序如代码1-5

代码1-5

package com.hadoop.mapreduce;

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;

public class MatrixReducer extends Reducer<Text, Text, Text, Text> {

	private int columnM = 0;

	protected void setup(Context context) throws IOException, InterruptedException {
		Configuration conf = context.getConfiguration();
		columnM = Integer.parseInt(conf.get("columnM"));
	};

	protected void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {
		int sum = 0;
		int[] m = new int[columnM + 1];
		int[] n = new int[columnM + 1];
		for (Text val : values) {
			String[] tuple = val.toString().split(",");
			if (tuple.length != 3) {
				throw new RuntimeException("MatrixReducer tuple error");
			}
			if ("M".equals(tuple[0])) {
				m[Integer.parseInt(tuple[1])] = Integer.parseInt(tuple[2]);
			} else {
				n[Integer.parseInt(tuple[1])] = Integer.parseInt(tuple[2]);
			}
		}
		for (int i = 1; i < columnM + 1; i++) {
			sum += m[i] * n[i];
		}
		context.write(key, new Text(sum + ""));
	};

}

矩阵乘法主函数如代码1-5

package com.hadoop.mapreduce;

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

public class Matrix {

	public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
		if (args == null || args.length != 5) {
			throw new RuntimeException("请输入输入路径、输出路径、矩阵M的行数、矩阵M的列数、矩阵N的列数");
		}
		Configuration conf = new Configuration();
		conf.set("rowM", args[2]);
		conf.set("columnM", args[3]);
		conf.set("columnN", args[4]);
		Job job = Job.getInstance(conf);
		job.setJobName("Matrix");
		job.setJarByClass(Matrix.class);
		job.setMapperClass(MatrixMapper.class);
		job.setReducerClass(MatrixReducer.class);
		job.setOutputKeyClass(Text.class);
		job.setOutputValueClass(Text.class);
		FileInputFormat.addInputPaths(job, args[0]);
		FileOutputFormat.setOutputPath(job, new Path(args[1]));
		System.exit(job.waitForCompletion(true) ? 0 : 1);
	}

}

将代码1-3、1-4、1-5打成Matrix.jar包,然后运行,运行结果如代码1-6(注:代码1-6省略部分MapReduce执行内容)

代码1-6

[email protected]:/data# hadoop jar Matrix.jar com.hadoop.mapreduce.Matrix /data/ /output/ 2 3 3
…………
[email protected]:/data# hadoop fs -ls -R /output
-rw-r--r--   1 root supergroup          0 2017-01-07 12:04 /output/_SUCCESS
-rw-r--r--   1 root supergroup         57 2017-01-07 12:04 /output/part-r-00000
[email protected]:/data# hadoop fs -cat /output/part-r-00000
1,1     11234
1,2     2004
1,3     8330
2,1     15275
2,2     4432
2,3     11994
时间: 2024-12-09 09:27:42

矩阵乘法的MapReduce实现的相关文章

矩阵乘法的Mapreduce实现过程

MapReduce实现矩阵的乘法 在学习pageRank算法时看到这么一个小小的编程应用.并且一直自诩只要有原理就能写出代码(只是时间问题),矩阵乘法的原理很简单,基本上理工科生(只要学过线性代数或者相关课程)都知道.但是从来没有想过通过并行计算的方式来完成矩阵乘法. 这里矩阵的知识就不啰嗦了,矩阵的乘积记作为P=M*N.则P中的元素 简单粗暴的讲,就是左矩阵M的行依次与右矩阵的列元素对应相乘,然后再相加. 可能说到mapreduce算法可能都会想到map用来整理数据(这里指的就是矩阵中的元素)

【甘道夫】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. 值得一提的是,矩阵乘法满足结合律和分配率,但并不满足交换律,如下图所示的这个例子,两个矩阵交换相乘后,结果变了: 下面咱们来具体解决这个矩阵相乘的问题. 解法一.暴力解法 其实,通过前面的分析

51nod 1137 矩阵乘法

基本的矩阵乘法 中间for(int j=0;i<n;i++)  //这里写错了   应该是j<n 晚上果然  效率不行 等会早点儿睡 //矩阵乘法 就是 两个矩阵 第一个矩阵的列 等与 第二个矩阵的行相同 // 然后ans[i][j] += a[i][k] * b[k][j]; #include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 150; int n; ll a[ma

矩阵乘法

矩阵加法就是相同位置的数字加一下,矩阵减法也类似 矩阵乘以一个常数,就是所有位置都乘以这个数 矩阵乘以矩阵 计算规则是,第一个矩阵第一行的每个数字(2和1),各自乘以第二个矩阵第一列对应位置的数字(1和1),然后将乘积相加( 2 x 1 + 1 x 1),得到结果矩阵左上角的那个值3 矩阵的本质就是线性方程式,两者是一一对应关系.如果从线性方程式的角度,理解矩阵乘法就毫无难度.下面是一组线性方程式 矩阵的最初目的,只是为线性方程组提供一个简写形式 下面是严格的证明.有三组未知数 x.y 和 t,

矩阵乘法&lt;简单总结&gt;

原理:矩阵相乘最重要的方法是一般矩阵乘积.它只有在第一个矩阵的 行数 和第二个矩阵的 列数 相同时才可进行.若A为m×n矩阵,B为n×p矩阵,则他们的乘积AB会是一个m×p矩阵. 若A=    a    b    c        d    e    f        g    h    i    B=    A    D        B    E        C    F    A*B=CC=    aA+bB+cC    aD+bE+cF        dA+eB+fC    dD+eE

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

【CDQ】BZOJ 2738 矩阵乘法

题意:给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数 思路: 整体二分+二维树状数组 二分询问的答案mid,将数值小等mid的全部插入二维树状数组 然后查询每个矩阵内的元素个数,若数量>K-1则放左边,否则放右边 继续向下分治,左边二分l-mid,右边mid-r 代码: #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include