1.1 矩阵乘法介绍

矩阵乘法的定义

  矩阵乘法的定义要求相乘的两个矩阵A和B,A的列必须等于B的行,结果为一个矩阵C。C的每个元素是A的行和B的列对应元素的乘积的和,也就是他们的标准内积(标准内积还没学到,可以点这个链接看看)。用数学语言描述就是:
A m × n = ( a 11 ⋯ a 1 n ⋮ ⋱ ⋮ a m 1 ⋯ a m n ) B n × p = ( b 11 ⋯ b 1 p ⋮ ⋱ ⋮ b n 1 ⋯ b n p ) C m × p = ( ∑ k = 0 n a 1 k b k 1 ⋯ ∑ k = 0 n a 1 k b k p ⋮ ⋱ ⋮ ∑ k = 0 n a m k b k 1 ⋯ ∑ k = 0 n a m k b k p ) A^{m\times n}=\begin{pmatrix}a_{11} & \cdots & a_{1n}\\ \vdots & \ddots & \vdots\\ a_{m1} & \cdots & a_{mn} \end{pmatrix}\\ B^{n\times p}=\begin{pmatrix} b_{11} & \cdots & b_{1p}\\ \vdots & \ddots & \vdots\\ b_{n1} & \cdots & b_{np} \end{pmatrix}\\ C^{m\times p}=\begin{pmatrix} \sum_{k=0}^{n} a_{1k}b_{k1} & \cdots & \sum_{k=0}^{n} a_{1k}b_{kp} \\ \vdots & \ddots & \vdots\\ \sum_{k=0}^{n} a_{mk}b_{k1} & \cdots & \sum_{k=0}^{n} a_{mk}b_{kp} \end{pmatrix} Am×n= a11am1a1namn Bn×p= b11bn1b1pbnp Cm×p= k=0na1kbk1k=0namkbk1k=0na1kbkpk=0namkbkp
  结果C的任意一个元素是这样计算出来的:
c i j = ∑ k = 0 n a i k b k j c_{ij}=\sum_{k=0}^{n} a_{ik}b_{kj} cij=k=0naikbkj
  矩阵乘法有很多意义,但是我只写三种:一、线性方程组;二、线性变换;三、线性组合。因为这三种对于初学者来说,比较容易理解。

线性方程组

  线性方程组可以看作矩阵与向量的乘积,比如下列线性方程组:
5 x + 3 y + 2 x = 10 − x + 4 y + 6 z = − 10 − 2 x − 3 y − 4 z = 9 5x+3y+2x=10\\ -x+4y+6z=-10\\ -2x-3y-4z=9 5x+3y+2x=10x+4y+6z=102x3y4z=9
  可以表示为矩阵和一个未知向量相乘:
( 5 3 2 − 1 4 6 − 2 − 3 − 4 ) x = ( 10 − 10 9 ) x = ( 19 8 7 8 − 9 4 ) \begin{pmatrix} 5 & 3 & 2\\ -1 & 4 & 6 \\ -2 & -3 & -4 \end{pmatrix}x=\begin{pmatrix} 10\\ -10\\ 9 \end{pmatrix}\\ x=\begin{pmatrix} \frac{19}8\\ \frac{7}8\\ -\frac{9}4 \end{pmatrix} 512343264 x= 10109 x= 8198749

线性变换

  至于什么样的变换才能叫线性变换,这个是纯代数的问题,比较难,我这里就不过多讲了,但是行变换是一个线性变换,我举过例子,那么多个行变换就可以通过乘法组合起来,这点在后续的矩阵的LU分解中特别重要!尤其是多个线性变换先后作用,可以连乘起来,组成一个线性变换,比如下列行变换:
x 1 = ( 1 0 0 0 2 1 0 0 0 0 1 0 0 0 0 1 ) x 2 = ( 1 0 0 0 0 1 0 0 2 0 1 0 0 0 0 1 ) x_1= \begin{pmatrix} 1 & 0 & 0 & 0\\ 2 & 1 & 0 & 0\\ 0 & 0 & 1 & 0\\ 0 & 0 & 0 & 1 \end{pmatrix}\\ x_2= \begin{pmatrix} 1 & 0 & 0 & 0\\ 0 & 1 & 0 & 0\\ 2 & 0 & 1 & 0\\ 0 & 0 & 0 & 1 \end{pmatrix} x1= 1200010000100001 x2= 1020010000100001
   x 1 x_1 x1的作用是把第一行乘以两倍加到第二行, x 2 x_2 x2的作用是把第一行乘以两倍加到第三行,那么先后进行这两种作用就是 x 1 x 2 x_1x_2 x1x2,把这两个矩阵乘起来使用就行了。
x 1 x 2 = ( 1 0 0 0 2 1 0 0 2 0 1 0 0 0 0 1 ) x_1x_2=\begin{pmatrix} 1 & 0 & 0 & 0\\ 2 & 1 & 0 & 0\\ 2 & 0 & 1 & 0\\ 0 & 0 & 0 & 1 \end{pmatrix} x1x2= 1220010000100001
  这个乘完的矩阵会把矩阵第一行乘以两倍,加到第二行和第三行。利用矩阵乘法,可以把多个线性变换组合起来,节省了大量计算量。

线性组合

  线性组合在几何空间里用得特别多。比如一个向量的坐标是 ( 1 , 1 , 1 ) (1,1,1) (1,1,1),那么就可以看成是自然基和 ( 1 , 1 , 1 ) T (1,1,1)^T (1,1,1)T这个向量的乘法,于是有:
( 1 0 0 0 1 0 0 0 1 ) ( 1 1 1 ) = ( 1 1 1 ) \begin{pmatrix} 1 & 0 & 0\\ 0 & 1 & 0\\ 0 & 0 & 1 \end{pmatrix}\begin{pmatrix} 1\\ 1 \\ 1 \end{pmatrix}=\begin{pmatrix} 1 \\ 1 \\ 1 \end{pmatrix} 100010001 111 = 111
  标准坐标系,计算没什么意义,假如坐标系换了呢?比如说坐标系换成了这样:
x 1 = ( 1 0 0 ) , x 2 = ( 1 2 0 ) , x 3 = ( 1 2 3 ) x_1=\begin{pmatrix} 1 \\ 0 \\ 0 \end{pmatrix}, x_2=\begin{pmatrix} 1 \\ 2 \\ 0 \end{pmatrix}, x_3=\begin{pmatrix} 1 \\ 2 \\ 3 \end{pmatrix} x1= 100 ,x2= 120 ,x3= 123
  那么其实就是要求三个比例 α 1 , α 2 , α 3 \alpha_1,\alpha_2,\alpha_3 α1,α2,α3组成一个线性组合,使得下式成立:
α 1 ( 1 0 0 ) + α 2 ( 1 2 0 ) + α 3 ( 1 2 3 ) = ( 1 1 1 ) \alpha_1\begin{pmatrix} 1 \\ 0 \\ 0 \end{pmatrix}+\alpha_2 \begin{pmatrix} 1 \\ 2\\ 0 \end{pmatrix}+ \alpha_3\begin{pmatrix} 1 \\ 2 \\ 3 \end{pmatrix}=\begin{pmatrix} 1 \\ 1 \\ 1 \end{pmatrix} α1 100 +α2 120 +α3 123 = 111
  其实也可以转为矩阵乘法,就是:
( 1 1 1 0 2 2 0 0 3 ) ( α 1 α 2 α 3 ) = ( 1 1 1 ) α 1 = 1 2 , α 2 = 1 6 , α 3 = 1 3 \begin{pmatrix} 1 & 1 & 1\\ 0 & 2 & 2\\ 0 & 0 & 3 \end{pmatrix}\begin{pmatrix} \alpha_1 \\ \alpha_2 \\ \alpha_3 \end{pmatrix}=\begin{pmatrix} 1 \\ 1 \\ 1 \end{pmatrix}\\ \alpha_1=\frac12,\alpha_2=\frac16,\alpha_3=\frac13 100120123 α1α2α3 = 111 α1=21,α2=61,α3=31

python实现

  按照定义实现就是这样:

    def __mul__(self, other):
        if isinstance(other, sympy.Expr):
            return Matrix([[sympy.simplify(e * other) for e in line] for line in self.__lines])
        columns = len(self.__lines)
        rows = len(other.__lines[0])
        if columns != rows:
            raise Exception("矩阵A列数%d != 矩阵B的行数%d" % (columns, rows))
        # 弄一个m行p列的新矩阵
        m = len(self.__lines[0])
        n = columns
        p = len(other.__lines)

        result = [[0] * m for _ in range(0, p)]
        # i 代表 A矩阵的行
        for i in range(0, m):
            # j 代表 B 矩阵的列
            for j in range(0, p):
                # 第一个矩阵的行 与第二个矩阵列的乘积和
                # k 代表 A矩阵的列和B矩阵的行
                for k in range(0, n):
                    mul = self.__lines[k][i] * other.__lines[j][k]
                    result[j][i] += mul
                if not isinstance(result[j][i], complex):
                    result[j][i] = round(result[j][i], 2)
        return Matrix(result)

  有没有更快的算法呢?是有的,我的下一篇文章就是专门介绍比常规算法更快的算法:Strassen算法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

醒过来摸鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值