Skip to content

第三十一讲:线性变换及对应矩阵

如何判断一个操作是不是线性变换?线性变换需满足以下两个要求:

T(v+w)=T(v)+T(w)T(cv)=cT(v)

即变换T需要同时满足加法和数乘不变的性质。将两个性质合成一个式子为:T(cv+dw)=cT(v)+dT(w)

例1,二维空间中的投影操作,T:R2R2,它可以将某向量投影在一条特定直线上。检查一下投影操作,如果我们将向量长度翻倍,则其投影也翻倍;两向量相加后做投影与两向量做投影再相加结果一致。所以投影操作是线性变换。

“坏”例1,二维空间的平移操作,即平面平移:

python
%matplotlib inline
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np


fig = plt.figure()

sp1 = plt.subplot(221)
vectors_1 = np.array([[0,0,3,2],]) 
X_1, Y_1, U_1, V_1 = zip(*vectors_1)
plt.axhline(y=0, c='black')
plt.axvline(x=0, c='black')
sp1.quiver(X_1, Y_1, U_1, V_1, angles='xy', scale_units='xy', scale=1)
sp1.set_xlim(0, 10)
sp1.set_ylim(0, 5)
sp1.set_xlabel("before shifted")

sp2 = plt.subplot(222)
vector_2 = np.array([[0,0,3,2],
                     [3,2,2,0],
                     [0,0,5,2],
                     [0,0,10,4]]) 
X_2,Y_2,U_2,V_2 = zip(*vector_2)
plt.axhline(y=0, c='black')
plt.axvline(x=0, c='black')
sp2.quiver(X_2, Y_2, U_2, V_2, angles='xy', scale_units='xy', scale=1)
sp2.set_xlim(0, 10)
sp2.set_ylim(0, 5)
sp2.set_xlabel("shifted by horizontal 2 then double")

sp3 = plt.subplot(223)
vectors_1 = np.array([[0,0,6,4],]) 
X_1, Y_1, U_1, V_1 = zip(*vectors_1)
plt.axhline(y=0, c='black')
plt.axvline(x=0, c='black')
sp3.quiver(X_1, Y_1, U_1, V_1, angles='xy', scale_units='xy', scale=1)
sp3.set_xlim(0, 10)
sp3.set_ylim(0, 5)
sp3.set_xlabel("double the vector")

sp4 = plt.subplot(224)
vector_2 = np.array([[0,0,6,4],
                     [6,4,2,0],
                     [0,0,8,4]]) 
X_2,Y_2,U_2,V_2 = zip(*vector_2)
plt.axhline(y=0, c='black')
plt.axvline(x=0, c='black')
sp4.quiver(X_2, Y_2, U_2, V_2, angles='xy', scale_units='xy', scale=1)
sp4.set_xlim(0, 10)
sp4.set_ylim(0, 5)
sp4.set_xlabel("doubled vector shifted by horizontal 2")

plt.subplots_adjust(hspace=0.33)
plt.draw()
%matplotlib inline
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np


fig = plt.figure()

sp1 = plt.subplot(221)
vectors_1 = np.array([[0,0,3,2],]) 
X_1, Y_1, U_1, V_1 = zip(*vectors_1)
plt.axhline(y=0, c='black')
plt.axvline(x=0, c='black')
sp1.quiver(X_1, Y_1, U_1, V_1, angles='xy', scale_units='xy', scale=1)
sp1.set_xlim(0, 10)
sp1.set_ylim(0, 5)
sp1.set_xlabel("before shifted")

sp2 = plt.subplot(222)
vector_2 = np.array([[0,0,3,2],
                     [3,2,2,0],
                     [0,0,5,2],
                     [0,0,10,4]]) 
X_2,Y_2,U_2,V_2 = zip(*vector_2)
plt.axhline(y=0, c='black')
plt.axvline(x=0, c='black')
sp2.quiver(X_2, Y_2, U_2, V_2, angles='xy', scale_units='xy', scale=1)
sp2.set_xlim(0, 10)
sp2.set_ylim(0, 5)
sp2.set_xlabel("shifted by horizontal 2 then double")

sp3 = plt.subplot(223)
vectors_1 = np.array([[0,0,6,4],]) 
X_1, Y_1, U_1, V_1 = zip(*vectors_1)
plt.axhline(y=0, c='black')
plt.axvline(x=0, c='black')
sp3.quiver(X_1, Y_1, U_1, V_1, angles='xy', scale_units='xy', scale=1)
sp3.set_xlim(0, 10)
sp3.set_ylim(0, 5)
sp3.set_xlabel("double the vector")

sp4 = plt.subplot(224)
vector_2 = np.array([[0,0,6,4],
                     [6,4,2,0],
                     [0,0,8,4]]) 
X_2,Y_2,U_2,V_2 = zip(*vector_2)
plt.axhline(y=0, c='black')
plt.axvline(x=0, c='black')
sp4.quiver(X_2, Y_2, U_2, V_2, angles='xy', scale_units='xy', scale=1)
sp4.set_xlim(0, 10)
sp4.set_ylim(0, 5)
sp4.set_xlabel("doubled vector shifted by horizontal 2")

plt.subplots_adjust(hspace=0.33)
plt.draw()

png

python
plt.close(fig)
plt.close(fig)

比如,上图中向量长度翻倍,再做平移,明显与向量平移后再翻倍的结果不一致。

有时我们也可以用一个简单的特例判断线性变换,检查T(0)=?0。零向量平移后结果并不为零。

所以平面平移操作并不是线性变换。

“坏”例2,求模运算,T(v)=v, T:R3R1,这显然不是线性变换,比如如果我们将向量翻倍则其模翻倍,但如果我将向量翻倍取负,则其模依然翻倍。所以T(v)T(v)

例2,旋转45操作,T:R2R2,也就是将平面内一个向量映射为平面内另一个向量。检查可知,如果向量翻倍,则旋转后同样翻倍;两个向量先旋转后相加,与这两个向量先相加后旋转得到的结果一样。

所以从上面的例子我们知道,投影与旋转都是线性变换。

例3,矩阵乘以向量,T(v)=Av,这也是一个(一系列)线性变换,不同的矩阵代表不同的线性变换。根据矩阵的运算法则有A(v+w)=A(v)+A(w), A(cv)=cAv。比如取A=[1001],作用于平面上的向量v,会导致vx分量不变,而y分量取反,也就是图像沿x轴翻转。

线性变换的核心,就是该变换使用的相应的矩阵。

比如我们需要做一个线性变换,将一个三维向量降至二维,T:R3R2,则在T(v)=Av中,vR3, T(v)R2,所以A应当是一个2×3矩阵。

如果我们希望知道线性变换T对整个输入空间Rn的影响,我们可以找到空间的一组基v1, v2, , vn,检查T对每一个基的影响T(v1), T(v2), , T(vn),由于输入空间中的任意向量都满足:

所以我们可以根据T(v)推出线性变换T对空间内任意向量的影响,得到:

现在我们需要考虑,如何把一个与坐标无关的线性变换变成一个与坐标有关的矩阵呢?

1式中,c1,c2,,cn就是向量v在基v1,v2,,vn上的坐标,比如分解向量v=[324]=3[100]+2[010]+4[001],式子将向量v分解在一组标准正交基[100],[010],[001]上。当然,我们也可以选用矩阵的特征向量作为基向量,基的选择是多种多样的。

我们打算构造一个矩阵A用以表示线性变换T:RnRm。我们需要两组基,一组用以表示输入向量,一组用以表示输出向量。令v1,v2,,vn为输入向量的基,这些向量来自Rnw1,w2,,wm作为输出向量的基,这些向量来自Rm

我们用二维空间的投影矩阵作为例子:

python
fig = plt.figure()

vectors_1 = np.array([[0, 0, 3, 2],
                      [0, 0, -2, 3]]) 
X_1, Y_1, U_1, V_1 = zip(*vectors_1)
plt.axis('equal')
plt.axhline(y=0, c='black')
plt.axvline(x=0, c='black')
plt.quiver(X_1, Y_1, U_1, V_1, angles='xy', scale_units='xy', scale=1)
plt.plot([-6, 12], [-4, 8])
plt.annotate('$v_1=w_1$', xy=(1.5, 1), xytext=(10, -20), textcoords='offset points', size=14, arrowprops=dict(arrowstyle="->"))
plt.annotate('$v_2=w_2$', xy=(-1, 1.5), xytext=(-60, -20), textcoords='offset points', size=14, arrowprops=dict(arrowstyle="->"))
plt.annotate('project line', xy=(4.5, 3), xytext=(-90, 10), textcoords='offset points', size=14, arrowprops=dict(arrowstyle="->"))

ax = plt.gca()
ax.set_xlim(-5, 5)
ax.set_ylim(-4, 4)
ax.set_xlabel("Project Example")

plt.draw()
fig = plt.figure()

vectors_1 = np.array([[0, 0, 3, 2],
                      [0, 0, -2, 3]]) 
X_1, Y_1, U_1, V_1 = zip(*vectors_1)
plt.axis('equal')
plt.axhline(y=0, c='black')
plt.axvline(x=0, c='black')
plt.quiver(X_1, Y_1, U_1, V_1, angles='xy', scale_units='xy', scale=1)
plt.plot([-6, 12], [-4, 8])
plt.annotate('$v_1=w_1$', xy=(1.5, 1), xytext=(10, -20), textcoords='offset points', size=14, arrowprops=dict(arrowstyle="->"))
plt.annotate('$v_2=w_2$', xy=(-1, 1.5), xytext=(-60, -20), textcoords='offset points', size=14, arrowprops=dict(arrowstyle="->"))
plt.annotate('project line', xy=(4.5, 3), xytext=(-90, 10), textcoords='offset points', size=14, arrowprops=dict(arrowstyle="->"))

ax = plt.gca()
ax.set_xlim(-5, 5)
ax.set_ylim(-4, 4)
ax.set_xlabel("Project Example")

plt.draw()

png

python
plt.close(fig)
plt.close(fig)

从图中可以看到,设输入向量的基为v1,v2v1就在投影上,而v2垂直于投影方向,输出向量的基为w1,w2,而v1=w1,v2=w2。那么如果输入向量为v=c1v1+c2v2,则输出向量为T(v)=c1v1,也就是线性变换去掉了法线方向的分量,输入坐标为(c1,c2),输出坐标变为(c1,0)

找出这个矩阵并不困难,Av=w,则有[1000][c1c2]=[c10]

本例中我们选取的基极为特殊,一个沿投影方向,另一个沿投影法线方向,其实这两个向量都是投影矩阵的特征向量,所以我们得到的线性变换矩阵是一个对角矩阵,这是一组很好的基。

所以,如果我们选取投影矩阵的特征向量作为基,则得到的线性变换矩阵将是一个包含投影矩阵特征值的对角矩阵。

继续这个例子,我们不再选取特征向量作为基,而使用标准基v1=[10],v2=[01],我们继续使用相同的基作为输出空间的基,即v1=w1,v2=w2。此时投影矩阵为P=aaTaTa=[12121212],这个矩阵明显没有上一个矩阵“好”,不过这个矩阵也是一个不错的对称矩阵。

总结通用的计算线性变换矩阵A的方法:

  • 确定输入空间的基v1,v2,,vn,确定输出空间的基w1,w2,,wm
  • 计算T(v1)=a11w1+a21w2++am1wm,求出的系数ai1就是矩阵A的第一列;
  • 继续计算T(v2)=a12w1+a22w2++am2wm,求出的系数ai2就是矩阵A的第二列;
  • 以此类推计算剩余向量直到vn
  • 最终得到矩阵A=[a11a12a1na21a22a2nam1am2amn]

最后我们介绍一种不一样的线性变换,T=ddx

  • 设输入为c1+c2x+c3x3,基为1,x,x2

  • 则输出为导数:c2+2c3x,基为1,x

    所以我们需要求一个从三维输入空间到二维输出空间的线性变换,目的是求导。求导运算其实是线性变换,因此我们只要知道少量函数的求导法则(如sinx,cosx,ex),就能求出它们的线性组合的导数。

    A[c1c2c3]=[c22c3],从输入输出的空间维数可知,A是一个2×3矩阵,A=[010002]

最后,矩阵的逆相当于对应线性变换的逆运算,矩阵的乘积相当于线性变换的乘积,实际上矩阵乘法也源于线性变换。

本站没有备案,因为不需要备案