码农眼中的数学之~矩阵专栏(附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

2.1.矩阵的定义¶

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

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

$\begin{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:

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

这个就是3阶方阵



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

$\begin{cases}x_1+x_2=-1\\2x_1-x_2=4\\3x_1+5x_2=-7\\\end{cases}$ ==> $\begin{bmatrix}1&1\\2&-1\\3&5\end{bmatrix}\begin{bmatrix}x_1\\x_2\end{bmatrix}=\begin{bmatrix}-1\\4\\-7\end{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在线编辑器可以推荐的)

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

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

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

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

举个简单的例子:A×B

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

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

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

你这样想就记得了:$\begin{bmatrix} 1&2 \\3&4 \end{bmatrix}\begin{bmatrix} x_1 \end{bmatrix} 还原成方程组就是这样\begin{cases}1*x_1+2*?\\3*x_1+4*?\end{cases}\\这是什么鬼?至少得这样吧:\begin{bmatrix} 1&2 \\3&4 \end{bmatrix}\begin{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

$\begin{bmatrix} 4&3 \\2&1 \end{bmatrix}\begin{bmatrix} 1&2 \\3&4 \end{bmatrix}=\begin{bmatrix} 4*1+3*3&4*2+3*4 \\2*1+1*3&2*2+1*4 \end{bmatrix}=\begin{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

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

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

$ \begin{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列

$\begin{bmatrix}1&2 \\3&4 \\5&6\end{bmatrix}^T ==> \begin{bmatrix}1&3&5 \\2&4&6\end{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.上三角矩阵和下三角矩阵¶

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

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

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

$\begin{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的方阵 (单位矩阵属于对角矩阵中的一种)

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

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

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

$\begin{bmatrix}3&0&0 \\0&9&0 \\0&0&6\end{bmatrix}^n = \begin{bmatrix}3^n&0&0 \\0&9^n&0 \\0&0&6^n\end{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:

$ \begin{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.消元法¶

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

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

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

转换成方程组:

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

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

$\begin{cases}x_{11}=\frac{1}{2}\\x_{21}=-\frac{1}{4} \end{cases}\\\begin{cases}x_{12}=-\frac{1}{2}\\x_{22}=\frac{3}{4} \end{cases}\\ ==> \begin{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{\begin{bmatrix}a_{11}&a_{12} \\a_{21}&a_{22}\end{bmatrix}=\frac{1}{a_{11}a_{22}-a_{12}a_{21}}\begin{bmatrix}a_{22}&-a_{12} \\-a_{21}&a_{11}\end{bmatrix}}$

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

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

扩展系列:伪逆矩阵¶

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

判断矩阵是否可逆:

$$det\begin{bmatrix}a_{11}&a_{12} \\a_{21}&a_{22}\end{bmatrix}=a_{11}a_{12}-a_{12}a_{21}\\det\begin{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?

原文地址:https://www.cnblogs.com/dotnetcrazy/p/9314518.html

时间: 2024-10-24 15:06:05

码农眼中的数学之~矩阵专栏(附Numpy讲解)的相关文章

老码农眼中的CRM 图解

概述 喔家ArchiSelf CRM 是企业"以客户为中心"价值观的核心体现之一, 各种2B的应用都无可避免,而企业应用具有一定的复杂性,理解CRM系统也不是轻而易举的事情.在老码农的眼中,CRM 系统可能是这样的: 业务组成 业务单元的组成是第一位, 业务单元是企业的实在需求,也是采用CRM系统的主要因素. 如上所示,业务单元大约可以概括成9个方面. 客户管理 客户是第一位的, 先贤德鲁克的话不用赘述.客户管理包括什么呢? 人在业务中的重要性不言而喻.客户联系人管理包括建立联系人概况

【知乎】怎么成为一个优秀的程序员,而不是一个优秀的码农?

怎么成为一个优秀的程序员,而不是一个优秀的码农? 9 条评论 分享 默认排序按时间排序 98 个回答 3844赞同反对,不会显示你的姓名 萧井陌 微信公众号:炼瓜研究所 技术社区 - 3844 人赞同 优秀的程序员会告诉你打根基的重要性,会劝你在厚积薄发前要隐忍. 优秀的码农会告诉你学啥底层.啥啥啥一拖就好了,学了python还要啥自行车啊,数据结构排序函数二分搜索这不都内置了吗?工作中永远用不到,学算法有啥用啊?成为高手有很多种方法汇编是个屁啊? +++基础的分割线+++ 列举几个我认为比较重

为什么你只是个码农

实际上IT行业在中国并不是特别差的行业,而程序员的工资也并不低,但为什么中国的程序员总被称作码农或者说是苦逼的程序员? 为什么他们常常自嘲为码农,搬砖工? 来料加工,缺乏创造力 我们生活在自己那个小小的加拉帕戈斯泡沫中(与全球化隔绝),对世界上其他的事情置若罔闻.撇开科学软件不谈(仿真系统.开发工具等等),我不认为我们对学术充满热情. 在大学初学计算机的时候,我们常常研究算法.数据结构.计算机系统等. 但是在实际工作中,公司所要求的与技术人员的想法相差很远(特别是一些中小型的公司),业务线要求我

写给立志做码农的大学生(蘑菇街你都挂了,你还要面腾讯? 我去,我一定要去)

先简单介绍一下我自己,我是一所普通大学的本科生,大学录取时的专业是非计算机系的,在大一下学期意识到自己喜欢敲代码以后,就提交了转专业申请.大二起开始在计算机系学习.大三时(2015年4月)拿到了腾讯暑期实习的offer,暑期实习的过程中获得留用offer,大四没跑秋招,几乎就在学校浪荡了一年. 我不是大牛,不是来传播鸡汤或成功学的,只是最近有感于学弟学妹们在学习以及规划方面严重不足,觉得这是一个共性问题,遂捉起纸笔,写点东西. 1. 确定方向 1.1 选择比努力更重要 关于方向的选择其实越早确定

码农-如果当初学习编程时能有人给我这些忠告该多好

在你学习编程之前思考一下你的目标 要知道编程大多时候就是在创造,当你有最终目标感时道路会更加的清晰.如果你的目标是"学习编程"而不是更具体的学习哪种程序及如何让你的生活更好,那么你可能会发现这不过是一次令人沮丧的实践. 我有点惭愧地承认我学习计算机科学的部分动机是为了证明我聪明,及我想干"聪明人"的工作.我也喜欢思考数学和理论(<哥德尔.艾舍尔.巴赫:集异璧之大成 >这本书在我易受影响的年纪进入了我的脑海),编程是一个不错的选择.当然这并不足以使我坚持这

写给立志做码农的大学生

先简单介绍一下我自己,我是一所普通大学的本科生,大学录取时的专业是非计算机系的,在大一下学期意识到自己喜欢敲代码以后,就提交了转专业申请.大二起开始在计算机系学习.大三时(2015年4月)拿到了腾讯暑期实习的offer,暑期实习的过程中获得留用offer,大四没跑秋招,几乎就在学校浪荡了一年. 我不是大牛,不是来传播鸡汤或成功学的,只是最近有感于学弟学妹们在学习以及规划方面严重不足,觉得这是一个共性问题,遂捉起纸笔,写点东西. 1. 确定方向 1.1 选择比努力更重要 关于方向的选择其实越早确定

老码农教你学英语

转自:http://blog.jobbole.com/45296/ 对于咱们这些高端大气.时刻需要和国际接轨的码农,英语的重要性自然是毋庸置疑的.尤其是那些胸怀大志的潜在大牛们,想在码农行业闯出一片天地,秒杀身边的小弟们,熟练掌握英语更是实现其目标最关键的因素之一.否则,试想在你捧着某出版社刚刚翻译出来的<JSP 高效编程>苦苦学习JSP模板的时候,你旁边的小弟却是拿着原版的<AngularJS in Action>学习开发单页面应用,虽然你们都同样认真地学习了一个月,可做出来东西

我是如何从程序小白成为码农的

转眼大学生活就要结束了,想想还真有点舍不得.简单叙述一下我大学的编程生涯. 大学一年级,对我来说,可以说基本上没有接触到什么编程的技能,买了个笔记本也就是用来聊聊天看看电影什么的.至于C语言是什么,我去!还是睡觉打球吧.从大一就养成了翘课的习惯,导致整个大学基本上都没有上过几节课.罪过…幸运的是靠着考前的几天的抱佛脚居然没有挂科,还拿了几次奖学金,和学霸们埋头苦读比起来也算是值了. 记得大一下学期开设了C语言的课,也是大学期间唯一的一门专门教授编程语言的课,尼玛由于缺课太多,中途去听一堂完全是天

做工程师而不是做码农

时间很重要 很多人喜欢苦苦钻研一样东西,觉得知识一定要是自己思考出来的才算学会,这个精神很好,但确实最不经济的学习方法.这一点上,我吃过亏也受过益,所以现在越发体会深刻:我上学的时候,物理一直很好,属于那种下课玩玩也能考很好的类型,数学却差的出奇,我一直想不通为什么,直到后来看到一种叫NIH(Not Invented Here)中文即非我独创的心理疾病是,我才发现,MD,这是病,得治.学数学的时候,我喜欢跟公式较劲,跟定理较劲.不仅要会推导,还老是纠结于为什么别人能想出1+1=2,我为什么没有想