线性代数
正交性
正交基和标准正交基
描述空间的一个重要方式除了维度以外就是基,基是一组向量,这组向量的个数就是这个空间的维度. 而一个n维空间任何一组线性无关的向量都是这个n维空间的一组基.正因如此一个n维空间是有无数组基的.但实际为了研究方便,一般更倾向于正交基(下右)

首先两个向量互相垂直,称两个向量正交. 而一组向量,如果两两正交,则称为正交向量组. 正交非零向量组一定线性无关.
Prof.正交非零向量组一定线性无关假设v1,v2,v3,..vn是一组正交向量组需证明:k1v1+k2v2+k3v3+...+knvn=0只有零解(k1v1+k2v2+k3v3+...+knvn).v1=0.vik1v1.vi+k2v2.vi++...+kivi.vi+knvn.vi=0kivi.vi=0ki∣∣vi∣∣2=0∣∣vi∣∣2>0,ki=0得证
因此,n个非零正交向量一定是n维空间的基.
如果一个空间的一组基两两正交,则称这组基为一组正交基.
如果一个空间的一组正交基,模均为1,则称这组基为一组标准正交基. 而一个空间的标准正交基依然有无数组:
一维投影
通常对于一个空间来说我们只能得到随便的一组基,前面讲了如何求四大子空间的维度和一组基,但是得到的那组基绝对不能保证他们是正交的,我们得到的这组基是什么样子是和给定的矩阵是密切相关的.
因此如果给定一个空间的一组基,我们希望进一步找到这个空间的一组正交基,进一步如何找到标准正交基?
以2维空间为例,如果给出任意一组基,如何得到一组正交基?需要借助投影:
这样就解决了2维空间如何找到一组标准正交基的问题,那么到3维空间以及n维空间呢?
高维投影和Gram-Schmidt过程
看看三维空间如何求正交基:

如上图左是一组三维空间的基u,v,w ,首先使用上面讲的一维投影处理其中的两个向量u,v 变成p1,p2 , 此时p1,p2 相互正交,接着只需要将w 和p1,p2 垂直. 在w 向量末端引一条垂线垂直于p1,p2 组成的平面得到投影p, 此时和p1,p2 都垂直的向量就是 绿色的w−p .
很容易发现a 是w 在p1 的投影,而b 是w 在p2 的投影.
a=∣∣p1∣∣2w.p1p1b=∣∣p2∣∣2w.p2p2w−p=w−∣∣p1∣∣2w.p1p1−∣∣p2∣∣2w.p2p2
因此最终结果:
p1=up2=v−pv=v−∣∣p1∣∣2p1.vp1p3=w−pw=w−∣∣p1∣∣2w.p1p1−∣∣p2∣∣2w.p2p2
如果已知一组基:v1,v2,v3,…vn , 求一组正交基:
p1=v1p2=v2−∣∣p1∣∣2p1.v2p1p3=v3−∣∣p1∣∣2v3.p1p1−∣∣p2∣∣2v3.p2p2p4=v4−∣∣p1∣∣2v4.p1p1−∣∣p2∣∣2v4.p2p2−−∣∣p3∣∣2v4.p3p3...pn=vn−...
这个过程就叫做格拉姆-施密特过程,即Gram-Schmidt过程. 注意算法的输入是一组基,即线性无关的.
Gram-Schmidt过程就是 给出一组基,求出另外一组基的过程.
有了正交基得到标准正交基就很简单:
u^=∣∣u∣∣1.u=(∣∣u∣∣u1,∣∣u∣∣u2,...,∣∣u∣∣un)
代码实现Gram-Schmidt:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| from .Vector import Vector from .Matrix import Matrix from .LinearSystem import rank
def gram_schmidt_process(basis):
matrix = Matrix(basis) assert rank(matrix) == len(basis)
res = [basis[0]] for i in range(1, len(basis)): p = basis[i] for r in res: p = p - basis[i].dot(r) / r.dot(r) * r res.append(p) return res
|
简单测试代码:
1 2 3 4 5 6 7 8 9 10
| from LA.Vector import Vector from LA.GramSchmidtProcess import gram_schmidt_process
if __name__ == "__main__": basis = [Vector([2,1]),Vector([1,1])]
res1 = gram_schmidt_process(basis) for row in res1: print(row)
|

可见这组基是正交基.
标准正交基的性质
一组n维标准正交基v1,v2,v3,…,vn , 按照列的方式排成一个n阶方阵Q,称Q为标准正交矩阵. 之所以是方阵是因为标准正交矩阵的核心性质和幂有关,而只有方阵有矩阵的幂.
标准正交矩阵的重要性质:
QT.Q=I
证明:
Prof.QT.Q=IQ=(v1v2...vn)QT.Q=v1v2...vn(v1v2...vn)=v1.v1v2.v1...vn.v1v1.v2v2.v2...vn.v2............v1.vnv2.vnvn.vn=10...001...0............001=I
Q的各列是线性无关的,可以得到Q是可逆的,而QT 是Q的左逆,QT 就是Q的右逆,QT 就是Q的逆.
因此对于标准正交矩阵来说:
Q−1=QT
机器学习算法的PCA降维将一个高维空间降为一个低维空间,反过来低维空间在转成高维空间就需要利用这条性质. 因为描述低维空间的方式就是一个标准正交矩阵,反过去的过程就需要看这个标准正交矩阵的逆.
矩阵的QR分解
上面标准正交矩阵的这个性质Q−1=QT 的一个应用就是矩阵的QR分解:
A=QR
其中Q就是标准正交矩阵,R是一个上三角矩阵.
为什么把矩阵分成Q,R和这样的形式?很多真实世界的问题本质就是Ax=b 这样的线性系统,如果此时A可以分解为Q和R两部分:
(QR)x=bQ−1QRx=Q−1bRx=QTb
两边同时乘以Q−1 ,此时方程就可以非常快的求解出来.
假设A=(a1a2…an) ,对A的各个列向量执行Gram-Schmidt过程,得到p1,p2,p3,…,pn , 然后在进行规范化得到q1,q2,q3,…,qn.
而每个p的求法就是前面提到的Gram-Schmidt过程:
p1=a1p2=a2−∣∣p1∣∣2a2.p1p1p3=a3−∣∣p1∣∣2a3.p1p1−∣∣p2∣∣2a3.p2p2p4=a4−∣∣p1∣∣2a4.p1p1−∣∣p2∣∣2a4.p2p2−−∣∣p3∣∣2a4.p3p3...
观察一下a,p,q的关系:
p1=a1=∣∣p1∣∣q1=r11q1p2=a2−∣∣p1∣∣2a2.p1p1=∣∣p2∣∣q2a2=∣∣p1∣∣2a2.p1p1+∣∣p2∣∣q2=r21q1+r22q2p3=a3−∣∣p1∣∣2a3.p1p1−∣∣p2∣∣2a3.p2p2a3=∣∣p1∣∣2a3.p1p1+∣∣p2∣∣2a3.p2p2+∣∣p3∣∣q3=r31q1+r32q2+r33q3
根据Gram-Schmidt过程把A化成一组正交基,然后化为标准正交基,那么反推回来A的各个列向量都可以写成这组标准正交基各个列向量的线性组合:
a1=r11q1a2=r21q1+r22q2a3=r31q1+r32q2+r33q3a4=r41q1+r42q2+r43q3+r44q4an=rn1q1+rn2q2+rn3q3+...+rnnqn
因此A可以写成n个矩阵相加的形式:
A=(a1a2...an)=(r11q1r21q1+r22q2...rn1q1+rn2q2+...+rnnqn)=(r11q1r21q1..rn1q1)+(0r22q2...rn2q2)+...+(00...rnnqn)=(q1q2...qn).r110...0r21r22...0............rn1rn2...rnn=Q.R
前面的标准正交矩阵就是Q,后面的上三角矩阵是R,这样就实现了矩阵的QR分解.
相当于证明了方阵A的各个列向量线性无关的话能够进行矩阵的QR分解,进而通过Gram-Schmidt求出Q,然后通过正交矩阵性质求出R.
对于R,我们可以通过下面式子求得:
R=Q−1.A
代码实现QR分解:
1 2 3 4 5 6 7 8 9
| def qr(A): assert A.row_num() == A.col_num(),"A must be square"
basis=[A.col_vector(i) for i in range(A.col_num())] P = gram_schmidt_process(basis) Q = Matrix([v/v.norm() for v in P]).T() R = Q.T().dot(A)
return Q, R
|
测试代码:
1 2 3 4 5 6 7 8 9 10 11
| from LA.Matrix import Matrix from LA.GramSchmidtProcess import qr
if __name__ == "__main__": A = Matrix([[1,1,2],[1,1,0],[1,0,0]])
Q1,R1 = qr(A) print(Q1) print(R1) print(Q1.dot(R1))
|

上面打印结果正确.