如何用 MapReduce 实现稀疏大矩阵乘法代码

简单回顾一下矩阵乘法:

矩阵乘法要求左矩阵的列数与右矩阵的行数相等m×n的矩阵A,与n×p的矩阵B相乘结果为m×p的矩阵C。详细内容可以查看:

为了方便描述,先进行假設:

  • 矩阵A的行数为m,列数为naij为矩阵A第i行j列的元素。
  • 矩阵B的行数为n列数为p,bij为矩阵B第i行j列的元素

??因为分布式计算的特点,需要找箌相互独立的计算过程以便能够在不同的节点上进行计算而不会彼此影响。根据矩阵乘法的公式C中各个元素的计算都是相互独立的,即各个cij在计算过程中彼此不影响这样的话,在Map阶段可以把计算所需要的元素都集中到同一个key中然后,在Reduce阶段就可以从中解析出各个元素来计算cij

??另外,以a11为例它将会在c11、c12……c1p的计算中使用。也就是说在Map阶段,当我们从HDFS取出一行记录时如果该记录是A的元素,则需要存储成p个<key, value>对并且这p个key互不相同;如果该记录是B的元素,则需要存储成m个<key,

??普遍有一个共识是:数据结构+算法=程序所以在编写代碼之前需要先理清数据存储结构和处理数据的算法。

??经过处理用于计算cij需要的a、b就转变为有相同key("i,j")的数据对,通过value中"a:"、"b:"能区分元素是来自矩阵A还是矩阵B以及具体的位置(在矩阵A的第几列,在矩阵B的第几行)

??通过map数据预处理和shuffle数据分组两个阶段,reduce阶段只需要知道两件事就行:

  • <key,Iterable(value)>对经过计算得到的是矩阵C的哪个元素因为map阶段对数据的处理,key(i,j)中的数据对就是其在矩阵C中的位置,第i行j列
  • Iterable中嘚每个value来自于矩阵A和矩阵B的哪个位置?这个也在map阶段进行了标记对于value(x:y,z),只需要找到y相同的来自不同矩阵(即x分别为a和b)的两个元素取z相乘,然后加和即可

??计算过程已经设计清楚了,就需要对数据结构进行设计大体有两种设计方案:

??第一种:使用最原始嘚表示方式,相同行内不同列数据通过","分割不同行通过换行分割;

??第二种:通过行列表示法,即文件中的每行数据有三个元素通过汾隔符分割第一个元素表示行,第二个元素表示列第三个元素表示数据。这种方式对于可以不列出为0的元素即可以减少稀疏矩阵的數据量。

??在上图中第一种方式存储的数据量小于第二种,但这只是因为例子中的数据设计成这样在现实中,使用分布式计算矩阵塖法的环境中大部分矩阵是稀疏矩阵,且数据量极大在这种情况下,第二种数据结构的优势就显现了出来而且,因为使用分布式计算如果数据大于64m,在map阶段将不能够逐行处理将不能确定数据来自于哪一行。不过由于现实中对于大矩阵的乘法,考虑到存储空间和內存的情况需要特殊的处理方式,有一种是将矩阵进行行列转换然后计算这个时候第一种还是挺实用的。

// 可能在mapA中存在在mapB中不存在的key或相反情况 // 因为,数据定义的时候使用的是稀疏矩阵的定义 // 所以这种只存在于一个map中的key,说明其对应元素为0不影响结果

??比较两種代码,可以很清楚的看出两种实现只是在map阶段有些区别,reduce阶段基本相同对于其中关于行i、列j定义不是从0计数(虽然我倾向于从0开始計数,不用写等号简单),是为了更直观的观察数据处理过程是否符合设计

??在第一种实现中,需要记录当前是读取的哪一行数据所以,这种仅适用于不需要分块的小文件中进行的矩阵乘法运算第二种实现中,每行数据记录了所在行所在列不会有这方面的限制。

??在第二种实现中遍历两个HashMap时,取mapA的key作为循环标准是因为在一般情况下,mapA和mapB的key是相同的(如第一种实现)因为使用稀疏矩阵,兩个不相同的key说明是0可以舍弃不参与计算,所以只使用mapA的key并判断mapB是否存在该key对应的值。

??两种实现的reduce阶段计算最后结果时,都是矗接使用内存存储数据、计算结果所以当数据量很大的时候(通常都会很大,否则不会用分布式处理)极易造成内存溢出,所以对於大矩阵的运算,还需要其他的转换方式比如行列相乘运算、分块矩阵运算、基于最小粒度相乘的算法等方式。另外因为这两份代码嘟是demo,所以代码中缺少过滤错误数据的部分


素有长宽和该位置的值三个属性然后通过成员中的row、col(行列)来找到该值来进行计算,计算理论依据就是我们平时手算的方法

你对这个回答的评价是?

下载百度知道APP抢鲜体验

使用百度知道APP,立即抢鲜体验你的手机镜头里或许有别人想知道的答案。

简单回想一下矩阵乘法:

矩阵乘法要求左矩阵的列数与右矩阵的行数相等m×n的矩阵A,与n×p的矩阵B相乘结果为m×p的矩阵C。具体内容能够查看:

为了方便描写叙述,先进荇如果:

  • 矩阵A的行数为m,列数为naij为矩阵A第i行j列的元素。
  • 矩阵B的行数为n列数为p。bij为矩阵B第i行j列的元素

??由于分布式计算的特点,须偠找到相互独立的计算过程以便能够在不同的节点上进行计算而不会彼此影响。依据矩阵乘法的公式C中各个元素的计算都是相互独立嘚,即各个cij在计算过程中彼此不影响这种话,在Map阶段能够把计算所须要的元素都集中到同一个key中然后,在Reduce阶段就能够从中解析出各个え素来计算cij

??另外,以a11为例它将会在c11、c12……c1p的计算中使用。也就是说在Map阶段,当我们从HDFS取出一行记录时假设该记录是A的元素。則须要存储成p个<key, value>对而且这p个key互不同样。假设该记录是B的元素则须要存储成m个<key, value>对的key应该都是同样的,这样才干被传递到同一个Reduce中

??普遍有一个共识是:数据结构+算法=程序,所以在编写代码之前须要先理清数据存储结构和处理数据的算法

??经过处理,用于计算cij须要嘚a、b就转变为有同样key("i,j")的数据对通过value中"a:"、"b:"能区分元素是来自矩阵A还是矩阵B。以及详细的位置(在矩阵A的第几列在矩阵B的第几行)。

??通过map数据预处理和shuffle数据分组两个阶段reduce阶段仅仅须要知道两件事即可:

  • <key,Iterable(value)>对经过计算得到的是矩阵C的哪个元素?由于map阶段对数据的处理key(i,j)中的数据对。就是其在矩阵C中的位置第i行j列。
  • Iterable中的每一个value来自于矩阵A和矩阵B的哪个位置这个也在map阶段进行了标记。对于value(x:y,z)僅仅须要找到y同样的来自不同矩阵(即x分别为a和b)的两个元素,取z相乘然后加和就可以。

??计算过程已经设计清楚了就须要对数据結构进行设计。大体有两种设计方案:

??第一种:使用最原始的表示方式同样行内不同列数据通过","切割。不同行通过换行切割

??叧外一种:通过行列表示法,即文件里的每行数据有三个元素通过分隔符切割第一个元素表示行,第二个元素表示列第三个元素表示數据。这样的方式对于能够不列出为0的元素即能够降低稀疏矩阵的数据量。

??在上图中第一种方式存储的数据量小于另外一种,但這仅仅是由于样例中的数据设计成这样在现实中,使用分布式计算矩阵乘法的环境中大部分矩阵是稀疏矩阵。且数据量极大在这样嘚情况下,另外一种数据结构的优势就显现了出来并且,由于使用分布式计算假设数据大于64m,在map阶段将不可以逐行处理将不能确定數据来自于哪一行。只是由于现实中对于大矩阵的乘法,考虑到存储空间和内存的情况须要特殊的处理方式,有一种是将矩阵进行行列转换然后计算这个时候第一种还是挺有用的。

// 可能在mapA中存在在mapB中不存在的key或相反情况 // 由于,数据定义的时候使用的是稀疏矩阵的定義 // 所以这样的仅仅存在于一个map中的key。说明其相应元素为0不影响结果

??比較两种代码,能够非常清楚的看出两种实现仅仅是在map阶段囿些差别,reduce阶段基本同样对于当中关于行i、列j定义不是从0计数(尽管我倾向于从0開始计数。不用写等号简单),是为了更直观的观察數据处理过程是否符合设计

??在第一种实现中,须要记录当前是读取的哪一行数据所以。这样的仅适用于不须要分块的小文件里进荇的矩阵乘法运算

另外一种实现中,每行数据记录了所在行所在列不会有这方面的限制。

??在另外一种实现中遍历两个HashMap时。取mapA的key莋为循环标准是由于在普通情况下,mapA和mapB的key是同样的(如第一种实现)由于使用稀疏矩阵,两个不同样的key说明是0能够舍弃不參与计算。所以仅仅使用mapA的key并推断mapB是否存在该key相应的值。

??两种实现的reduce阶段计算最后结果时。都是直接使用内存存储数据、计算结果所以當数据量非常大的时候(通常都会非常大,否则不会用分布式处理)极易造成内存溢出,所以对于大矩阵的运算,还须要其它的转换方式比方行列相乘运算、分块矩阵运算、基于最小粒度相乘的算法等方式。

另外由于这两份代码都是demo,所以代码中缺少过滤错误数据嘚部分

我要回帖

更多关于 矩阵乘法代码 的文章

 

随机推荐