2.矩陣專欄¶ 吐槽一下:矩陣本身不難,但是矩陣的寫作太蛋疼了 (⊙﹏⊙)汗 還好有Numpy,不然真的崩潰了... LaTex有沒有一個集成了很多常用公式以及推導或者含題庫的線上編輯器? 代碼褲子:https://github.com/lotapp/BaseCode 線上編程系:https://m ...
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 npIn [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 + BOut[3]:
array([[ 1, 3, 5], [ 7, 9, 11], [13, 15, 17]])In [4]:
# 和A+B相等 B + AOut[4]:
array([[ 1, 3, 5], [ 7, 9, 11], [13, 15, 17]])In [5]:
# 減法 A - BOut[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 * AOut[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 / 2Out[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×矩陣BOut[15]:
array([[ 8, 5], [20, 13]])
程式驗證了我們上面的運算結果,還得註意一下:
A×B
和B×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×矩陣AOut[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的列==>方陣
)
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 npIn [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.TOut[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.TOut[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}$
性質(行列式後面會說)
- 上(下)三角矩陣的行列式為對角線元素相乘
- 上(下)三角矩陣乘以繫數後也是上(下)三角矩陣
- 上(下)三角矩陣間的加減法和乘法運算的結果仍是上(下)三角矩陣
- 上(下)三角矩陣的逆矩陣也仍然是上(下)三角矩陣
# 創建一個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