NumPy科学计算库学习_012_NumPy数组中的线性代数
一、点积np.dot(A,B)
1、数字与数字之间的点积
- 即数字A与数字B的乘积。
num_dot = np.dot(2,10)
print("【数与数的点积】\n",num_dot)
【数与数的点积】
20
2、数字与任意形状数组的点积
- 即该数字与数组每个元素相乘,只改变每个元素的值,数组形状不变。
arr1d_num_dot = np.dot(2,np.array([5,6,7]))
arr2d_num_dot = np.dot(2,np.array([[5,6,7],[5,6,7]]))
arr3d_num_dot = np.dot(2,np.array([[[5,6,7],[5,6,7]],[[5,6,7],[5,6,7]]]))
print("【数字与一维数组的点积】\n",arr1d_num_dot)
print("【数字与二维数组的点积】\n",arr2d_num_dot)
print("【数字与三维数组的点积】\n",arr3d_num_dot)
【数字与一维数组的点积】
[10 12 14]
【数字与二维数组的点积】
[[10 12 14]
[10 12 14]]
【数字与三维数组的点积】
[[[10 12 14]
[10 12 14]]
[[10 12 14]
[10 12 14]]]
3、一维数组之间的点积
- 返回的值就是向量的
内积
- 两个一维数组的列必须相同
arr1d_dot = np.dot(np.array([2,3,4]),np.array([5,6,7]))
print("【一维数组之间的点积】\n","2x5+3x6+4x7 =","10+18+28 =",arr1d_dot)
【一维数组之间的点积】
2x5+3x6+4x7 = 10+18+28 = 56
4、二维数组之间的点积
- 矩阵A
最后一维
= 矩阵B第一维
- 合法运算条件 => 矩阵A列数 = 矩阵B行数
- 结果满足形状 => (A的行数,B的列数)
\[{\begin{bmatrix}
\color{red}{4}&\color{red}{2}&\color{red}{3}\\
{1}&{3}&{1}\\
\end{bmatrix}_{(2,3)}}
{\cdot}
{\begin{bmatrix}
\color{red}{2}&{7}\\
\color{red}{-5}&{-7}\\
\color{red}{9}&{3}\\
\end{bmatrix}_{(3,2)}}
=
{\begin{bmatrix}
\color{red}{8-10+27=25}&\color{lightgrey}{?}\\
\color{lightgrey}{?}&\color{lightgrey}{?}\\
\end{bmatrix}_{(2,2)}}
\]
\[{\begin{bmatrix}
\color{red}{4}&\color{red}{2}&\color{red}{3}\\
{1}&{3}&{1}\\
\end{bmatrix}_{(2,3)}}
{\cdot}
{\begin{bmatrix}
{2}&\color{red}{7}\\
{-5}&\color{red}{-7}\\
{9}&\color{red}{3}\\
\end{bmatrix}_{(3,2)}}
=
{\begin{bmatrix}
\color{lightgrey}{?}&\color{red}{28-14+9=23}\\
\color{lightgrey}{?}&\color{lightgrey}{?}\\
\end{bmatrix}_{(2,2)}}
\]
\[{\begin{bmatrix}
{4}&{2}&{3}\\
\color{red}{1}&\color{red}{3}&\color{red}{1}\\
\end{bmatrix}_{(2,3)}}
{\cdot}
{\begin{bmatrix}
\color{red}{2}&{7}\\
\color{red}{-5}&{-7}\\
\color{red}{9}&{3}\\
\end{bmatrix}_{(3,2)}}
=
{\begin{bmatrix}
\color{lightgrey}{?}&\color{lightgrey}{?}\\
\color{red}{2-15+9=-4}&\color{lightgrey}{?}\\
\end{bmatrix}_{(2,2)}}
\]
\[{\begin{bmatrix}
{4}&{2}&{3}\\
\color{red}{1}&\color{red}{3}&\color{red}{1}\\
\end{bmatrix}_{(2,3)}}
{\cdot}
{\begin{bmatrix}
{2}&\color{red}{7}\\
{-5}&\color{red}{-7}\\
{9}&\color{red}{3}\\
\end{bmatrix}_{(3,2)}}
=
{\begin{bmatrix}
\color{lightgrey}{?}&\color{lightgrey}{?}\\
\color{lightgrey}{?}&\color{red}{7-21+3=-11}\\
\end{bmatrix}_{(2,2)}}
\]
\[\color{darkorange}{最终结果=>}
\color{darkorange}{\begin{bmatrix}
{25}&{23}\\
{-4}&{-11}\\
\end{bmatrix}_{({2},{2})}}
\]
5、多维数组之间的点积
- 矩阵A
最后一维
= 矩阵B倒数第二维
A = np.random.random((2,3,4,3))
B = np.random.random((5,2,2,2,3,1))
print("【矩阵A形状】\n",A.shape)
print("【矩阵B形状】\n",B.shape)
C = np.dot(A,B)
print("【矩阵C形状】\n",C.shape)
print("---------------------------------")
A = np.random.random((2,3,2))
B = np.random.random((4,2,2))
print("【矩阵A形状】\n",A.shape)
print("【矩阵B形状】\n",B.shape)
C = np.dot(A,B)
print("【矩阵C形状】\n",C.shape)
print("---------------------------------")
【矩阵A】
(2, 3, 4, 3)
【矩阵B】
(5, 2, 2, 2, 3, 1)
【矩阵C】
(2, 3, 4, 5, 2, 2, 2, 1)
---------------------------------
【矩阵A】
(2, 3, 2)
【矩阵B】
(4, 2, 2)
【矩阵C】
(2, 3, 4, 2)
---------------------------------
二、内积np.inner(A,B)
- 即数字A与数字B的乘积。
1、数字与数字之间的内积
num_inner = np.inner(2,3)
print("【数字与数字间的内积】\n",num_inner)
【数字与数字间的内积】
6
2、数字与任意形状数组的内积
- 即该数字与数组每个元素相乘,只改变每个元素的值,数组形状不变。
arr1d_num_inner = np.dot(2,np.array([5,6,7]))
arr2d_num_inner = np.dot(2,np.array([[5,6,7],[5,6,7]]))
arr3d_num_inner = np.dot(2,np.array([[[5,6,7],[5,6,7]],[[5,6,7],[5,6,7]]]))
print("【数字与一维数组的内积】\n",arr1d_num_inner)
print("【数字与二维数组的内积】\n",arr2d_num_inner)
print("【数字与三维数组的内积】\n",arr3d_num_inner)
【数字与一维数组的内积】
[10 12 14]
【数字与二维数组的内积】
[[10 12 14]
[10 12 14]]
【数字与三维数组的内积】
[[[10 12 14]
[10 12 14]]
[[10 12 14]
[10 12 14]]]
3、一维数组之间的内积
- 两个一维数组的列必须相同
arr1d_inner = np.inner(np.array([2,3,4]),np.array([5,6,7]))
print("【一维数组之间的内积】\n","2x5+3x6+4x7 =","10+18+28 =",arr1d_inner)
【一维数组之间的内积】
2x5+3x6+4x7 = 10+18+28 = 56
4、二维数组之间的内积
- A的
最后一维
= B的最后一维
\[{\begin{bmatrix}
\color{red}{1}&\color{red}{2}&\color{red}{3}\\
{1}&{2}&{3}\\
\end{bmatrix}_{(2,3)}}
{\cdot}
{\begin{bmatrix}
\color{red}{0}&\color{red}{1}&\color{red}{2}\\
{0}&{1}&{2}\\
{0}&{1}&{2}\\
\end{bmatrix}_{(3,3)}}
=
{\begin{bmatrix}
\color{red}{0+2+6=8}&\color{lightgrey}{?}&\color{lightgrey}{?}\\
\color{lightgrey}{?}&\color{lightgrey}{?}&\color{lightgrey}{?}\\
\end{bmatrix}_{(2,3)}}
\]
\[{\begin{bmatrix}
\color{red}{1}&\color{red}{2}&\color{red}{3}\\
{1}&{2}&{3}\\
\end{bmatrix}_{(2,3)}}
{\cdot}
{\begin{bmatrix}
{0}&{1}&{2}\\
\color{red}{0}&\color{red}{1}&\color{red}{2}\\
{0}&{1}&{2}\\
\end{bmatrix}_{(3,3)}}
=
{\begin{bmatrix}
\color{lightgrey}{?}&\color{red}{0+2+6=8}&\color{lightgrey}{?}\\
\color{lightgrey}{?}&\color{lightgrey}{?}&\color{lightgrey}{?}\\
\end{bmatrix}_{(2,3)}}
\]
\[{\begin{bmatrix}
\color{red}{1}&\color{red}{2}&\color{red}{3}\\
{1}&{2}&{3}\\
\end{bmatrix}_{(2,3)}}
{\cdot}
{\begin{bmatrix}
{0}&{1}&{2}\\
{0}&{1}&{2}\\
\color{red}{0}&\color{red}{1}&\color{red}{2}\\
\end{bmatrix}_{(3,3)}}
=
{\begin{bmatrix}
\color{lightgrey}{?}&\color{lightgrey}{?}&\color{red}{0+2+6=8}\\
\color{lightgrey}{?}&\color{lightgrey}{?}&\color{lightgrey}{?}\\
\end{bmatrix}_{(2,3)}}
\]
\[{\begin{bmatrix}
{1}&{2}&{3}\\
\color{red}{1}&\color{red}{2}&\color{red}{3}\\
\end{bmatrix}_{(2,3)}}
{\cdot}
{\begin{bmatrix}
\color{red}{0}&\color{red}{1}&\color{red}{2}\\
{0}&{1}&{2}\\
{0}&{1}&{2}\\
\end{bmatrix}_{(3,3)}}
=
{\begin{bmatrix}
\color{lightgrey}{?}&\color{lightgrey}{?}&\color{lightgrey}{?}\\
\color{red}{0+2+6=8}&\color{lightgrey}{?}&\color{lightgrey}{?}\\
\end{bmatrix}_{(2,3)}}
\]
\[{\begin{bmatrix}
{1}&{2}&{3}\\
\color{red}{1}&\color{red}{2}&\color{red}{3}\\
\end{bmatrix}_{(2,3)}}
{\cdot}
{\begin{bmatrix}
{0}&{1}&{2}\\
\color{red}{0}&\color{red}{1}&\color{red}{2}\\
{0}&{1}&{2}\\
\end{bmatrix}_{(3,3)}}
=
{\begin{bmatrix}
\color{lightgrey}{?}&\color{lightgrey}{?}&\color{lightgrey}{?}\\
\color{lightgrey}{?}&\color{red}{0+2+6=8}&\color{lightgrey}{?}\\
\end{bmatrix}_{(2,3)}}
\]
\[{\begin{bmatrix}
{1}&{2}&{3}\\
\color{red}{1}&\color{red}{2}&\color{red}{3}\\
\end{bmatrix}_{(2,3)}}
{\cdot}
{\begin{bmatrix}
{0}&{1}&{2}\\
{0}&{1}&{2}\\
\color{red}{0}&\color{red}{1}&\color{red}{2}\\
\end{bmatrix}_{(3,3)}}
=
{\begin{bmatrix}
\color{lightgrey}{?}&\color{lightgrey}{?}&\color{lightgrey}{?}\\
\color{lightgrey}{?}&\color{lightgrey}{?}&\color{red}{0+2+6=8}\\
\end{bmatrix}_{(2,3)}}
\]
\[\color{darkorange}{最终结果=>}
\color{darkorange}{\begin{bmatrix}
{8}&{8}&{8}\\
{8}&{8}&{8}\\
\end{bmatrix}_{({2},{2})}}
\]
5、多维数组之间的内积
- 矩阵A
最后一维
= 矩阵B最后一维
A = np.random.random((1,2,2,3))
B = np.random.random((3,2,3))
print("【矩阵A形状】\n",A.shape)
print("【矩阵B形状】\n",B.shape)
C = np.inner(A,B)
print("【矩阵C形状】\n",C.shape)
print("---------------------------------")
A = np.random.random((2,2))
B = np.random.random((1,2,2))
print("【矩阵A形状】\n",A.shape)
print("【矩阵B形状】\n",B.shape)
C = np.inner(A,B)
print("【矩阵C形状】\n",C.shape)
print("---------------------------------")
【矩阵A形状】
(1, 2, 2, 3)
【矩阵B形状】
(3, 2, 3)
【矩阵C形状】
(1, 2, 2, 3, 2)
---------------------------------
【矩阵A形状】
(2, 2)
【矩阵B形状】
(1, 2, 2)
【矩阵C形状】
(2, 1, 2)
---------------------------------
三、矩阵乘积运算A@B
1、含义
- Python中,符号@代表2个含义:
- 代表装饰器
- 代表
numpy.matmul(A,B)
- 显然这里的
A@B
代表NumPy数组之间的乘积运算。
2、注意
A
@B
等价于numpy.matmul(A,B)
- 只允许
矩阵之间
相乘
3、一维数组(向量)之间的运算
- 规则服从内积
np.inner(A,B)
- 列必须相同。
A = np.array([1,4])
B = np.array([2,2])
print("1 x 2 + 4 x 2 =",A@B)
1 x 2 + 4 x 2 = 10
4、二维数组之间的运算
- 规则服从点积
np.dot(A,B)
- 合法运算条件 => 矩阵A列数 = 矩阵B行数
- 结果满足形状 => (A的行数,B的列数)
A = np.random.random((3,2))
print(A.shape)
B = np.random.random((2,2))
print(B.shape)
C = A@B
print(C)
【A的形状】
(22, 40)
【B的形状】
(40, 19)
【A@B形状】
(22, 19)
【np.dot(A,B)形状】
(22, 19)
5、一维数组与多维数组的运算
- 假设:$$ A = [0,6] $$ $$ B = [[1,2],[3,4]] $$
- 这种情况很有意思,我们先看看api怎么描述的:
- 地址:https://numpy.org/doc/stable/reference/generated/numpy.matmul.html#numpy.matmul
- If the first argument is 1-D, it is promoted to a matrix by
prepending a 1
to its dimensions. After matrix multiplication theprepended 1 is removed
. - If the second argument is 1-D, it is promoted to a matrix by
appending a 1
to its dimensions. After matrix multiplication theappended 1 is removed
.
- 解释起来有两种情况
- 当第一个参数为1-D时,由于A的形状在numpy中表示为
(2,)
(非矩阵,是向量,表示2个元素),要在2前
加一个轴,这个轴的值为1。即A被升维成矩阵,形状是(1,2)
。此时,A与B执行点积
操作。当运算完毕后,A原本被添加的轴会被回收,即A回到形状(2,)
的向量模式。\[{\begin{bmatrix} \color{red}{0}&\color{red}{6}\\ \end{bmatrix}_{(1,2)}} {\begin{bmatrix} \color{red}{1}&{2}\\ \color{red}{3}&{4}\\ \end{bmatrix}_{(2,2)}} = {\begin{bmatrix} \color{red}{0*1+6*3=18}&\color{lightgrey}{?}\\ \end{bmatrix}_{(1,2)}} \]\[{\begin{bmatrix} \color{red}{0}&\color{red}{6}\\ \end{bmatrix}_{(1,2)}} {\begin{bmatrix} {1}&\color{red}{2}\\ {3}&\color{red}{4}\\ \end{bmatrix}_{(2,2)}} = {\begin{bmatrix} \color{lightgrey}{?}&\color{red}{0*2+6*4=24}\\ \end{bmatrix}_{(1,2)}} \]\[\color{darkorange}{最终结果=>} \color{darkorange}{\begin{bmatrix} {28}&{24}\\ \end{bmatrix}_{({1},{2})}} \]
- 当第一个参数为1-D时,由于A的形状在numpy中表示为
print("【A@B】\n",A@B)
【A@B】
[18 24]
- 相似地,当第二个参数为1-D时,A同样需要升维。【区别在于】要在
(2,)
中的2后面
添加一个值为1的轴,达到升维的效果。然后,B与A执行点积
操作。当运算完毕后,A原本被添加在后面的轴会被回收,即A回到形状(2,)
的向量模式。\[{\begin{bmatrix} \color{red}{1}&\color{red}{2}\\ {3}&{4}\\ \end{bmatrix}_{(2,2)}} {\begin{bmatrix} \color{red}{0}\\ \color{red}{6}\\ \end{bmatrix}_{(2,1)}} = {\begin{bmatrix} \color{red}{1*0+2*6=12}&\color{lightgrey}{?}\\ \end{bmatrix}_{(1,2)}} \]\[{\begin{bmatrix} {1}&{2}\\ \color{red}{3}&\color{red}{4}\\ \end{bmatrix}_{(2,2)}} {\begin{bmatrix} \color{red}{0}\\ \color{red}{6}\\ \end{bmatrix}_{(2,1)}} = {\begin{bmatrix} \color{lightgrey}{?}&\color{red}{3*0+4*6=24}\\ \end{bmatrix}_{(1,2)}} \]\[\color{darkorange}{最终结果=>} \color{darkorange}{\begin{bmatrix} {12}&{24}\\ \end{bmatrix}_{({1},{2})}} \]
print("【B@A】\n",B@A)
【B@A】
[12 24]
6、多维数组间的运算
- If either argument is N-D, N > 2, it is treated as a stack of matrices residing in the last two indexes and broadcast accordingly.
- 解释为:当参数维度>2时,参数被理解为一些矩阵(参数的最后两个维数为矩阵维数)的stack,计算时会相应的广播。
A = np.random.random((2,2,4))
print("【A】\n",A)
B = np.random.random((2,4,2))
print("【B】\n",B)
print("【A@B】\n",A@B,"\n【shape】\n",A.shape)
【A】
[[[0.0809837 0.29952977 0.12203496 0.04121702]
[0.16743815 0.07071087 0.71797707 0.36474334]]
[[0.64873228 0.94993455 0.90620734 0.57375955]
[0.05383746 0.16905596 0.37846488 0.18973101]]]
【B】
[[[0.13524156 0.63780383]
[0.82055257 0.5262344 ]
[0.65808148 0.86527029]
[0.77220339 0.88265401]]
[[0.54261569 0.20017844]
[0.14652248 0.14892133]
[0.80195632 0.32822467]
[0.21656456 0.30341411]]]
【A@B】
[[[0.36886916 0.35124818]
[0.83481004 1.08718959]]
[[1.34219377 0.74285408]
[0.39858486 0.21774171]]]
【shape】
(2, 2, 4)
四、矩阵的逆运算
1、 numpy.linalg.inv(np.array)
A = np.array([[1,2],[-1,-3]])
np.linalg.inv(A)
array([[ 3., 2.],
[-1., -1.]])
2、定义矩阵的逆
- 什么是逆矩阵
- \(矩阵A为n阶方阵,若存在n阶矩阵B,使得矩阵A、B的乘积为单位阵,则称A为可逆阵,B为A的逆矩阵。若方阵的逆阵存在,则称为可逆矩阵或非奇异矩阵,且其逆矩阵唯一。\\\)
- 什么是奇异矩阵:
- \(首先,看这个矩阵是不是方阵(即行数和列数相等的矩阵,若行数和列数不相等,那就谈不上奇异矩阵和非奇异矩阵)。如是方阵,再看此矩阵的\color{red}{行列式}|A|是否等于0,若等于0,称矩阵A为奇异矩阵;若不等于0,称矩阵A为非奇异矩阵。 同时,由|A|≠0可知矩阵A可逆,这样可以得出另外一个重要结论:可逆矩阵就是非奇异矩阵,非奇异矩阵也是可逆矩阵。 如果A为奇异矩阵,则AX=0有无穷解,AX=b有无穷解或者无解。如果A为非奇异矩阵,则AX=0有且只有唯一零解,AX=b有唯一解。\)
3、计算矩阵\(A\)的逆的方式
(1) 待定系数法(\({A}^{-1}\)为\({A}\)的逆;\({I}\)为单位矩阵,对角线均为\(1\),其他位置均为\(0\)。)
\[A =
{\begin{bmatrix}
{1}&{2}\\
{-1}&{-3}\\
\end{bmatrix}_{(2,2)}}
,
I =
{\begin{bmatrix}
{1}&{0}\\
{0}&{1}\\
\end{bmatrix}_{(2,2)}}
\]
\[假设:{A}^{-1} =
{\begin{bmatrix}
{a}&{b}\\
{c}&{d}\\
\end{bmatrix}_{(2,2)}}
\]
\[\begin{aligned}
A{\cdot}{A}^{-1}&=
{\begin{bmatrix}
{1}&{2}\\
{-1}&{-3}\\
\end{bmatrix}_{(2,2)}}
{\begin{bmatrix}
{a}&{b}\\
{c}&{d}\\
\end{bmatrix}_{(2,2)}}
=
{\begin{bmatrix}
{1}&{0}\\
{0}&{1}\\
\end{bmatrix}_{(2,2)}}\\
&=
{\begin{bmatrix}
{a+2c}&{b+2d}\\
{-a-3c}&{-b-3d}\\
\end{bmatrix}_{(2,2)}}\\
\end{aligned}
\]
\[\begin{cases}
a+2c = 1\\
b+2d = 0\\
-a-3c = 0\\
-b-3d = 1\\
\end{cases}
=>
\begin{cases}
a = 3\\
b = 2\\
c = -1\\
d = -1\\
\end{cases}
\]
\[故:
{A}^{-1}={\begin{bmatrix}
{3}&{2}\\
{-1}&{-1}\\
\end{bmatrix}_{(2,2)}}\\
\]
(2) 高斯消元法
\[A =
{\begin{bmatrix}
{1}&{2}\\
{-1}&{-3}\\
\end{bmatrix}_{(2,2)}}
,
I =
{\begin{bmatrix}
{1}&{0}\\
{0}&{1}\\
\end{bmatrix}_{(2,2)}}
\]
\[\begin{aligned}
{A}{I}&
=
\left[\begin{array}{lc|rc}
1 & 2 & 1 & 0\\
-1 & -3 & 0 & 1\\
\end{array}\right]\\
&\overset{{r_1}+{r_2}}{\rightarrow}
\left[\begin{array}{lc|rc}
1 & 2 & 1 & 0\\
0 & -1 & 1 & 1\\
\end{array}\right]\\
&\overset{{r_1}+{2r_2}}{\rightarrow}
\left[\begin{array}{lc|rc}
1 & 0 & 3 & 2\\
0 & -1 & 1 & 1\\
\end{array}\right]\\
&\overset{{-r_2}}{\rightarrow}
\left[\begin{array}{lc|rc}
1 & 0 & 3 & 2\\
0 & 1 & -1 & -1\\
\end{array}\right]\\
&\end{aligned}
\]
\[故:
{A}^{-1}={\begin{bmatrix}
{3}&{2}\\
{-1}&{-1}\\
\end{bmatrix}_{(2,2)}}\\
\]
(3) 矩阵LU三角分解法
- 线性代数的目的是求解线性方程组\(A\vec{x}=\vec{b}\),并非单纯求A的逆。
- 单就解方程而言,LU分解是最实用的算法,很少会去求逆,求逆可以说是下下策。
<1> 手撸LU求逆步骤有些长,读者请耐心看...
-
\(\color{red}{目标矩阵A和公式关系:}\)
\[A = {\begin{bmatrix} {2}&{2}&{3}\\ {4}&{7}&{7}\\ {-2}&{4}&{5}\\ \end{bmatrix}} ; \begin{cases} L\vec{y} = \vec{b}\\ U\vec{x} = \vec{y}\\ \end{cases} ; AA^{-1}=I\\ \] -
\(\color{red}{分解成U:}\)
\[{\begin{bmatrix} \color{darkorange}{2}&{2}&{3}\\ \color{red}{4}&{7}&{7}\\ \color{blue}{-2}&{4}&{5}\\ \end{bmatrix}} _{r2-2r1、r1+r2} => {\begin{bmatrix} {2}&{2}&{3}\\ {0}&\color{green}{3}&{1}\\ {0}&\color{pink}{6}&{8}\\ \end{bmatrix}} _{r3-2r2} => {\begin{bmatrix} \color{green}{2}&\color{green}{2}&\color{green}{3}\\ {0}&\color{green}{3}&\color{green}{1}\\ {0}&{0}&\color{green}{6}\\ \end{bmatrix}} _{上三角完成}= U \] -
\(\color{red}{通过U的过程求出L:}\)
- \(L的对角线值均为1,对角线上方的值均为0,只需要通过U求对角线下方的值。\)
\[L = {\begin{bmatrix} {1}&{0}&{0}\\ {a_{21}}&{1}&{0}\\ {a_{31}}&{a_{32}}&{1}\\ \end{bmatrix}} = {\begin{bmatrix} {1}&{0}&{0}\\ {\color{red}{4}/\color{darkorange}{2}}&{1}&{0}\\ {\color{blue}{-2}/\color{darkorange}{2}}&{\color{pink}{6}/\color{green}{3}}&1\\ \end{bmatrix}} = {\begin{bmatrix} {1}&{0}&{0}\\ {2}&{1}&{0}\\ {-1}&{2}&{1}\\ \end{bmatrix}}_{下三角完成} \] -
\(\color{red}{验证A=LU:}\)
\[LU = {\begin{bmatrix} {1}&{0}&{0}\\ {2}&{1}&{0}\\ {-1}&{2}&{1}\\ \end{bmatrix}} {\begin{bmatrix} {2}&{2}&{3}\\ {0}&{3}&{1}\\ {0}&{0}&{6}\\ \end{bmatrix}} = {\begin{bmatrix} {2}&{2}&{3}\\ {4}&{7}&{7}\\ {-2}&{4}&{5}\\ \end{bmatrix}} = A {\color{red}{(成立)}} \] -
\(\color{red}{矩阵的转换:}\)
- \(\hat{a}代表A^{-1}中的每个元素\)\[ AA^{-1} = I <=> {\begin{bmatrix} {a_{11}}&{a_{12}}&{a_{13}}\\ {a_{21}}&{a_{22}}&{a_{23}}\\ {a_{31}}&{a_{32}}&{a_{33}}\\ \end{bmatrix}} {\begin{bmatrix} {\hat{a}_{11}}&{\hat{a}_{12}}&{\hat{a}_{13}}\\ {\hat{a}_{21}}&{\hat{a}_{22}}&{\hat{a}_{23}}\\ {\hat{a}_{31}}&{\hat{a}_{32}}&{\hat{a}_{33}}\\ \end{bmatrix}} = {\begin{bmatrix} {1}&{0}&{0}\\ {0}&{1}&{0}\\ {0}&{0}&{1}\\ \end{bmatrix}} \]
- \(根据矩阵相乘规则,将以上等式分解为3份\)
\[ A {\begin{bmatrix} {\hat{a}_{11}}\\ {\hat{a}_{21}}\\ {\hat{a}_{31}}\\ \end{bmatrix}}= {\begin{bmatrix} {1}\\ {0}\\ {0}\\ \end{bmatrix}} ; A {\begin{bmatrix} {\hat{a}_{12}}\\ {\hat{a}_{22}}\\ {\hat{a}_{32}}\\ \end{bmatrix}}= {\begin{bmatrix} {0}\\ {1}\\ {0}\\ \end{bmatrix}} ; A {\begin{bmatrix} {\hat{a}_{13}}\\ {\hat{a}_{23}}\\ {\hat{a}_{33}}\\ \end{bmatrix}}= {\begin{bmatrix} {0}\\ {0}\\ {1}\\ \end{bmatrix}} \] - \(\hat{a}代表A^{-1}中的每个元素\)
-
\(\color{red}{带入求逆:}\)
\[ {\begin{bmatrix}
{2}&{2}&{3}\\
{4}&{7}&{7}\\
{-2}&{4}&{5}\\
\end{bmatrix}}
{\begin{bmatrix}
{\hat{a}_{11}}\\
{\hat{a}_{21}}\\
{\hat{a}_{31}}\\
\end{bmatrix}}=
{\begin{bmatrix}
{1}\\
{0}\\
{0}\\
\end{bmatrix}}
=>
{\begin{bmatrix}
{\hat{a}_{11}}\\
{\hat{a}_{21}}\\
{\hat{a}_{31}}\\
\end{bmatrix}}
=
{\begin{bmatrix}
0.19{\dot4}\\
-0.9\dot{4}\\
0.8\dot{3}\\
\end{bmatrix}}
\]
\[ {\begin{bmatrix}
{2}&{2}&{3}\\
{4}&{7}&{7}\\
{-2}&{4}&{5}\\
\end{bmatrix}}
{\begin{bmatrix}
{\hat{a}_{12}}\\
{\hat{a}_{22}}\\
{\hat{a}_{32}}\\
\end{bmatrix}}=
{\begin{bmatrix}
{0}\\
{1}\\
{0}\\
\end{bmatrix}}
=>
{\begin{bmatrix}
{\hat{a}_{12}}\\
{\hat{a}_{22}}\\
{\hat{a}_{32}}\\
\end{bmatrix}}=
{\begin{bmatrix}
{0.0\dot{5}}\\
{0.\dot{4}}\\
{-0.\dot{3}}\\
\end{bmatrix}}
\]
\[ {\begin{bmatrix}
{2}&{2}&{3}\\
{4}&{7}&{7}\\
{-2}&{4}&{5}\\
\end{bmatrix}}
{\begin{bmatrix}
{\hat{a}_{13}}\\
{\hat{a}_{23}}\\
{\hat{a}_{33}}\\
\end{bmatrix}}
{\begin{bmatrix}
{0}\\
{0}\\
{1}\\
\end{bmatrix}}
=>
{\begin{bmatrix}
{\hat{a}_{13}}\\
{\hat{a}_{23}}\\
{\hat{a}_{33}}\\
\end{bmatrix}}=
{\begin{bmatrix}
{-0.19\dot{4}}\\
{-0.0\dot{5}}\\
{0.1\dot{6}}\\
\end{bmatrix}}
\]
\[ A^{-1}
=
{\begin{bmatrix}
{\hat{a}_{11}}&{\hat{a}_{12}}&{\hat{a}_{13}}\\
{\hat{a}_{21}}&{\hat{a}_{22}}&{\hat{a}_{23}}\\
{\hat{a}_{31}}&{\hat{a}_{32}}&{\hat{a}_{33}}\\
\end{bmatrix}}
=
{\begin{bmatrix}
{0.19\dot{4}}&0.0\dot{5}&-0.19\dot{4}\\
{-0.9\dot{4}}&0.\dot{4}&-0.0\dot{5}\\
0.8\dot{3}&-0.\dot{3}&0.1\dot{6}\\
\end{bmatrix}}
\]
- \(\color{red}{Python代码求逆,对比手算结果:}\)
\[AA^{-1}
=
{\begin{bmatrix}
{2}&{2}&{3}\\
{4}&{7}&{7}\\
{-2}&{4}&{5}\\
\end{bmatrix}}
{\begin{bmatrix}
{0.19\dot{4}}&0.0\dot{5}&-0.19\dot{4}\\
{-0.9\dot{4}}&0.\dot{4}&-0.0\dot{5}\\
0.8\dot{3}&-0.\dot{3}&0.1\dot{6}\\
\end{bmatrix}}
=
{\begin{bmatrix}
{1}&{0}&{0}\\
{0}&{1}&{0}\\
{0}&{0}&{1}\\
\end{bmatrix}}
=
I
\]
# 手算的思维验证逆运算
A = np.array([[2,2,3],[4,7,7],[-2,4,5]])
b1 = np.array([1,0,0])
b2 = np.array([0,1,0])
b3 = np.array([0,0,1])
a_hat1 = np.linalg.solve(A,b1)
a_hat2 = np.linalg.solve(A,b2)
a_hat3 = np.linalg.solve(A,b3)
a = np.vstack((a_hat1,a_hat2,a_hat3))
inv_A = np.transpose(a)
print("【A的逆】\n",inv_A)
np.set_printoptions(suppress=True) # 不输出科学计算格式
print("【验证】AA^(-1)=I\n",np.dot(A,inv_A))
【A的逆】
[[ 0.19444444 0.05555556 -0.19444444]
[-0.94444444 0.44444444 -0.05555556]
[ 0.83333333 -0.33333333 0.16666667]]
【验证】AA^(-1)=I
[[ 1. -0. 0.]
[-0. 1. 0.]
[-0. -0. 1.]]
# 最简单的验证方式
A = np.array([[2,2,3],[4,7,7],[-2,4,5]])
np.linalg.inv(A)
array([[ 0.19444444, 0.05555556, -0.19444444],
[-0.94444444, 0.44444444, -0.05555556],
[ 0.83333333, -0.33333333, 0.16666667]])
(4) PLU三角分解法
-
\(个人认为,PLU解法其实是LU解法的一种优化。\\\)
-
\(P\)的含义:
- 置换矩阵(Permutation Matrix),作用就是用来置换目标矩阵的行或列的
- \(PA用来置换行\)
- 第一行填写A的最后一行
- 第二行填写A的第一行
- 第三行填写A的第二行
\[PA= {\begin{bmatrix} {0}&{0}&{1}\\ {1}&{0}&{0}\\ {0}&{1}&{0}\\ \end{bmatrix}} {\begin{bmatrix} {1}&{2}&{3}\\ {4}&{5}&{6}\\ {7}&{8}&{9}\\ \end{bmatrix}} = {\begin{bmatrix} {7}&{8}&{9}\\ {1}&{2}&{3}\\ {4}&{5}&{6}\\ \end{bmatrix}} \] - \(AP用来置换列\)
- 第一列填写A的第二列
- 第二列填写A的最后一列
- 第三列填写A的第一列
\[AP= {\begin{bmatrix} {1}&{2}&{3}\\ {4}&{5}&{6}\\ {7}&{8}&{9}\\ \end{bmatrix}} {\begin{bmatrix} {0}&{0}&{1}\\ {1}&{0}&{0}\\ {0}&{1}&{0}\\ \end{bmatrix}} = {\begin{bmatrix} {2}&{3}&{1}\\ {5}&{6}&{4}\\ {8}&{9}&{7}\\ \end{bmatrix}} \]
- \(PA用来置换行\)
- 置换矩阵(Permutation Matrix),作用就是用来置换目标矩阵的行或列的
-
\(引入P的原因:\)
- 规避大数,防止类似
memory_out_of_bound
的极端错误发生,让运算更加稳定,提高运算效率。 - 我们拿一个例子说明:
\[\color{red}{---------A=L_{0}U_{0}出现大数---------}\\ A = {\begin{bmatrix} {10}^{-20}&{1}\\ {1}&{1}\\ \end{bmatrix}} = {\begin{bmatrix} {1}&{0}\\ {10}^{20}&{1}\\ \end{bmatrix}} {\begin{bmatrix} {10^{-20}}&{1}\\ {0}&{1-10^{20}}\\ \end{bmatrix}} =L_{0}U_{0}\\ \color{red}{---------PA=L_{1}U_{1}规避大数---------}\\ PA = {\begin{bmatrix} {0}&{1}\\ {1}&{0}\\ \end{bmatrix}} {\begin{bmatrix} {10}^{-20}&{1}\\ {1}&{1}\\ \end{bmatrix}} = {\begin{bmatrix} {1}&{1}\\ {10}^{-20}&{1}\\ \end{bmatrix}} = {\begin{bmatrix} {1}&{0}\\ {10^{-20}}&{1}\\ \end{bmatrix}} {\begin{bmatrix} {1}&{1}\\ {0}&{1-10^{-20}}\\ \end{bmatrix}} =L_{1}U_{1} \]- 选择置换矩阵P的策略:
\(\color{blue}{沿着对角线从左上角到右下角遍历A,并检测当前列的最大元素在下方的哪一行(当前行上方的行保持不变),找到后就将当前行和目标行交换,并记录下一个。最后按顺序算的乘积就得到了P。}\\\) - \(Python中P的求法\)
A = np.array([[2,2,3],[4,7,7],[-2,4,5]]) p, l, u = lu(A) print("【p】\n",p) print("【l】\n",l) print("【u】\n",u)
【p】 [[0. 0. 1.] [1. 0. 0.] [0. 1. 0.]] 【l】 [[ 1. 0. 0. ] [-0.5 1. 0. ] [ 0.5 -0.2 1. ]] 【u】 [[4. 7. 7. ] [0. 7.5 8.5] [0. 0. 1.2]]
- 规避大数,防止类似
五、矩阵的行列式
from scipy.linalg import det
A = np.array([[2,2,3],[4,7,7],[-2,4,5]])
determinant = det(A)
print("【矩阵A的行列式】\n",determinant)
【矩阵A的行列式】
36.0
六、矩阵的特征值和特征向量
1.函数
scipy.linalg.eig(a, b=None, left=False, right=True, overwrite_a=False, overwrite_b=False, check_finite=True, homogeneous_eigvals=False)
2.代码
from scipy.linalg import eig
A = np.array([[2,2,3],[4,7,7],[-2,4,5]])
eig_val = eig(A)
eig_val
(array([ 1.09944991+1.35711935j, 1.09944991-1.35711935j,
11.80110019+0.j ]),
array([[ 0.09875023+0.32757253j, 0.09875023-0.32757253j,
0.30227012+0.j ],
[ 0.68871688+0.j , 0.68871688-0.j ,
0.85783339+0.j ],
[-0.63697277-0.05365987j, -0.63697277+0.05365987j,
0.41563765+0.j ]]))
七、qr分解值
1、函数
scipy.linalg.qr(a, overwrite_a=False, lwork=None, mode='full', pivoting=False, check_finite=True)[source]
- Calculate the decomposition A = Q R where Q is unitary/orthogonal and R upper triangular.
2、代码
from scipy.linalg import qr
A = np.array([[2,2,3],[4,7,7],[-2,4,5]])
qr(A)
(array([[-0.40824829, 0. , 0.91287093],
[-0.81649658, -0.4472136 , -0.36514837],
[ 0.40824829, -0.89442719, 0.18257419]]),
array([[-4.89897949, -4.89897949, -4.89897949],
[ 0. , -6.70820393, -7.60263112],
[ 0. , 0. , 1.09544512]]))
八、svd分解值
1、函数
scipy.linalg.svd(a, full_matrices=True, compute_uv=True, overwrite_a=False, check_finite=True, lapack_driver='gesdd')
- Factorizes the matrix a into two unitary matrices U and Vh, and a 1-D array s of singular values (real, non-negative) such that a == U @ S @ Vh, where S is a suitably shaped matrix of zeros with main diagonal s.
2、代码
from scipy.linalg import svd
A = np.array([[2,2,3],[4,7,7],[-2,4,5]])
svd(A)
(array([[-0.31181575, 0.25631867, 0.91491621],
[-0.83572711, 0.38412266, -0.39244105],
[-0.45203002, -0.88698958, 0.09443697]]),
array([12.64089135, 3.9611834 , 0.71895193]),
array([[-0.24226772, -0.65516277, -0.71558934],
[ 0.96514267, -0.08746437, -0.24667712],
[ 0.0990251 , -0.75040771, 0.65351534]]))