• 码农眼中的数学之~矩阵专栏(附Numpy讲解)


     

    2.矩阵专栏

    吐槽一下:矩阵本身不难,但是矩阵的写作太蛋疼了 (⊙﹏⊙)汗 还好有Numpy,不然真的崩溃了...

    LaTex有没有一个集成了很多常用公式以及推导或者含题库的在线编辑器?

    代码裤子:https://github.com/lotapp/BaseCode

    在线编程系:https://mybinder.org/v2/gh/lotapp/BaseCode/master

    数学基础:https://www.cnblogs.com/dotnetcrazy/p/9294292.html

    Numpy基础:https://www.cnblogs.com/dotnetcrazy/p/9309555.html

    在线预览http://github.lesschina.com/python/ai/math/矩阵专栏.html

    2.1.矩阵的定义

    矩阵:是一个按照长方阵列排列的复数或实数集合。

    通俗讲就是:把数排成m行n列后,然后用中括号把它们括住,这种形式的组合就是矩阵了~ eg:

    $egin{bmatrix} &a_{11}&a_{12}&a_{13}&...&a_{1n} \ &a_{21}&a_{22}&a_{23}&...&a_{2n} \ &a_{31}&a_{32}&a_{33}&...&a_{3n} \ &vdots&vdots&vdots&ddots&vdots\ &a_{m1}&a_{m2}&a_{m3}&...&a_{mn} \ end{bmatrix}$

    比如上面这个示例就是一个m × n的矩阵(m行n列的矩阵),如果m=n那么就叫做n阶方阵,eg:

    $egin{bmatrix} 1&2&3 \ 4&5&6 \ 7&8&9 end{bmatrix}$

    这个就是3阶方阵


    如果回到中学,老师肯定都是通过一次方程组来引入矩阵(逆天的老师是这么讲的):

    $egin{cases}x_1+x_2=-1\2x_1-x_2=4\3x_1+5x_2=-7\end{cases}$ ==> $egin{bmatrix}1&1\2&-1\3&5end{bmatrix}egin{bmatrix}x_1\x_2end{bmatrix}=egin{bmatrix}-1\4\-7end{bmatrix}$

    如果你方程组都忘记怎么解的话...好吧还是说下吧:“比如这题,可以先把x2移到右边,这样x1就等于一个表达式了(x1=-x2-1),然后带入第二个表达式就可以解出x1和x2了,一次的其实两个表达式就可以解出了,剩下的你可以把值带进去验证一下”

    2.2.矩阵的运算(含幂运算)

    2.2.1.加、减

    加减比较简单,就是对应元素相加减 (只有行列都相同的矩阵才可以进行)

    就不用麻烦的LaTex一行行打了,咱们用更方便的 NumPy 来演示一下矩阵加法(不懂代码的直接看结果,不影响阅读的)

    Numpy有专门的矩阵函数(np.mat),用法和ndarray差不多,我们这边使用经常使用ndarray类型,基础忘记了可以去查看一下:Numpy基础

    扩展:矩阵的加法运算满足交换律:A + B = B + A (乘法不行)

    In [1]:
    import numpy as np
    
    In [2]:
    # 创建两个集合
    A = np.arange(1,10).reshape((3,3))
    B = np.arange(9).reshape((3,3))
    
    print(A)
    print("-"*5)
    print(B)
    
     
    [[1 2 3]
     [4 5 6]
     [7 8 9]]
    -----
    [[0 1 2]
     [3 4 5]
     [6 7 8]]
    
    In [3]:
    # 加法
    A + B
    
    Out[3]:
    array([[ 1,  3,  5],
           [ 7,  9, 11],
           [13, 15, 17]])
    In [4]:
    # 和A+B相等
    B + A
    
    Out[4]:
    array([[ 1,  3,  5],
           [ 7,  9, 11],
           [13, 15, 17]])
    In [5]:
    # 减法
    A - B
    
    Out[5]:
    array([[1, 1, 1],
           [1, 1, 1],
           [1, 1, 1]])
    In [6]:
    ################ 变化来了 ################
    
    In [7]:
    # 之前说过 ”只有行列都相同的矩阵才可以进行“ 来验证一下
    # 创建一个2行3列的矩阵
    C = np.arange(6).reshape((2,3))
    D = np.arange(6).reshape((3,2))
    
    print(C)
    print("-"*5)
    print(D)
    
     
    [[0 1 2]
     [3 4 5]]
    -----
    [[0 1]
     [2 3]
     [4 5]]
    
    In [8]:
    # 2行3列的矩阵 + 3行2列的矩阵
    C + D # 不同形状的矩阵不能进行加运算
    
     
    ---------------------------------------------------------------------------
    ValueError                                Traceback (most recent call last)
    <ipython-input-8-bc97e29f7e31> in <module>()
          1 # 2行3列的矩阵 + 3行2列的矩阵
    ----> 2C + D # 不同形状的矩阵不能进行加运算
    
    ValueError: operands could not be broadcast together with shapes (2,3) (3,2) 
    In [9]:
    C - D # 不同形状的矩阵不能进行减运算
    
     
    ---------------------------------------------------------------------------
    ValueError                                Traceback (most recent call last)
    <ipython-input-9-ca5169d0bf6c> in <module>()
    ----> 1C - D # 不同形状的矩阵不能进行减运算
    
    ValueError: operands could not be broadcast together with shapes (2,3) (3,2) 
     

    2.2.2.数乘、数除

    这个也比较简单,就是和每个元素相乘,eg:2×A,A原本的每一个元素都扩大了两倍

    数除其实就是乘以倒数(1/x)

    In [10]:
    print(A)
    
     
    [[1 2 3]
     [4 5 6]
     [7 8 9]]
    
    In [11]:
    # 比如2×A,A原本的每一个元素都扩大了两倍
    2 * A
    
    Out[11]:
    array([[ 2,  4,  6],
           [ 8, 10, 12],
           [14, 16, 18]])
    In [12]:
    print(A)
    
     
    [[1 2 3]
     [4 5 6]
     [7 8 9]]
    
    In [13]:
    # 友情提醒:Numpy里面的运算基本上都是针对每一个元素
    A / 2
    
    Out[13]:
    array([[0.5, 1. , 1.5],
           [2. , 2.5, 3. ],
           [3.5, 4. , 4.5]])
     

    2.2.3.矩阵乘法

    矩阵乘法还是要用LaTex演示一下的,不然有些朋友可能还是觉得比较抽象:(大家有什么好用的LaTex在线编辑器可以推荐的)

    拿上面那个方程组来演示一下:

    $egin{bmatrix}1&1\2&-1\3&5end{bmatrix}egin{bmatrix}x_1\x_2end{bmatrix} ==> egin{cases}x_1+x_2\2x_1-x_2\3x_1+5x_2end{cases}$

    稍微变化一下就更形象了:

    $egin{bmatrix}1&1\2&-1\3&5end{bmatrix}egin{bmatrix}x_1&y_1\x_2&y_2end{bmatrix} ==> egin{cases}x_1+x_2\2x_1-x_2\3x_1+5x_2end{cases} egin{cases}y_1+y_2\2y_1-x_2\3y_1+5y_2end{cases}==>egin{bmatrix}x_1+x_2&y_1+y_2\2x_1-x_2&2y_1-y_2\3x_1+5x_2&3y_1+5y_2end{bmatrix}$

    举个简单的例子:A×B

    $egin{bmatrix} 1&2 \3&4 end{bmatrix}egin{bmatrix} 4&3 \2&1 end{bmatrix}=egin{bmatrix} 1*4+2*2&1*3+2*1 \3*4+4*2&3*3+4*1 end{bmatrix}=egin{bmatrix} 8&5 \20&13 end{bmatrix}$

    以后记不得怎么乘就自己推一下,值得注意的是:

    两个矩阵的乘法仅当第一个矩阵A的列数(column)和另一个矩阵B的行数(row)相等才可以进行计算

    你这样想就记得了:$egin{bmatrix} 1&2 \3&4 end{bmatrix}egin{bmatrix} x_1 end{bmatrix} 还原成方程组就是这样egin{cases}1*x_1+2*?\3*x_1+4*?end{cases}\这是什么鬼?至少得这样吧:egin{bmatrix} 1&2 \3&4 end{bmatrix}egin{bmatrix} x_1 \x_2 end{bmatrix}$

    In [14]:
    # 通过代码看一看
    A = np.array([[1,2],[3,4]])
    B = np.array([[4,3],[2,1]])
    
    print(A)
    print("-"*5)
    print(B)
    
     
    [[1 2]
     [3 4]]
    -----
    [[4 3]
     [2 1]]
    
    In [15]:
    # 注意一下,Numpy里面的乘法默认是每个数对应相乘
    # 如果是矩阵相乘可以使用dot()方法
    # 或者你创建矩阵对象,这样×默认就是矩阵乘法了
    
    A.dot(B) # 矩阵A×矩阵B
    
    Out[15]:
    array([[ 8,  5],
           [20, 13]])
     

    程序验证了我们上面的运算结果,还得注意一下:

    A×BB×A是不一样的,eg:B×A

    $egin{bmatrix} 4&3 \2&1 end{bmatrix}egin{bmatrix} 1&2 \3&4 end{bmatrix}=egin{bmatrix} 4*1+3*3&4*2+3*4 \2*1+1*3&2*2+1*4 end{bmatrix}=egin{bmatrix} 13&20 \5&8 end{bmatrix}$

    如果你乘着乘着就忘记到底怎么乘,就把右边的矩阵换成x1,x2,然后就会了

    In [16]:
    print(A)
    print("-"*5)
    print(B)
    
     
    [[1 2]
     [3 4]]
    -----
    [[4 3]
     [2 1]]
    
    In [17]:
    B.dot(A) # 矩阵B×矩阵A
    
    Out[17]:
    array([[13, 20],
           [ 5,  8]])
    In [18]:
    ################ 变化来了 ################
    
    In [19]:
    # 来验证一下”两个矩阵的乘法仅当第一个矩阵A的列数(column)和另一个矩阵D的行数(row)相等才可以进行计算“
    print(A)
    print("-"*5)
    print(D)
    
     
    [[1 2]
     [3 4]]
    -----
    [[0 1]
     [2 3]
     [4 5]]
    
    In [20]:
    # A有2列 D有3行
    A.dot(D) # 不能乘
    
     
    ---------------------------------------------------------------------------
    ValueError                                Traceback (most recent call last)
    <ipython-input-20-c1a9f22a6f8d> in <module>()
          1 # A有2列 D有3行
    ----> 2A.dot(D) # 不能乘
    
    ValueError: shapes (2,2) and (3,2) not aligned: 2 (dim 1) != 3 (dim 0)
    In [21]:
    # 你反过来就符合A的列数=D的行数了
    D.dot(A)
    
    Out[21]:
    array([[ 3,  4],
           [11, 16],
           [19, 28]])
     

    2.2.4.幂乘、幂运算

    幂乘比较简单,就是每个元素开平方,不一定是方阵

    必须是方阵才能进行幂运算,比如A²=A×A(矩阵相乘前提:第一个矩阵A的行=第二个矩阵A的列==>方阵

    In [22]:
    print(A)
    print("-"*5)
    print(C)
    
     
    [[1 2]
     [3 4]]
    -----
    [[0 1 2]
     [3 4 5]]
    
    In [23]:
    # 幂乘(每个元素开平方) 
    np.power(A,2) # 使用 A**2也一样
    
    Out[23]:
    array([[ 1,  4],
           [ 9, 16]])
    In [24]:
    # 幂乘(不一定是方阵) 
    np.power(C,2)
    
    Out[24]:
    array([[ 0,  1,  4],
           [ 9, 16, 25]])
    In [25]:
    ################ 方阵幂运算 ################
    
    In [26]:
    # A*A*A
    np.linalg.matrix_power(A,3)
    
    Out[26]:
    array([[ 37,  54],
           [ 81, 118]])
    In [27]:
    # 不是方阵就over
    np.linalg.matrix_power(C,3)
    
     
    ---------------------------------------------------------------------------
    ValueError                                Traceback (most recent call last)
    <ipython-input-27-73f04ef7b54c> in <module>()
          1 # 不是方阵就over
    ----> 2np.linalg.matrix_power(C,3)
    
    ~/anaconda3/lib/python3.6/site-packages/numpy/matrixlib/defmatrix.py in matrix_power(M, n)
        137     M = asanyarray(M)
        138     if M.ndim != 2 or M.shape[0] != M.shape[1]:
    --> 139raise ValueError("input must be a square array")
        140     if not issubdtype(type(n), N.integer):
        141         raise TypeError("exponent must be an integer")
    
    ValueError: input must be a square array
     

    来个小结 + 扩展

    矩阵的加法运算满足交换律:A + B = B + A

    矩阵的乘法满足结合律和对矩阵加法的分配律:

    结合律:(AB)C = A(BC)

    左分配律:(A + B)C = AC + BC

    右分配律:C(A + B) = CA + CB

    矩阵的乘法与数乘运算之间也满足类似结合律的规律;与转置之间则满足倒置的

    分配律:c(A + B) = cA + cB

    结合律:c(AB) = (cA)B = A(cB)

    矩阵乘法不满足交换律 一般来说,矩阵A及B的乘积AB存在,但BA不一定存在,即使存在,大多数时候AB ≠ BA


    2.3.特殊矩阵

    2.3.1.零矩阵

    零矩阵就是所有的元素都是0

    $ egin{bmatrix} 0&0&0 \ 0&0&0 \ 0&0&0 end{bmatrix} $

    同样的:全1矩阵就是所有元素都是1

    $ egin{bmatrix} 1&1&1 \ 1&1&1 \ 1&1&1 end{bmatrix} $

    In [1]:
    import numpy as np
    
    In [2]:
    # 一维
    # 可以指定类型 np.zeros(5,dtype=int)
    np.zeros(5) # 完整写法:np.zeros((5,))
    
    Out[2]:
    array([0., 0., 0., 0., 0.])
    In [3]:
    # 二维
    np.zeros((2,5))# 建议用元组,官方文档都是元组
    
    Out[3]:
    array([[0., 0., 0., 0., 0.],
           [0., 0., 0., 0., 0.]])
    In [4]:
    # 三维 ==> 可以这么理解,2个2*5(2行5列)的矩阵
    np.zeros((2,2,5))
    
    Out[4]:
    array([[[0., 0., 0., 0., 0.],
            [0., 0., 0., 0., 0.]],
    
           [[0., 0., 0., 0., 0.],
            [0., 0., 0., 0., 0.]]])
    In [5]:
    ################ 全1矩阵 ################
    
    In [6]:
    # `np.ones(tuple)` 用法和`np.zeros(tuple)`差不多
    # 可以指定类型 np.ones(5,dtype=int)
    # 一维
    np.ones(5) # 完整写法 np.ones((5,))
    
    Out[6]:
    array([1., 1., 1., 1., 1.])
    In [7]:
    # 二维,传一个shape元组
    np.ones((2,5))
    
    Out[7]:
    array([[1., 1., 1., 1., 1.],
           [1., 1., 1., 1., 1.]])
    In [8]:
    # 三维 可以理解为两个二维数组
    np.ones((2,2,5))
    
    Out[8]:
    array([[[1., 1., 1., 1., 1.],
            [1., 1., 1., 1., 1.]],
    
           [[1., 1., 1., 1., 1.],
            [1., 1., 1., 1., 1.]]])
    In [9]:
    ################ 指定值矩阵 ################
    
    In [10]:
    # 创建指定值的矩阵:
    np.full((3,5),222)
    
    Out[10]:
    array([[222, 222, 222, 222, 222],
           [222, 222, 222, 222, 222],
           [222, 222, 222, 222, 222]])
    In [11]:
    # 创建指定值的矩阵,浮点类型
    np.full((3,5),222.0)
    
    Out[11]:
    array([[222., 222., 222., 222., 222.],
           [222., 222., 222., 222., 222.],
           [222., 222., 222., 222., 222.]])
     

    2.3.3.转置矩阵

    转置矩阵 :将矩阵的行列互换得到的新矩阵(行列式不变)

    m行×n列的矩阵行和列交换后就变成了n行×m列的矩阵,eg:3行×2列 ==> 2行×3列

    $egin{bmatrix}1&2 \3&4 \5&6end{bmatrix}^T ==> egin{bmatrix}1&3&5 \2&4&6end{bmatrix}$

    矩阵的转置满足分配律:

    $(A + B)^T = A^T + B^T$

    $(AB)^T = B^TA^T$

    再次提醒:两个矩阵的乘法仅当第一个矩阵A的列数(column)和另一个矩阵B的行数(row)相等才可以进行计算

    In [12]:
    A = np.arange(6).reshape((2,3))
    
    print(A)
    
     
    [[0 1 2]
     [3 4 5]]
    
    In [13]:
    # 转置矩阵(行列互换)
    A.T
    
    Out[13]:
    array([[0, 3],
           [1, 4],
           [2, 5]])
    In [14]:
    B = np.random.randint(10,size=(2,3))
    
    print(B)
    
     
    [[4 4 7]
     [5 3 9]]
    
    In [15]:
    ################ 验证系列 ################
    
    In [16]:
    # 验证一下(A+B)^T=A^T+B^T
    print(A.T + B.T)
    print("-"*5)
    print((A+B).T)
    
     
    [[ 4  8]
     [ 5  7]
     [ 9 14]]
    -----
    [[ 4  8]
     [ 5  7]
     [ 9 14]]
    
    In [17]:
    # 验证一下(A+B)^T=A^T+B^T
    # 其实也再一次验证了,Numpy运算符默认是对每一个元素的操作
    (A+B).T == A.T + B.T
    
    Out[17]:
    array([[ True,  True],
           [ True,  True],
           [ True,  True]])
    In [18]:
    ################ 验证系列 ################
    
    In [19]:
    # 把A变成3*2的矩阵,不够元素用0补
    # reshape:有返回值,不对原始多维数组进行修改
    # resize:无返回值,会对原始多维数组进行修改
    A.resize(3,2)
    
    print(A)
    print(B)
    
     
    [[0 1]
     [2 3]
     [4 5]]
    [[4 4 7]
     [5 3 9]]
    
    In [20]:
    # 验证(AB)^T=B^T×A^T
    print((A.dot(B)).T)
    print("-"*5)
    print((B.T).dot(A.T))
    
     
    [[ 5 23 41]
     [ 3 17 31]
     [ 9 41 73]]
    -----
    [[ 5 23 41]
     [ 3 17 31]
     [ 9 41 73]]
    
     

    2.3.3.上三角矩阵和下三角矩阵

    上三角矩阵 :主对角线以下都是零的方阵

    $egin{bmatrix} 2&9&4&7 \ 0&7&3&3 \ 0&0&6&1 \ 0&0&0&1 end{bmatrix}$

    下三角矩阵 :主对角线以上都是零的方阵

    $egin{bmatrix} 2&0&0&0 \ 3&7&0&0 \ 5&6&7&0 \ 1&2&3&4 end{bmatrix}$

    性质(行列式后面会说)

    1. 上(下)三角矩阵的行列式为对角线元素相乘
    2. 上(下)三角矩阵乘以系数后也是上(下)三角矩阵
    3. 上(下)三角矩阵间的加减法和乘法运算的结果仍是上(下)三角矩阵
    4. 上(下)三角矩阵的逆矩阵也仍然是上(下)三角矩阵
    In [21]:
    # 创建一个5行4列矩阵
    A = np.random.randint(10,size=(4,4))
    
    print(A)
    
     
    [[3 5 2 3]
     [7 2 9 6]
     [5 1 7 6]
     [1 2 8 4]]
    
    In [22]:
    # 上三角
    np.triu(A)
    
    Out[22]:
    array([[3, 5, 2, 3],
           [0, 2, 9, 6],
           [0, 0, 7, 6],
           [0, 0, 0, 4]])
    In [23]:
    # 下三角
    np.tril(A)
    
    Out[23]:
    array([[3, 0, 0, 0],
           [7, 2, 0, 0],
           [5, 1, 7, 0],
           [1, 2, 8, 4]])
    In [24]:
    # 验证一下最后一个性质
    # 三角矩阵的逆矩阵也仍然是三角矩阵
    print(np.triu(A).T)
    print('-'*5)
    print(np.tril(A).T)
    
     
    [[3 0 0 0]
     [5 2 0 0]
     [2 9 7 0]
     [3 6 6 4]]
    -----
    [[3 7 5 1]
     [0 2 1 2]
     [0 0 7 8]
     [0 0 0 4]]
    
     

    2.3.4.对角矩阵

    对角矩阵 :主对角线之外的元素皆为0的方阵 (单位矩阵属于对角矩阵中的一种)

    $egin{bmatrix}0&0&0 \0&0&0 \0&0&0end{bmatrix} egin{bmatrix}1&0&0 \0&1&0 \0&0&1end{bmatrix} egin{bmatrix}2&0&0 \0&2&0 \0&0&2end{bmatrix} egin{bmatrix}3&0&0 \0&9&0 \0&0&6end{bmatrix}$

    扩充:对角矩阵的运算包括和、差运算、数乘运算、同阶对角阵的乘积运算,且结果仍为对角阵

    而且有意思的是:对角矩阵的矩阵幂运算等于其对应元素的幂运算

    $egin{bmatrix}3&0&0 \0&9&0 \0&0&6end{bmatrix}^n = egin{bmatrix}3^n&0&0 \0&9^n&0 \0&0&6^nend{bmatrix}$

    In [25]:
    # 简单创建
    np.diag([3,9,6])
    
    Out[25]:
    array([[3, 0, 0],
           [0, 9, 0],
           [0, 0, 6]])
    In [26]:
    np.diag([2,2,2])
    
    Out[26]:
    array([[2, 0, 0],
           [0, 2, 0],
           [0, 0, 2]])
    In [27]:
    ################ 验证系列 ################
    
    In [28]:
    # np.diag?
    print(A)
    
    # 获取对角元素,然后再生成对角矩阵
    B = np.diag(A.diagonal()) #或者 np.diag(np.diag(A))
    
    print(B)
    
     
    [[3 5 2 3]
     [7 2 9 6]
     [5 1 7 6]
     [1 2 8 4]]
    [[3 0 0 0]
     [0 2 0 0]
     [0 0 7 0]
     [0 0 0 4]]
    
    In [29]:
    B.dot(B).dot(B)
    
    Out[29]:
    array([[ 27,   0,   0,   0],
           [  0,   8,   0,   0],
           [  0,   0, 343,   0],
           [  0,   0,   0,  64]])
    In [30]:
    # 对角矩阵的矩阵幂运算等于其对应元素的幂运算
    B**3
    
    Out[30]:
    array([[ 27,   0,   0,   0],
           [  0,   8,   0,   0],
           [  0,   0, 343,   0],
           [  0,   0,   0,  64]])
     

    2.3.5.单位矩阵

    单位矩阵 :单位矩阵是个方阵(行列相等),从左上角到右下角的对角线(称为主对角线)上的元素均为1。其他全都为0,eg:

    $ egin{bmatrix} 1&0&0 \ 0&1&0 \ 0&0&1 end{bmatrix} $

    任何矩阵 x 单位矩阵 都等于其本身 (反过来也一样(这个和1×a=a×1一个道理))

    In [31]:
    # 定义一个2行的单位矩阵(列默认和行一致)
    # np.eye(rows,columns=rows)
    np.eye(2)
    
    Out[31]:
    array([[1., 0.],
           [0., 1.]])
    In [32]:
    ################ 验证扩展 ################
    
    In [33]:
    # 可以指定类型
    B = np.eye(4,dtype=int)
    
    print(B)
    
     
    [[1 0 0 0]
     [0 1 0 0]
     [0 0 1 0]
     [0 0 0 1]]
    
    In [34]:
    print(A)
    
     
    [[3 5 2 3]
     [7 2 9 6]
     [5 1 7 6]
     [1 2 8 4]]
    
    In [35]:
    # 任何矩阵 x 单位矩阵 都等于其本身
    A.dot(B)
    
    Out[35]:
    array([[3, 5, 2, 3],
           [7, 2, 9, 6],
           [5, 1, 7, 6],
           [1, 2, 8, 4]])
    In [36]:
    # 反过来也一样(这个和1*a=a*1一个道理)
    B.dot(A)
    
    Out[36]:
    array([[3, 5, 2, 3],
           [7, 2, 9, 6],
           [5, 1, 7, 6],
           [1, 2, 8, 4]])
     

    2.3.6.对称矩阵

    对称矩阵 :元素以主对角线为对称轴对应相等的方阵

    对称矩阵的转置是它本身:$A^T=A$

    In [37]:
    A = np.random.randint(10,size=(4,4))
    
    print(A)
    
     
    [[0 1 6 9]
     [1 2 4 7]
     [4 8 7 9]
     [3 6 8 0]]
    
    In [38]:
    B = np.triu(A)
    B += B.T - np.diag(A.diagonal())
    print(B)
    
     
    [[0 1 6 9]
     [1 2 4 7]
     [6 4 7 9]
     [9 7 9 0]]
    
    In [39]:
    # 验证一下
    B.T == B
    
    Out[39]:
    array([[ True,  True,  True,  True],
           [ True,  True,  True,  True],
           [ True,  True,  True,  True],
           [ True,  True,  True,  True]])
    In [40]:
    ################ 分步解释 ################
    
    In [41]:
    # 创建上三角矩阵
    B = np.triu(A)
    
    print(B)
    
     
    [[0 1 6 9]
     [0 2 4 7]
     [0 0 7 9]
     [0 0 0 0]]
    
    In [42]:
    # 上三角+它的逆矩阵(发现距离对角矩阵只是多加一次对角线上的元素)
    B += B.T
    
    print(B)
    
     
    [[ 0  1  6  9]
     [ 1  4  4  7]
     [ 6  4 14  9]
     [ 9  7  9  0]]
    
    In [43]:
    # 所以减去对角线上的元素,得到对角矩阵
    B - np.diag(A.diagonal())
    
    Out[43]:
    array([[0, 1, 6, 9],
           [1, 2, 4, 7],
           [6, 4, 7, 9],
           [9, 7, 9, 0]])
     

    2.4.逆矩阵

    逆矩阵 :设A是数域上的一个n阶方阵,若在相同数域上存在另一个n阶矩阵B,使得:AB=BA=E 则我们称B是A的逆矩阵(表示为$A^{-1}$),而A则被称为可逆矩阵

    通俗话讲就是:原矩阵×逆矩阵=逆矩阵×原矩阵=单位矩阵

    2.4.1.消元法

    可能一看到逆矩阵,大家就想到代数余子式 ,不过逆天要说的是,代数余子式就和我们程序员面试题一样,有些题目就是又繁琐实际运用又没多大意义的题目一样,很多时候面试官都不看面试题一眼,同样的那些出题老师自己解题一般都不会使用。我这边介绍一下方便简单的方法“消元法

    比如求$egin{bmatrix}3&2 \1&2end{bmatrix}^{-1}$,就可以表示为:

    $egin{bmatrix}3&2 \1&2end{bmatrix}egin{bmatrix}x_{11}&x_{12} \x_{21}&x_{22}end{bmatrix}=egin{bmatrix}1&0 \0&1end{bmatrix}$

    转换成方程组:

    $egin{cases} egin{bmatrix}3&2 \1&2end{bmatrix}egin{bmatrix}x_{11} \x_{21}end{bmatrix}=egin{bmatrix}1 \0end{bmatrix}\ egin{bmatrix}3&2 \1&2end{bmatrix}egin{bmatrix}x_{12} \x_{22}end{bmatrix}=egin{bmatrix}0 \1end{bmatrix} end{cases} ==> 求方程组egin{cases}3x_{11}+2x_{21}=1\1x_{11}+2x_{21}=0end{cases}和egin{cases}3x_{12}+2x_{22}=0\1x_{12}+2x_{22}=1end{cases}的解$

    这样很轻松就能解出逆矩阵了

    $egin{cases}x_{11}=frac{1}{2}\x_{21}=-frac{1}{4} end{cases}\egin{cases}x_{12}=-frac{1}{2}\x_{22}=frac{3}{4} end{cases}\ ==> egin{bmatrix}frac{1}{2}&-frac{1}{2} \-frac{1}{4}&frac{3}{4} end{bmatrix}$

    In [44]:
    A = np.array([[3,2],[1,2]])
    
    print(A)
    
     
    [[3 2]
     [1 2]]
    
    In [45]:
    # 求A的逆矩阵
    np.linalg.inv(A)
    
    Out[45]:
    array([[ 0.5 , -0.5 ],
           [-0.25,  0.75]])
     

    2.4.2.二阶方阵公式

    如果只是2阶方阵,有更简单的公式(只能2阶使用,而消元法不受限制)矩阵是否可逆就看分母是否为0

    $large{egin{bmatrix}a_{11}&a_{12} \a_{21}&a_{22}end{bmatrix}=frac{1}{a_{11}a_{22}-a_{12}a_{21}}egin{bmatrix}a_{22}&-a_{12} \-a_{21}&a_{11}end{bmatrix}}$

    比如求$egin{bmatrix}3&2 \1&2end{bmatrix}^{-1}$:

    $frac{1}{3×2-2×1}egin{bmatrix}2&-2 \-1&3end{bmatrix}=egin{bmatrix}frac{1}{2}&-frac{1}{2} \-frac{1}{4}&frac{3}{4} end{bmatrix}$

    扩展系列:伪逆矩阵

    非方阵可以求 伪逆矩阵 AXA=A,XAX=X

    判断矩阵是否可逆:

    $$detegin{bmatrix}a_{11}&a_{12} \a_{21}&a_{22}end{bmatrix}=a_{11}a_{12}-a_{12}a_{21}\detegin{bmatrix}a_{11}&a_{12}&a_{13} \a_{21}&a_{22}&a_{23}\a_{31}&a_{32}&a_{33}end{bmatrix}=a_{11}a_{22}a_{33}+a_{12}a_{23}a_{31}+a_{13}a_{21}a_{32}-a_{13}a_{22}a_{31}-a_{12}a_{21}a_{33}-a_{11}a_{23}a_{32}$$

    方法很多(比如还可以通过余子式),公式其实有规律,你可以先摸索下(给个提示):

    正负
    a11a22 +
    a12a21 -
    正负
    a11a22a33 +
    a11a23a32 -
    a12a21a33 -
    a12a23a31 +
    a13a21a32 +
    a13a22a31 -

    程序比较简单:np.linalg.det(A)

    In [46]:
    A = np.array([[7, 3, 6],[5, 3, 1]])
    
    print(A)
    
     
    [[7 3 6]
     [5 3 1]]
    
    In [47]:
    # 不等于0就是可逆
    np.linalg.det(A)
    
     
    ---------------------------------------------------------------------------
    LinAlgError                               Traceback (most recent call last)
    <ipython-input-47-2ce8e7bdf499> in <module>()
          1 # 不等于0就是可逆
    ----> 2np.linalg.det(A)
    
    ~/anaconda3/lib/python3.6/site-packages/numpy/linalg/linalg.py in det(a)
       1869     a = asarray(a)
       1870     _assertRankAtLeast2(a)
    -> 1871_assertNdSquareness(a)
       1872     t, result_t = _commonType(a)
       1873     signature = 'D->D' if isComplexType(t) else 'd->d'
    
    ~/anaconda3/lib/python3.6/site-packages/numpy/linalg/linalg.py in _assertNdSquareness(*arrays)
        209     for a in arrays:
        210         if max(a.shape[-2:]) != min(a.shape[-2:]):
    --> 211raise LinAlgError('Last 2 dimensions of the array must be square')
        212 
        213 def _assertFinite(*arrays):
    
    LinAlgError: Last 2 dimensions of the array must be square
    In [48]:
    # 必须是方阵的验证
    np.linalg.inv(A)
    
     
    ---------------------------------------------------------------------------
    LinAlgError                               Traceback (most recent call last)
    <ipython-input-48-0af3c81a492f> in <module>()
          1 # 必须是方阵的验证
    ----> 2np.linalg.inv(A)
    
    ~/anaconda3/lib/python3.6/site-packages/numpy/linalg/linalg.py in inv(a)
        521     a, wrap = _makearray(a)
        522     _assertRankAtLeast2(a)
    --> 523_assertNdSquareness(a)
        524     t, result_t = _commonType(a)
        525 
    
    ~/anaconda3/lib/python3.6/site-packages/numpy/linalg/linalg.py in _assertNdSquareness(*arrays)
        209     for a in arrays:
        210         if max(a.shape[-2:]) != min(a.shape[-2:]):
    --> 211raise LinAlgError('Last 2 dimensions of the array must be square')
        212 
        213 def _assertFinite(*arrays):
    
    LinAlgError: Last 2 dimensions of the array must be square
    In [49]:
    # 有时候还是需要求逆矩阵
    # 那就可以求它的伪逆矩阵
    X = np.linalg.pinv(A)
    
    print(X)
    
     
    [[-0.00632911  0.15189873]
     [-0.05696203  0.16708861]
     [ 0.20253165 -0.26075949]]
    
    In [50]:
    # A*X*A=A
    A.dot(X).dot(A)
    
    Out[50]:
    array([[7., 3., 6.],
           [5., 3., 1.]])
    In [51]:
    # X*A*X=X
    X.dot(A).dot(X)
    
    Out[51]:
    array([[-0.00632911,  0.15189873],
           [-0.05696203,  0.16708861],
           [ 0.20253165, -0.26075949]])
    In [52]:
    ################ 简单说下mat ################
    
    In [53]:
    # 创建一个矩阵
    A = np.mat([[3,2],[1,2]])
    
    print(A)
    type(A)
    
     
    [[3 2]
     [1 2]]
    
    Out[53]:
    numpy.matrixlib.defmatrix.matrix
    In [54]:
    # 求它的逆矩阵
    A.I
    
    Out[54]:
    matrix([[ 0.5 , -0.5 ],
            [-0.25,  0.75]])
    In [55]:
    # A^T
    A.T
    
    Out[55]:
    matrix([[3, 1],
            [2, 2]])
    In [56]:
    # *默认就是矩阵乘法
    A * A
    
    Out[56]:
    matrix([[11, 10],
            [ 5,  6]])
    In [57]:
    # 更多自己查看下帮助文档把,用法和array基本上一样,
    # 我这边只是简单提一下,怕你们不去看(所有和矩阵相关的东西,里面都有封装,很方便)
    np.mat?
    
  • 相关阅读:
    Java课堂测试——一维数组
    05构建之法阅读笔记之二
    第八周个人总结
    团队项目第一篇——NABCD
    第七周学习进度报告
    地铁合作的第二周
    04构建之法阅读笔记之一
    第六周学习进度报告
    03人月神话阅读笔记之三
    地铁合作的第一周
  • 原文地址:https://www.cnblogs.com/dotnetcrazy/p/9314518.html
Copyright © 2020-2023  润新知