zoukankan      html  css  js  c++  java
  • 码农眼中的数学之~矩阵专栏(附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?
    
  • 相关阅读:
    JID 2.0 RC4 发布,高性能的 Java 序列化库
    FBReaderJ 1.6.3 发布,Android 电子书阅读器
    Arquillian 1.0.3.Final 发布,单元测试框架
    JavaScript 的宏扩展 Sweet.js
    Hypertable 0.9.6.5 发布,分布式数据库
    JRuby 1.7.0 发布,默认使用 Ruby 1.9 模式
    httppp 1.4.0 发布,HTTP响应时间监控
    Redis 2.6.0 正式版发布,高性能K/V服务器
    OfficeFloor 2.5.0 发布,IoC 框架
    XWiki 4.3 首个里程碑发布
  • 原文地址:https://www.cnblogs.com/dotnetcrazy/p/9314518.html
Copyright © 2011-2022 走看看