说明:本篇博客出自湖南师范大学基础教育大数据研究与应用重点实验室
人工智能基础-数学知识之线性代数
本篇博客是人工智能基础-数学知识之线性代数的第二部分内容,主要包括矩阵(矩阵的创建、矩阵的运算、逆矩阵),矩阵与方程组的关系、最小二乘解的理解、及最小二乘法与线性回归的关系。
一、矩阵
矩阵就是个n行m列的二维表格,若行数和列数相等,这样的矩阵就被称为方阵,一个n行n列的方阵习惯上被叫做n阶方阵。
从形态上讲,矩阵可以分为方阵和非方阵两大类,方阵又有一些特殊形态,主要包括对角矩阵、单位矩阵、对称矩阵。
1.1 矩阵的创建
NumPy中有两种数据结构可以用于矩阵:ndarray和matrix。ndarray是广义的数组,既可以表示向量,又可以表示矩阵,甚至于更高维度的张量;matrix是专门针对矩阵的数据结构,是个二维数组。两者皆支持矩阵运算。
以下代码统一用matrix演示。
1.1.1 矩阵
①直接用mat方法创建矩阵,把一个二维数组对象传给它即可。代码如下:
# 用mat方法创建矩阵
import numpy as np
x=np.mat(np.random.rand(4,4))
print(x)
"""
结果为:
[[0.10734948 0.60631165 0.89618799 0.6914929 ]
[0.88829893 0.89936192 0.50669766 0.40657719]
[0.04182487 0.90204024 0.59826036 0.91880716]
[0.57673069 0.23257675 0.77724255 0.47098502]]
"""
②也可以用一个MATLAB风格的字符串来创建matrix对象。MATLAB风格的字符串就是一个以空格分隔列、以分号分隔行的字符串。
# 用mat方法创建矩阵
import numpy as np
x=np.mat('1 2 3; 4 5 6; 7 8 9')
print(x)
"""
结果为:
[[1 2 3]
[4 5 6]
[7 8 9]]
"""
1.1.2 对角矩阵
一个方阵对角线之外的元素都是0,这样的方阵就是对角方阵。通常可以这样表示:
[
a
11
0
0
0
0
a
22
0
0
0
0
a
33
0
0
0
0
a
44
]
\begin{bmatrix} a_{11} & 0 & 0 & 0 \\ 0 & a_{22} & 0 & 0 \\ 0 & 0 & a_{33} & 0 \\ 0 & 0 & 0 & a_{44}\end{bmatrix} \quad
⎣⎢⎢⎡a110000a220000a330000a44⎦⎥⎥⎤
在Numpy中,创建对角矩阵的方法是diag。
#创建对角矩阵
import numpy as np
x=np.diag([1,2,3,5]) # diag的参数就是对角线的元素的值
print(x)
"""
结果为
[[1 0 0 0]
[0 2 0 0]
[0 0 3 0]
[0 0 0 5]]
"""
1.1.3 单位矩阵
指一个方阵对角线元素都是1的对角矩阵,一般用字母𝐼表示。
I
=
[
1
0
0
0
0
1
0
0
0
0
1
0
0
0
0
1
]
I=\begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1\end{bmatrix} \quad
I=⎣⎢⎢⎡1000010000100001⎦⎥⎥⎤
在Numpy中,创建单位矩阵的方法是eye。
#创建单位矩阵
import numpy as np
x=np.eye(4) # eye()的参数为方阵的维数
print(x)
"""
结果为
[[1. 0. 0. 0.]
[0. 1. 0. 0.]
[0. 0. 1. 0.]
[0. 0. 0. 1.]]
"""
1.1.4 对称矩阵
方阵中的元素满足
a
i
j
=
𝑎
𝑗
𝑖
a_{ij}=𝑎_{𝑗𝑖}
aij=aji这个方阵就称为对称矩阵。对称方阵的特点是
𝐴
=
𝐴
𝑇
𝐴=𝐴^𝑇
A=AT
Numpy没有提供创建对称矩阵的方法,不过可以根据对称方阵的特点进行创建。
#创建对称矩阵
import numpy as np
A=np.mat('1 2 3; 4 5 6; 7 8 9')
print(A*A.T) # T就是对矩阵转置
"""
结果为
[[ 14 32 50]
[ 32 77 122]
[ 50 122 194]]
"""
1.2 矩阵的运算
矩阵的运算包括加、减、数乘等常规操作,还有矩阵特有的矩阵乘法、求逆矩阵等。
1.2.1 矩阵的加法和数乘
矩阵加法就是把其对应元素相加;
数乘就是将绝阵中的每个元素和这个数字相乘。
#矩阵的加法和数乘运算
import numpy as np
A=np.mat('1 2 3; 4 5 6; 7 8 9')
B=np.mat('1 2 3; 4 5 6; 7 8 9')
# 两个矩阵直接相加
print(A+B)
# 矩阵与数字相乘
print(A*3)
"""
结果为:
[[ 2 4 6]
[ 8 10 12]
[14 16 18]]
[[ 3 6 9]
[12 15 18]
[21 24 27]]
"""
1.2.2 矩阵乘法
两个矩阵相乘的运算规则如图所示,:
运算法则也如公式所示
C
[
i
]
[
j
]
=
s
u
m
(
A
[
i
]
[
k
]
∗
B
[
k
]
[
j
]
)
,
k
=
1
,
.
.
.
,
n
C[i][j]=sum(A[i][k]*B[k][j]),k=1,...,n
C[i][j]=sum(A[i][k]∗B[k][j]),k=1,...,nNumPy重载了矩阵的乘法运算符,所以两个矩阵对象可以使用乘号直接运算。
#矩阵乘法运算
import numpy as np
A=np.mat('1 2 3; 4 5 6; 7 8 9')
B=np.mat('1 2 3; 4 5 6; 7 8 9')
print(A*B)
"""
结果为:
[[ 30 36 42]
[ 66 81 96]
[102 126 150]]
"""
1.2.3 逆矩阵
n阶方阵𝐴,若存在n阶方阵𝐵,使得𝐴𝐵=𝐵𝐴=𝐼,就认为方阵𝐴可逆,其逆矩阵是𝐵,记作
𝐴
−
1
=
𝐵
𝐴^{−1}=𝐵
A−1=B
NumPy的matrix类可以用.𝐼进行矩阵的求逆。
#矩阵求逆运算
import numpy as np
A=np.mat(np.random.rand(3,3))
B=A.I
print(B)
print(A*B) #验证。矩阵与逆矩阵的乘积结果应该是单位矩阵
"""
结果为:
[[ 1.48503851 2.91919395 -7.7984185 ]
[ 18.83764252 10.33212638 -57.97021969]
[-23.58383003 -15.046136 80.71690901]]
#由于计算机精度问题,非对角线元素是非常接近0的数字。
[[ 1.00000000e+00 -5.81251328e-16 -3.63077105e-15]
[ 6.18014183e-17 1.00000000e+00 -7.98300484e-16]
[ 4.52833976e-16 -2.42575889e-16 1.00000000e+00]]
"""
二、矩阵与线性方程组
首先摆出结论:矩阵最基本的应用是求解线性方程组。
举个例子,方程组为:
{
2
x
+
y
=
3
4
x
+
3
y
=
7
\begin{cases} 2x+y=3\\ 4x+3y=7 \end{cases}
{2x+y=34x+3y=7
很明显,这个方程组的解为
x
=
1
,
y
=
1
x=1,y=1
x=1,y=1
根据矩阵乘法的规则,上面这个方程组还可以变为(大家仔细感受一下):
[
2
1
4
3
]
∗
[
x
y
]
=
[
3
7
]
\begin{bmatrix} 2 & 1 \\ 4 & 3 \end{bmatrix} \quad*\begin{bmatrix} x \\ y \end{bmatrix} \quad=\begin{bmatrix} 3 \\ 7 \end{bmatrix} \quad
[2413]∗[xy]=[37]
人们约定俗成地用大写字母地黑斜体表示矩阵,比如𝐴;用小写字母地黑斜体表示向量,比如a,小写y代表向量,所以上面的方程组可以表示成:
A
a
=
y
Aa=y
Aa=y
三、最小二乘解
假如现在有一个问题:二维平面上有三个点A(1,1),B(2,2),C(3,2),试求一条直线来拟合这三个点。
如果求一条直线经过这三个点,这是无法做到的,也就是说没有解析解。但是我们可以寻求它的近似解(最优解),从下面三个角度看。
3.1 微积分方法
全文假设不存在非常奇怪的点,所有的点都在某一直线附近。
那么假设拟合的直线方程: y = a x + b y=ax+b y=ax+b
那么误差和 f f f为:
f = Σ i = 1 3 ( a x i + b − y i ) 2 f=Σ^{3}_{i=1}(ax_i+b-y_i)^2 f=Σi=13(axi+b−yi)2
我们就是要最小化这个误差平方和,因此叫做最小平方法(least square method)。
对于微积分方法,如果
f
f
f是连续的,则
f
f
f在导数为0时取得极值。而此时
f
f
f是二次函数,则极值只有一个,也是最值。
分别求
f
f
f对
a
a
a和
b
b
b的偏导,并让其等于0,得到两个方程:
14
a
+
6
b
=
11
14a+6b=11
14a+6b=11
6
a
+
3
b
=
5
6a+3b=5
6a+3b=5
解得
a
=
1
2
a=\frac{1}{2}
a=21 ,
b
=
2
3
b=\frac{2}{3}
b=32
3.2 数值求解
原问题等价于:
m
i
n
∥
A
x
−
y
∥
2
2
{min∥Ax−y∥}_2^2
min∥Ax−y∥22
记
f
(
x
)
=
∥
A
x
−
y
∥
2
2
=
(
A
x
−
y
)
T
(
A
x
+
y
)
=
x
T
A
T
A
x
−
2
y
T
A
x
+
y
T
y
f(x)={∥Ax−y∥}_2^2=(Ax-y)^T(Ax+y)=x^TA^TAx−2y^TAx+y^Ty
f(x)=∥Ax−y∥22=(Ax−y)T(Ax+y)=xTATAx−2yTAx+yTy,
因为要取最小值,对 x 求导得:
Δ
f
=
2
(
A
T
A
x
−
A
T
y
)
Δf=2(A^TAx-A^Ty)
Δf=2(ATAx−ATy)
解得
x
=
(
A
T
A
)
−
1
A
T
y
x=(A^TA)^{−1} A^Ty
x=(ATA)−1ATy
对于刚刚那个实例,同样假设直线方程为 y = a x + b y=ax+b y=ax+b
将三个点代入方程,则有: a + b = 1 a+b=1 a+b=1; 2 a + b = 2 2a+b=2 2a+b=2; 3 a + b = 2 3a+b=2 3a+b=2
写成矩阵形式为: [ 1 1 2 1 3 2 ] ∗ [ a b ] = [ 1 2 2 ] \begin{bmatrix} 1 & 1 \\2 & 1 \\ 3 & 2 \end{bmatrix} \quad*\begin{bmatrix} a \\ b \end{bmatrix} \quad=\begin{bmatrix} 1 \\ 2 \\ 2 \end{bmatrix} \quad ⎣⎡123112⎦⎤∗[ab]=⎣⎡122⎦⎤即是 A x = y Ax=y Ax=y
但是我们知道,b不在A平面上,就是我们无法找到精确解,只能找近似解。
根据上一节的知识点,只需在方程两边左乘A的转置就可以得到近似解: x = ( A T A ) − 1 A T y x=(A^TA)^{−1} A^Ty x=(ATA)−1ATy分别计算 A T A A^TA ATA 、 A T y A^Ty ATy得到方程:
6 a + 3 b = 5 6a+3b=5 6a+3b=5 14 a + 6 b = 11 14a+6b=11 14a+6b=11解得 a = 1 / 2 a=1/2 a=1/2, b = 2 / 3 b=2/3 b=2/3。
3.3 几何理解
平面D是由向量 a 1 a_1 a1, a 2 a_2 a2生成的空间。 b b b向量穿过D,交于点O。它在平面上的投影是p向量。
如果问,怎么用 a 1 a_1 a1, a 2 a_2 a2来表示b,准确答案是无解的。但是我们可以找到它的最优近似解,就是b在D上的投影p。
四、用python解方程组
4.1 有解析解的方程组
NumPy中有个linalg子模块提供了solve方法来解方程组。比如下面这个方程组:
{
x
−
2
y
+
z
=
0
2
y
−
8
z
=
8
−
4
x
+
5
y
+
9
z
=
−
9
\begin{cases} x-2y+z=0 \\ 2y-8z=8 \\ -4x+5y+9z=-9 \end{cases}
⎩⎪⎨⎪⎧x−2y+z=02y−8z=8−4x+5y+9z=−9可以这么解:
# 用solve方法解方程组
import numpy as np
# 把方程组左边的系数用矩阵表示
A = np.mat("1 -2 1;0 2 -8;-4 5 9")
# 把方程组右边的结果用向量表示
b = np.array([0, 8, -9])
# 直接调用linalg中的solve函数求解
x = np.linalg.solve(A,b)
print(x)
# 结果为 [29. 16. 3.]
4.2 没有解析解的方程组
再看下面这个方程组:
{
x
−
2
y
+
z
=
0
2
y
−
z
=
8
−
4
x
+
5
y
−
2.5
z
=
−
9
\begin{cases} x-2y+z=0 \\ 2y-z=8 \\ -4x+5y-2.5z=-9 \end{cases}
⎩⎪⎨⎪⎧x−2y+z=02y−z=8−4x+5y−2.5z=−9
如果使用4.1的方法,会发现结果报错,其中有这样一句话:numpy.linalg.LinAlgError: Singular matrix
这个错误是说,系数矩阵A是个奇异矩阵,是不可求逆的句子,即方程组没有解析解,那如何找最优解呢?
可以这么解:
# 求最小二乘解
import numpy as np
A = np.mat("1 -2 1;0 2 -1;-4 5 -2.5")
pi_a = np.linalg.pinv(A) # 求伪逆,求解
b = np.array([0,8,-9])
x = np.dot(pi_a,b)
print(x)
# 结果为 [[ 7.14285714 3.10649351 -1.55324675]]
这个解也叫做最小二乘解。
五、最小二乘法与线性回归
回归(Regression)是一类重要的监督学习算法,其目标是通过训练样本的学习,得到从样本特征到目标值之间的映射。在回归中,样本的标签是连续值。线性回归(Linear Regression)是回归问题中的重要一类。在线性回归中,样本特征与目标值之间是线性相关的。
回归的重要应用是预测,比如根据人的身高、性别、体重等特征预测鞋子的尺码;根据学历、专业、工作经验等特征预测薪资待遇;根据房屋的面积、楼层、户型等特征预测房屋的价格。
最简单的回归是线性回归,就是建立下面这样一个公式:
y
=
a
1
x
1
+
a
2
x
2
+
.
.
.
+
a
m
x
m
+
b
y=a_1x_1+a_2x_2+...+a_mx_m+b
y=a1x1+a2x2+...+amxm+b其中:
y
y
y是关心的目标,如房屋的价格;
x
1
,
x
2
,
.
.
.
,
x
m
x_1,x_2,...,x_m
x1,x2,...,xm是数据中的特征,比如房屋的面积、楼层、户型等;
a
1
,
a
2
,
.
.
.
,
a
m
a_1,a_2,...,a_m
a1,a2,...,am是特征的系数;
b
b
b是截距项。
一旦能够得到这样一个方程,就可以把某一个房屋的
x
i
x_i
xi代入方程算出房屋的价格
y
y
y,这就是所谓的回归预测。
通常来说,可以把截距项
b
b
b当作一个新特征的系数,这个特征在所有样本上的值都是一样的,所以原始公式可以简化为
y
=
Σ
i
=
1
m
+
1
a
i
+
x
i
y=Σ^{m+1}_{i=1}a_i+x_i
y=Σi=1m+1ai+xi将特征值和目标代入方程组后可以发现:回归问题其实就是解方程组求未知系数
a
i
a_i
ai的问题,而且每个方程组都是最简单的线性方程,就可以用到我们前面讲的最小二乘法,即
x
=
(
A
T
A
)
−
1
A
T
y
x=(A^TA)^{−1} A^Ty
x=(ATA)−1ATy
总结:
- 矩阵最基本的应用是求解线性方程组。
- 线性回归中可以使用最小二乘法的策略。
- 最小二乘法结论: ( A T A ) x = A T y (A^TA)x=A^Ty (ATA)x=ATy
欢迎大家在评论区提出自己对本篇博客的看法和建议,有问题可留言或私戳我~
参考文献
[1] 张晓明.人工智能基础——数学知识.北京:人民邮电出版社.2020.
[2] 理解最小二乘法:https://zhuanlan.zhihu.com/p/44596093
[3] 最小二乘法的求解:https://blog.youkuaiyun.com/chenaiyanmie/article/details/80245846
[4] 最小二乘法(1)——线性问题:https://www.cnblogs.com/bigmonkey/p/11305015.html
[5] 线性代数: 什么是矩阵,以及矩阵的线性代数意义:https://blog.youkuaiyun.com/f980511/article/details/100762921