精华内容
下载资源
问答
  • 索引稀疏矩阵乘法(严蔚敏版) 原理 索引稀疏矩阵查找某一列的元素没那么方便,所以在做矩阵...求Q(2,2)的第一时,肯定是M的第一和N的第一列逐乘再累加,然后再M的第一和N的第二列逐乘累加 M(2,3)* ...

    行索引稀疏矩阵乘法(严蔚敏版)

    原理

    行索引稀疏矩阵查找某一列的元素没那么方便,所以在做矩阵乘法时(这里以M乘N=Q为例),严书的做法是:在求Q的某一行的值是,用M的一行去遍历N的每一行,对结果中同列的值进行累加,最后稀疏化存入Q的当前行中,这个过程还原成正常矩阵比较容易理解:
    求Q(2,2)的第一行时,肯定是M的第一行和N的第一列逐乘再累加,然后再M的第一行和N的第二列逐乘累加
    M(2,3)* N(3,2):
    矩阵相乘
    直接算的话就是:
    Q[1,1] = 1*1 + 2*0 + 3*1 = 1+0+3 = 4
    Q[1,2] = 1*0 + 2*1 + 3*1 = 0+2+3 = 5
    这回我们直接同时求两列的值,其实就是改变一下计算顺序:
    改变计算顺序
    这个就相当于严书代码中ctemp的作用,只不过ctemp是直接累加.

    代码

    #include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    const int MAX_E = 1e+4+5, MAX_R = 105;
    
    //严版特色,下标从1开始
    struct Triple{int i,j,e;};
    struct RLSMatrix{
        Triple data[MAX_E];
        int rpos[MAX_R];//行首索引, rpos[i]指向第i行中的首元素在data中的序号, 则rpos[i+1]-1指向第i行中最后一个非0元素在N.data中的序号.
        int rows, cols, elems;
    };
    
    int ctemp[MAX_R];//Q的第i行元素结果累加器,算完一行就压缩存储进Q.data中
    
    
    RLSMatrix mul(RLSMatrix M, RLSMatrix N){
        RLSMatrix Q;
        Q.rows = M.rows;Q.cols = N.cols;Q.elems = 0;
        if(M.elems * N.elems != 0){                              // Q是非零矩阵
            for(int arow = 1; arow <= M.rows; arow++){
                memset(ctemp, 0, sizeof(ctemp));              //到了下一行,清零
                Q.rpos[arow] = Q.elems+1;                  //新一行的行首索引是当前data中元素个数+1,从该处继续向data中存三元组
    
                int tp;      //用tp指向data中该行行末的下一个位置,方便遍历
                if(arow < M.rows) tp = M.rpos[arow+1];    //如果不是最后一行, tp指向下一行行首
                else tp = M.elems+1;   //最后一行, tp直接指向data中最后一个+1
    
                for(int p = M.rpos[arow];p < tp; p++){  //对当前行找到的每一个非零元
                    int brow = M.data[p].j;     //找到对应元在N中的行号(M中某行第三列的元素, 肯定和N中第三行某列的元素相乘)
                    int t;//和tp同样的套路
                    if(brow < N.rows) t = N.rpos[brow+1];
                    else t = N.elems+1;
    
                    for(int q = N.rpos[brow]; q < t; q++){//这里不是直接算出M的某行乘N的某列的值
                        //而是用M的某行,去遍历N的所有行,然后对每行的应该在同列的值进行累加
                        int ccol = N.data[q].j;
                        ctemp[ccol] += M.data[p].e * N.data[q].e;//累加器
                    }
                }//求得Q中第crow(=arow)行的非零元
    
                for(int ccol = 1; ccol <= Q.cols; ++ccol){//用M的一行遍历完了整个N矩阵
                    if(ctemp[ccol]){
                        Q.data[++Q.elems] = {arow, ccol, ctemp[ccol]};//压缩存储
                    }
                }
            }
        }
        return Q;
    }
    
    RLSMatrix makeMat(){
        /*
         * 输入rows, cols, 三元组个数
         * 输入三元组
         */
        RLSMatrix A;
        cin>>A.rows>>A.cols>>A.elems;
        for(int i = 1;i <= A.elems;i++){
            int x,y,e;
            cin>>x>>y>>e;
            A.data[i] = {x,y,e};
        }
    
        /*
         根据乘法中这段代码写的初始化rpos数组:
             int tp;      //用tp指向data中该行行末的下一个位置,方便遍历
             if(arow < M.rows) tp = M.rpos[arow+1];    //如果不是最后一行, tp指向下一行行首
             else tp = M.elems+1;   //最后一行, tp直接指向data中最后一个+1
             for(int p = M.rpos[arow];p < tp; p++) ...
            可以看出如果某行没有元素,则让tp = M.rpos[arow]则可不进行遍历,也就是M.rpos[arow] = M.rpos[arow+1]
            而当最后几行为空时,并不会执行else tp = M.elems+1;这时应该把rpos最后几行空的填成M.elems+1
         */
    
        int row = 1;
        for(int e = 1;e <= A.elems; e++){
            int arow = A.data[e].i;
            while(row <= arow){
                A.rpos[row++] = e;
            }
        }
        while(row <= A.rows){//如果最后几行没有元素,让索引指到elems+1的位置
            A.rpos[row++] = A.elems+1;
        }
        return A;
    }
    
    void printMat(RLSMatrix A){
        cout<<"rows:"<<A.rows<<" cols:"<<A.cols<<" elems:"<<A.elems<<endl;
        cout<<"-------------------------"<<endl;
        cout<<"data:"<<endl;
        for(int i = 1;i <= A.elems;i++) {
            cout<<setw(4)<<A.data[i].i<<setw(4)<<A.data[i].j<<setw(4)<<A.data[i].e<<endl;
        }
        cout<<"-------------------------"<<endl;
        cout<<"rpos: ";
        for(int j = 1;j <= A.rows; j++){
            cout<<A.rpos[j]<<' ';
        }
        cout<<endl<<endl;
    }
    
    int main(){
        ios::sync_with_stdio(false);
        RLSMatrix A = makeMat();
        printMat(A);
        RLSMatrix B = makeMat();
        printMat(B);
        RLSMatrix C = mul(A, B);
        printMat(C);
        return 0;
    }
    /*
     严书上的例子
     3 4 4
     1 1 3
     1 4 5
     2 2 -1
     3 1 2
    
     4 2 4
     1 2 2
     2 1 1
     3 1 -2
     3 2 4
     */
    
    

    结果

    展开全文
  • Tensorflow维、三维、四维矩阵运算(矩阵相乘,点乘,/累加)1. 矩阵相乘根据矩阵相乘的匹配原则,左乘矩阵数要等于右乘矩阵的行数。在多维(三维、四维)矩阵的相乘中,需要最后两维满足匹配原则。可以将多维...

    Tensorflow二维、三维、四维矩阵运算(矩阵相乘,点乘,行/列累加)

    1. 矩阵相乘

    根据矩阵相乘的匹配原则,左乘矩阵的列数要等于右乘矩阵的行数。

    在多维(三维、四维)矩阵的相乘中,需要最后两维满足匹配原则。

    可以将多维矩阵理解成:(矩阵排列,矩阵),即后两维为矩阵,前面的维度为矩阵的排列。

    比如对于(2,2,4)来说,视为2个(2,4)矩阵。

    对于(2,2,2,4)来说,视为2*2个(2,4)矩阵。

    import tensorflow as tf

    a_2d = tf.constant([1]*6, shape=[2, 3])

    b_2d = tf.constant([2]*12, shape=[3, 4])

    c_2d = tf.matmul(a_2d, b_2d)

    a_3d = tf.constant([1]*12, shape=[2, 2, 3])

    b_3d = tf.constant([2]*24, shape=[2, 3, 4])

    c_3d = tf.matmul(a_3d, b_3d)

    a_4d = tf.constant([1]*24, shape=[2, 2, 2, 3])

    b_4d = tf.constant([2]*48, shape=[2, 2, 3, 4])

    c_4d = tf.matmul(a_4d, b_4d)

    with tf.Session() as sess:

    tf.global_variables_initializer().run()

    print("# {}*{}={} \n{}".

    format(a_2d.eval().shape, b_2d.eval().shape, c_2d.eval().shape, c_2d.eval()))

    print("# {}*{}={} \n{}".

    format(a_3d.eval().shape, b_3d.eval().shape, c_3d.eval().shape, c_3d.eval()))

    print("# {}*{}={} \n{}".

    format(a_4d.eval().shape, b_4d.eval().shape, c_4d.eval().shape, c_4d.eval()))

    2. 点乘

    点乘指的是shape相同的两个矩阵,对应位置元素相乘,得到一个新的shape相同的矩阵。

    a_2d = tf.constant([1]*6, shape=[2, 3])

    b_2d = tf.constant([2]*6, shape=[2, 3])

    c_2d = tf.multiply(a_2d, b_2d)

    a_3d = tf.constant([1]*12, shape=[2, 2, 3])

    b_3d = tf.constant([2]*12, shape=[2, 2, 3])

    c_3d = tf.multiply(a_3d, b_3d)

    a_4d = tf.constant([1]*24, shape=[2, 2, 2, 3])

    b_4d = tf.constant([2]*24, shape=[2, 2, 2, 3])

    c_4d = tf.multiply(a_4d, b_4d)

    with tf.Session() as sess:

    tf.global_variables_initializer().run()

    print("# {}*{}={} \n{}".

    format(a_2d.eval().shape, b_2d.eval().shape, c_2d.eval().shape, c_2d.eval()))

    print("# {}*{}={} \n{}".

    format(a_3d.eval().shape, b_3d.eval().shape, c_3d.eval().shape, c_3d.eval()))

    print("# {}*{}={} \n{}".

    format(a_4d.eval().shape, b_4d.eval().shape, c_4d.eval().shape, c_4d.eval()))

    另外,点乘的其中一方可以是一个常数,也可以是一个和矩阵行向量等长(即列数)的向量。

    因为在点乘过程中,会自动将常数或者向量进行扩维。

    a_2d = tf.constant([1]*6, shape=[2, 3])

    k = tf.constant(2)

    l = tf.constant([2, 3, 4])

    b_2d_1 = tf.multiply(k, a_2d) # tf.multiply(a_2d, k) is also ok

    b_2d_2 = tf.multiply(l, a_2d) # tf.multiply(a_2d, l) is also ok

    a_3d = tf.constant([1]*12, shape=[2, 2, 3])

    b_3d_1 = tf.multiply(k, a_3d) # tf.multiply(a_3d, k) is also ok

    b_3d_2 = tf.multiply(l, a_3d) # tf.multiply(a_3d, l) is also ok

    a_4d = tf.constant([1]*24, shape=[2, 2, 2, 3])

    b_4d_1 = tf.multiply(k, a_4d) # tf.multiply(a_4d, k) is also ok

    b_4d_2 = tf.multiply(l, a_4d) # tf.multiply(a_4d, l) is also ok

    with tf.Session() as sess:

    tf.global_variables_initializer().run()

    print("# {}*{}={} \n{}".

    format(k.eval().shape, a_2d.eval().shape, b_2d_1.eval().shape, b_2d_1.eval()))

    print("# {}*{}={} \n{}".

    format(l.eval().shape, a_2d.eval().shape, b_2d_2.eval().shape, b_2d_2.eval()))

    print("# {}*{}={} \n{}".

    format(k.eval().shape, a_3d.eval().shape, b_3d_1.eval().shape, b_3d_1.eval()))

    print("# {}*{}={} \n{}".

    format(l.eval().shape, a_3d.eval().shape, b_3d_2.eval().shape, b_3d_2.eval()))

    print("# {}*{}={} \n{}".

    format(k.eval().shape, a_4d.eval().shape, b_4d_1.eval().shape, b_4d_1.eval()))

    print("# {}*{}={} \n{}".

    format(l.eval().shape, a_4d.eval().shape, b_4d_2.eval().shape, b_4d_2.eval()))

    4. 行/列累加

    a_2d = tf.constant([1]*6, shape=[2, 3])

    d_2d_1 = tf.reduce_sum(a_2d, axis=0)

    d_2d_2 = tf.reduce_sum(a_2d, axis=1)

    a_3d = tf.constant([1]*12, shape=[2, 2, 3])

    d_3d_1 = tf.reduce_sum(a_3d, axis=1)

    d_3d_2 = tf.reduce_sum(a_3d, axis=2)

    a_4d = tf.constant([1]*24, shape=[2, 2, 2, 3])

    d_4d_1 = tf.reduce_sum(a_4d, axis=2)

    d_4d_2 = tf.reduce_sum(a_4d, axis=3)

    with tf.Session() as sess:

    tf.global_variables_initializer().run()

    print("# a_2d 行累加得到shape:{}\n{}".format(d_2d_1.eval().shape, d_2d_1.eval()))

    print("# a_2d 列累加得到shape:{}\n{}".format(d_2d_2.eval().shape, d_2d_2.eval()))

    print("# a_3d 行累加得到shape:{}\n{}".format(d_3d_1.eval().shape, d_3d_1.eval()))

    print("# a_3d 列累加得到shape:{}\n{}".format(d_3d_2.eval().shape, d_3d_2.eval()))

    print("# a_4d 行累加得到shape:{}\n{}".format(d_4d_1.eval().shape, d_4d_1.eval()))

    print("# a_4d 列累加得到shape:{}\n{}".format(d_4d_2.eval().shape, d_4d_2.eval()))

    以上这篇Tensorflow矩阵运算实例(矩阵相乘,点乘,行/列累加)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家。

    展开全文
  • 矩阵乘法

    2017-10-20 20:21:06
    矩阵乘法的原理:第一个矩阵每一与第个矩阵的每一相乘之和,列入第一个矩阵第一与第个矩阵的第一相乘之和是新矩阵的第一第一,以此类推 矩阵的乘法结果是得到一个矩阵的行数和第个矩阵的数; #...
    矩阵乘法:两个二维数组的乘法,能够进行乘法的条件是第一个矩阵的列数必须等于第二个矩阵的行数;
    矩阵乘法的原理:第一个矩阵每一行与第二个矩阵的每一列相乘之和,例如第一个矩阵第一行与第二个矩阵的第一列相乘之和是新矩阵的第一行第一列,以此类推
    矩阵的乘法结果是得到一个矩阵的行数和第二个矩阵的列数;
    #include<iostream>
    using namespace std;
    #define rows 10
    #define cols 10
    int a[rows][cols];
    int b[rows][cols];
    int c[rows][cols];
    int main()
    {
        int m,n,p,q;
        cin>>m>>n;
        for(int i=0;i<m;i++)
        {
            for(int j=0;j<n;j++)//读入矩阵a,m行n列
            {
                cin>>a[i][j];
            }
            
        }
        cin>>p>>q;
        for(int i=0;i<p;i++)
        {
             for(int j=0;j<q;j++)//读入矩阵b,p行q列
             {
                   cin>>b[i][j];
             }
          
        }
            for(int i=0;i<m;i++)
            {
                for(int j=0;j<q;j++)
                {
                    for(int k=0;k<p;k++)
                    {
                         c[i][j]+=a[i][k]*b[k][j];//计算矩阵c,m行q列
                    }
                   
                }
            }
            cout<<m<<" "<<q<<endl;
                for(int i=0;i<m;i++)
                {
                     for(int j=0;j<q;j++)
                     {
                         cout<<c[i][j]<<"\t";//输出矩阵c
                     }
                        cout<<endl;
                }

        return 0;

    }

    展开全文
  • 理解矩阵乘法考研需要考一门课《线性代数》,这门课其实是教矩阵...教科书告诉你,计算规则是,第一个矩阵第一的每个数字(2 和 1),各自乘以第个矩阵第一对应位置的数字(1 和 1),然后将乘积相加( 2 x 1...

    ba8728f8e59c397e0fb4693a3754d88e.png

    理解矩阵乘法

    考研需要考一门课《线性代数》,这门课其实是教矩阵。

    刚学的时候,还蛮简单的,矩阵加法就是相同位置的数字加一下。

    矩阵乘法也类似,矩阵乘以一个常数,就是所有位置都乘以这个数。

    但是,等到矩阵乘以矩阵的时候,一切就不一样了。

    这个结果是怎么算出来的?

    教科书告诉你,计算规则是,第一个矩阵第一行的每个数字(2 和 1),各自乘以第二个矩阵第一列对应位置的数字(1 和 1),然后将乘积相加( 2 x 1 + 1 x 1),得到结果矩阵左上角的那个值 3。

    94e039aa5c50c0e99e55d85d963f95b5.png

    也就是说,结果矩阵第

    行与第
    列交叉位置的那个值,等于第一个矩阵第
    行与第二个矩阵第
    列,对应位置的每个值的乘积之和。

    怎么会有这么奇怪的规则?

    我一直没理解这个规则的含义,导致《线性代数》这门课就没学懂。研究生时发现,线性代数是向量计算的基础,很多重要的数学模型都要用到向量计算,所以我做不了复杂模型。这一直让我有点伤心。

    前些日子,受到一篇文章的启发,我终于想通了,矩阵乘法到底是什么东西。关键就是一句话,矩阵的本质就是线性方程式,两者是一一对应关系。如果从线性方程式的角度,理解矩阵乘法就毫无难度。

    下面是一组线性方程式:

    矩阵的最初目的,只是为线性方程组提供一个简写形式。

    老实说,从上面这种写法,已经能看出矩阵乘法的规则了:系数矩阵第一行的 2 和 1,各自与

    的乘积之和,等于 3。不过,这不算严格的证明,只是线性方程式转为矩阵的书写规则。

    下面才是严格的证明:有三组未知数

    ,其中
    的关系如下:

    的关系如下:

    有了这两组方程式,就可以求

    的关系。从矩阵来看,很显然,只要把第二个矩阵代入第一个矩阵即可。

    从方程式来看,也可以把第二个方程组代入第一个方程组:

    上面的方程组可以整理成下面的形式:

    最后那个矩阵等式,与前面的矩阵等式一一对照,就会得到下面的关系。

    矩阵乘法的计算规则,从而得到证明。

    展开全文
  • 最近学习C++,做了一个矩阵乘法的练习。先说一下功能,输入两个矩阵A,B,大小自己定,换行用;表示(matlab的习惯)。然后输出A*B的矩阵。1.思路首先,由于输入的矩阵维数是随机的,因此,我们要设计程序,手动把...
  • 矩阵乘法

    万次阅读 2018-09-03 17:09:16
    1. 有两个矩阵:A和B(矩阵...矩阵乘法的结果为的关系为:数量为A的数量, 数量为B的数量 2. 因为每一次都是A的与B的,所以最外层的两层循环可以使用A的的数量的变化,B的的数量进行变化 而...
  • 矩阵乘法运算

    2014-02-15 21:25:42
    编写一个函数实现MK列矩阵与KN列矩阵乘法。设A为MK列矩阵,B为KN列矩阵,则C=A×B,乘积C为MN列矩阵。 (阵乘法的规则是:设A[m,k],B[k,n],则C[m,n]= A[m,k] ×B[k,n]。)   问题分析:定义两个维...
  • C++矩阵乘法

    千次阅读 2017-03-09 17:30:20
    用惯了数学库,有的时候有些基本的运算... (2)矩阵乘法的要点,新的结果矩阵的第i第j是矩阵A的第i与矩阵B的第j的乘积,这一点不熟悉,写程序就会有点吃力;对程序结构思路就会存在不清晰的地方; (3)有很多可
  • 假设有一个MMMNNN矩阵AAA,首先在C++中为了能够使用维索引,需要定义长度为M∗NM*NM∗N的一级数据指针float ∗a_datafloat\ *a\_datafloat ∗a_data保存所有矩阵元素,然后定义长度为MMM的...
  • c++实现矩阵乘法运算Here is the program for matrix multiplication in C. 这是C语言中矩阵乘法的程序。 m and n are rows and columns of first matrix. m和n是第一矩阵的。 p and q are rows and ...
  • 再下一的输入是整数p,q,表示下一个矩阵是pq(n=p),再接下来就是一个pq矩阵。 要求输出两个矩阵相乘的结果矩阵(1《m,n,p,q《=8)。 输入样例: 输出样例: 2 3 10 19 30 2 4...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 628
精华内容 251
关键字:

二行二列矩阵乘法