矩阵变换
$Ax=y$
矩阵变换有多种解读:
变换:
- 向量x经过矩阵A的变换,变成了向量y
映射:
- 在坐标系A的度量下得到的结果为x,在标准坐标系下度量的结果为y
import numpy as np
import matplotlib.pyplot as plt
import time
import matplotlib.ticker as ticker
from mpl_toolkits.mplot3d import Axes3D
import mpl_toolkits.axisartist as axisartist
def show_change(A,show_eig = False):
lines=np.array( [
[[0,0,0],[0,0,1]],
[[0,0,0],[0,1,0]],
[[0,0,0],[1,0,0]],
[[1,0,0],[1,0,1]],
[[1,0,0],[1,1,0]],
[[0,1,0],[0,1,1]],
[[0,1,0],[1,1,0]],
[[0,0,1],[0,1,1]],
[[0,0,1],[1,0,1]],
[[0,0,1],[0,1,1]],
[[0,0,1],[0,1,1]],
[[1,1,1],[1,1,0]],
[[1,1,1],[1,0,1]],
[[1,1,1],[0,1,1]],
])
%matplotlib notebook
fig = plt.figure()
ax = Axes3D(fig,
azim=23,
)
o = np.array([0,0,0])
x =np.dot(np.array([1,0,0]),A)
y =np.dot(np.array([0,1,0]) ,A)
z =np.dot(np.array([0,0,1]) ,A)
length = 1.2
xs = [l[0] for l in lines]
ys = [l[1] for l in lines]
for l in lines:
ax.plot( *zip(l[0],l[1]),color='c',ls='-.')
for l in lines:
s1 = np.dot(A,l[0])
s2 = np.dot(A,l[1])
ax.plot( *zip(s1,s2),color='r',ls='--')
size = (-1,2)
ax.set_xlim3d(*size)
ax.set_ylim3d(*size)
ax.set_zlim3d(*size)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')
if show_eig:
a,b = np.linalg.eig(A)
o = [0,0,0]
ax.plot(*zip(o,b[:,0]),color='b',ls='-',lw=2)
ax.plot(*zip(o,b[:,1]),color='b',ls='-',lw=2)
ax.plot(*zip(o,b[:,2]),color='b',ls='-',lw=2)
new_b = np.dot(A,b)
ax.plot(*zip(o,new_b[:,0]),color='y',ls='-.',lw=1)
ax.plot(*zip(o,new_b[:,1]),color='y',ls='-.',lw=1)
ax.plot(*zip(o,new_b[:,2]),color='y',ls='-.',lw=1)
print('特征值:\n%s \n特征向量:\n%s' %(a,b))
A = np.array(
[[1,0,0],
[0,1,0],
[0,0,1]]
)
show_change(A)
<IPython.core.display.Javascript object>
典型的对角矩阵
- 沿着坐标轴的伸缩
- 沿着y轴压缩0.5
- 沿着z轴增长2 倍
- 因此立方体的大小变成了 1 * 0.5 * 2 = 1。它是对角线的乘积,也就是det A
A = np.array([[1,0,0]
,[0,.5,0],
[0,0,2]])
show_change(A)
[[1. 0. 0. ]
[0. 0.5 0. ]
[0. 0. 2. ]].[1 1 1]=[1. 0.5 2. ]
<IPython.core.display.Javascript object>
如果对角线元素中有0
- x轴方向直接被压扁
- 因此立方体的大小变成了 0,det A = 0
A = np.array([[0,0,0],[0,.5,0],[0,0,2]])
show_change(A)
[[0. 0. 0. ]
[0. 0.5 0. ]
[0. 0. 2. ]].[1 1 1]=[0. 0.5 2. ]
<IPython.core.display.Javascript object>
如果对角线元素中有负数
- y 轴上线颠倒
- det A < 0
A = np.array([[1,0,0],[0,-.5,0],[0,0,2]])
show_change(A)
[[ 1. 0. 0. ]
[ 0. -0.5 0. ]
[ 0. 0. 2. ]].[1 1 1]=[ 1. -0.5 2. ]
<IPython.core.display.Javascript object>
非对角矩阵
- 发生了倾斜
- 平行关系保持不变
- 空间中的某些向量没有发生旋转而是只发生了伸缩,在图中用蓝色表示的向量经过A的变换后称为了黄色的向量。 这个压缩率就是特征值。
A = np.array([[2,-0.5,-0.5],[-0.5,2,-0.5],[-0.5,-0.5,2]])
show_change(A,show_eig=True)
<IPython.core.display.Javascript object>
特征值:
[2.5 1. 2.5]
特征向量:
[[ 0.81649658 -0.57735027 0.47168785]
[-0.40824829 -0.57735027 -0.81302061]
[-0.40824829 -0.57735027 0.34133277]]
观察秩和可逆性
- 下面的矩阵把原本的正方体变化为了一个平面,体积为零因此 detA = 0
- 维度从三维降低为两维,因此rand A = 2
- 有一个特征向量被变换为了一个点,因次它对应的特征值为0
- 由于被压缩到了一个平面上,无法推测 A 的逆变化,因此 A 的逆矩阵不存在
x = np.array([1,1,1])
A = np.array([[2,2,2],[1,1,1],[1,1,2]])
y=np.dot(A,x)
print('{}.{}={}'.format(A,x,y))
a,b = np.linalg.eig(A)
print('特征值: %s' %a)
print('特征向量:%s' %b)
show_change(A,show_eig=True)
[[2 2 2]
[1 1 1]
[1 1 2]].[1 1 1]=[6 3 4]
特征值: [ 4.30277564e+00 -3.10974594e-16 6.97224362e-01]
特征向量:[[-7.72827507e-01 -7.07106781e-01 -6.23093003e-01]
[-3.86413754e-01 7.07106781e-01 -3.11546502e-01]
[-5.03410424e-01 -8.00981857e-17 7.17421694e-01]]
<IPython.core.display.Javascript object>
特征值:
[ 4.30277564e+00 -3.10974594e-16 6.97224362e-01]
特征向量:
[[-7.72827507e-01 -7.07106781e-01 -6.23093003e-01]
[-3.86413754e-01 7.07106781e-01 -3.11546502e-01]
[-5.03410424e-01 -8.00981857e-17 7.17421694e-01]]
观察行列的交替性质
对比下面两个结果可以看出,如果交换行列式的列或者行,那么空间发生了翻转,但是体积不变,因此
det(A) = -det(A_hat)
A = np.array(
[
[1,0,0],
[0,1,0],
[0,0,0],
])
show_change(A,show_eig=True)
<IPython.core.display.Javascript object>
特征值:
[1. 1. 0.]
特征向量:
[[1. 0. 0.]
[0. 1. 0.]
[0. 0. 1.]]
A_hat = np.array(
[
[0,1,0],
[1,0,0],
[0,0,0],
])
show_change(A_hat,show_eig=True)
<IPython.core.display.Javascript object>
特征值:
[ 1. -1. 0.]
特征向量:
[[ 0.70710678 -0.70710678 0. ]
[ 0.70710678 0.70710678 0. ]
[ 0. 0. 1. ]]