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:
$\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 (乘法不行)
import numpy as np
# 創建兩個集合
A = np.arange(1,10).reshape((3,3))
B = np.arange(9).reshape((3,3))
print(A)
print("-"*5)
print(B)
# 加法
A + B
# 和A+B相等
B + A
# 減法
A - B
################ 變化來了 ################
# 之前說過 ”只有行列都相同的矩陣才可以進行“ 來驗證一下
# 創建一個2行3列的矩陣
C = np.arange(6).reshape((2,3))
D = np.arange(6).reshape((3,2))
print(C)
print("-"*5)
print(D)
# 2行3列的矩陣 + 3行2列的矩陣
C + D # 不同形狀的矩陣不能進行加運算
C - D # 不同形狀的矩陣不能進行減運算
print(A)
# 比如2×A,A原本的每一個元素都擴大了兩倍
2 * A
print(A)
# 友情提醒:Numpy里面的運算基本上都是針對每一個元素
A / 2
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}$
# 通過代碼看一看
A = np.array([[1,2],[3,4]])
B = np.array([[4,3],[2,1]])
print(A)
print("-"*5)
print(B)
# 注意一下,Numpy里面的乘法默認是每個數對應相乘
# 如果是矩陣相乘可以使用dot()方法
# 或者你創建矩陣對象,這樣×默認就是矩陣乘法了
A.dot(B) # 矩陣A×矩陣B
程序驗證了我們上面的運算結果,還得注意一下:
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,然后就會了
print(A)
print("-"*5)
print(B)
B.dot(A) # 矩陣B×矩陣A
################ 變化來了 ################
# 來驗證一下”兩個矩陣的乘法僅當第一個矩陣A的列數(column)和另一個矩陣D的行數(row)相等才可以進行計算“
print(A)
print("-"*5)
print(D)
# A有2列 D有3行
A.dot(D) # 不能乘
# 你反過來就符合A的列數=D的行數了
D.dot(A)
print(A)
print("-"*5)
print(C)
# 冪乘(每個元素開平方)
np.power(A,2) # 使用 A**2也一樣
# 冪乘(不一定是方陣)
np.power(C,2)
################ 方陣冪運算 ################
# A*A*A
np.linalg.matrix_power(A,3)
# 不是方陣就over
np.linalg.matrix_power(C,3)
來個小結 + 擴展:
矩陣的加法運算滿足交換律: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} $
import numpy as np
# 一維
# 可以指定類型 np.zeros(5,dtype=int)
np.zeros(5) # 完整寫法:np.zeros((5,))
# 二維
np.zeros((2,5))# 建議用元組,官方文檔都是元組
# 三維 ==> 可以這么理解,2個2*5(2行5列)的矩陣
np.zeros((2,2,5))
################ 全1矩陣 ################
# `np.ones(tuple)` 用法和`np.zeros(tuple)`差不多
# 可以指定類型 np.ones(5,dtype=int)
# 一維
np.ones(5) # 完整寫法 np.ones((5,))
# 二維,傳一個shape元組
np.ones((2,5))
# 三維 可以理解為兩個二維數組
np.ones((2,2,5))
################ 指定值矩陣 ################
# 創建指定值的矩陣:
np.full((3,5),222)
# 創建指定值的矩陣,浮點類型
np.full((3,5),222.0)
A = np.arange(6).reshape((2,3))
print(A)
# 轉置矩陣(行列互換)
A.T
B = np.random.randint(10,size=(2,3))
print(B)
################ 驗證系列 ################
# 驗證一下(A+B)^T=A^T+B^T
print(A.T + B.T)
print("-"*5)
print((A+B).T)
# 驗證一下(A+B)^T=A^T+B^T
# 其實也再一次驗證了,Numpy運算符默認是對每一個元素的操作
(A+B).T == A.T + B.T
################ 驗證系列 ################
# 把A變成3*2的矩陣,不夠元素用0補
# reshape:有返回值,不對原始多維數組進行修改
# resize:無返回值,會對原始多維數組進行修改
A.resize(3,2)
print(A)
print(B)
# 驗證(AB)^T=B^T×A^T
print((A.dot(B)).T)
print("-"*5)
print((B.T).dot(A.T))
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)
# 上三角
np.triu(A)
# 下三角
np.tril(A)
# 驗證一下最后一個性質
# 三角矩陣的逆矩陣也仍然是三角矩陣
print(np.triu(A).T)
print('-'*5)
print(np.tril(A).T)
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}$
# 簡單創建
np.diag([3,9,6])
np.diag([2,2,2])
################ 驗證系列 ################
# np.diag?
print(A)
# 獲取對角元素,然后再生成對角矩陣
B = np.diag(A.diagonal()) #或者 np.diag(np.diag(A))
print(B)
B.dot(B).dot(B)
# 對角矩陣的矩陣冪運算等於其對應元素的冪運算
B**3
# 定義一個2行的單位矩陣(列默認和行一致)
# np.eye(rows,columns=rows)
np.eye(2)
################ 驗證擴展 ################
# 可以指定類型
B = np.eye(4,dtype=int)
print(B)
print(A)
# 任何矩陣 x 單位矩陣 都等於其本身
A.dot(B)
# 反過來也一樣(這個和1*a=a*1一個道理)
B.dot(A)
A = np.random.randint(10,size=(4,4))
print(A)
B = np.triu(A)
B += B.T - np.diag(A.diagonal())
print(B)
# 驗證一下
B.T == B
################ 分步解釋 ################
# 創建上三角矩陣
B = np.triu(A)
print(B)
# 上三角+它的逆矩陣(發現距離對角矩陣只是多加一次對角線上的元素)
B += B.T
print(B)
# 所以減去對角線上的元素,得到對角矩陣
B - np.diag(A.diagonal())
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}$
A = np.array([[3,2],[1,2]])
print(A)
# 求A的逆矩陣
np.linalg.inv(A)
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)
A = np.array([[7, 3, 6],[5, 3, 1]])
print(A)
# 不等於0就是可逆
np.linalg.det(A)
# 必須是方陣的驗證
np.linalg.inv(A)
# 有時候還是需要求逆矩陣
# 那就可以求它的偽逆矩陣
X = np.linalg.pinv(A)
print(X)
# A*X*A=A
A.dot(X).dot(A)
# X*A*X=X
X.dot(A).dot(X)
################ 簡單說下mat ################
# 創建一個矩陣
A = np.mat([[3,2],[1,2]])
print(A)
type(A)
# 求它的逆矩陣
A.I
# A^T
A.T
# *默認就是矩陣乘法
A * A
# 更多自己查看下幫助文檔把,用法和array基本上一樣,
# 我這邊只是簡單提一下,怕你們不去看(所有和矩陣相關的東西,里面都有封裝,很方便)
np.mat?