在这篇文章中,你将了解单值分解(SVD),它是线性代数、数据科学和机器学习的一个重要课题。例如,它被用来计算主成分分析(PCA)。你需要对线性代数的基础知识有一定的了解。
你只能将eigendecomposition应用于正方形矩阵,因为它使用的是单一的变化基础矩阵,这意味着初始向量和转换后的向量是相对于同一基础的。你用 到另一个基去做变换,然后你用
回到初始基。
如同异质分解一样,奇异值分解(SVD)的目的是将矩阵分解成更简单的组成部分:正交矩阵和对角矩阵。
你还看到,你可以将矩阵视为线性变换。矩阵的分解对应于将变换分解为多个子变换。在SVD的情况下,变换被转换为三个更简单的变换。
你将在这里看到三个例子:一个是二维的,一个是比较SVD和eigendecomposition的变换,还有一个是三维的。
二维的例子
你将通过一个自定义的函数matrix_2d_effect() ,看到这些变换的作用。这个函数绘制了单位圆(你可以在《数据科学基本数学》第05章中找到关于单位圆的更多细节),以及由矩阵转换的基向量。
你可以在这里找到这个函数。
为了表示转换前的单位圆和基向量,让我们用这个函数来表示身份矩阵。
I = np.array([ [1, 0],
[0, 1]
])
matrix_2d_effect(I)
# [...] Add labels

图0:单位圆和基础向量
现在让我们用这个函数来看看下面这个矩阵的效果 。
它将绘制出单位圆和经矩阵变换的基向量。
A = np.array([ [2, 5],
[7, 3]
])
matrix_2d_effect(A)
# [...] Add labels

图1:矩阵AA对单位圆和基向量的影响。
图1说明了 对你的二维空间的影响。让我们将其与SVD的矩阵相关的子变换进行比较。
你可以用Numpy计算 的SVD。
U, Sigma, V_transpose = np.linalg.svd(A)
记住,矩阵,
, 和
分别包含左奇异向量、奇异值和右奇异向量。你可以把
作为第一个改变基数的矩阵,
作为这个新基数的线性变换(这个变换应该是一个简单的缩放,因为
是对角线),而UU是另一个改变基数的矩阵。你可以在《数据科学基本数学》第10章中看到,SVD约束两个变化基矩阵
和
是正交的,也就是说,变换将是简单的旋转。
总而言之,对应于矩阵 的变换被分解为一个旋转(或一个反射,或一个反向反射)、一个缩放和另一个旋转(或一个反射,或一个反向反射)。
让我们依次看看每个矩阵的效果。
matrix_2d_effect(V_transpose)

图2:矩阵 对单位圆和基向量的影响。
你可以在图2中看到,单位圆和基向量已经被矩阵 。
matrix_2d_effect(np.diag(Sigma) @ V_transpose)

图3:矩阵 和
的影响。
然后,图3显示, 的效果是单位圆和基向量的缩放。
matrix_2d_effect(U @ np.diag(Sigma) @ V_transpose)

图4:矩阵,
和
的影响。
最后,第三个旋转是由 。你可以在图4中看到,这个变换与矩阵
相关的变换是一样的。你已经将变换分解为一个旋转、一个缩放和一个反射(看一下基向量:已经做了一个反射,因为黄色向量在绿色向量的左边,最初不是这样的)。
与Eigendecomposition的比较
由于矩阵 是方形的,你可以将这个分解与eigendecomposition进行比较,并使用相同类型的可视化。你会得到关于这两种方法之间的区别的见解。
记得在《数据科学基本数学》第09章中,矩阵AA的eigendecomposition是由。
让我们用Numpy计算矩阵 和
(读作 "大写的lambda")。
lambd, Q = np.linalg.eig(A)
注意,由于矩阵 不是对称的,它的特征向量不是正交的(它们的点积不等于零)。
Q[:, 0] @ Q[:, 1]
-0.16609095970747995
让我们看看 对基向量和单位圆的影响。
ax = matrix_2d_effect(np.linalg.inv(Q))

图5:矩阵 的影响。
你可以在图5中看到, ,旋转和缩放了单位圆和基向量。非正交矩阵的变换不是简单的旋转。
下一步是应用 。
ax = matrix_2d_effect(np.diag(lambd) @ np.linalg.inv(Q))

图6:矩阵 和
的效果
,如图6所示,其效果是通过Y轴进行拉伸和反射(黄色向量现在在绿色向量的右边)。
ax = matrix_2d_effect(Q @ np.diag(lambd) @ np.linalg.inv(Q))

图7:矩阵,
和
的效果。
图7中显示的最后一个变换对应于将基础变回初始基础。你可以看到它所导致的结果与与 有关的变换相同:两个矩阵
和
是相似的:它们对应于不同基数下的相同变换。
这突出了eigendecomposition和SVD之间的区别。用SVD,你有三种不同的变换,但其中两种只是旋转。用eigendecomposition,只有两个不同的矩阵,但与 相关的变换不一定是简单的旋转(只有在
是对称的情况下)。
三维实例
由于SVD可以用于非正方形矩阵,所以看看这种情况下的变换是如何分解的很有意思。
首先,非正方形矩阵映射两个具有不同维数的空间。请记住, by
矩阵将一个nn维的空间与一个
-维的空间映射。
让我们以一个3乘2的矩阵为例,将一个二维空间映射到一个三维空间。这意味着输入向量是二维的,输出向量是三维的。以矩阵 。
A = np.array([ [2, 5],
[1, 6],
[7, 3]
])
为了直观地了解 ,你将再次使用二维的单位圆,并计算这个圆上某些点的变换输出。每个点都被看作是一个输入向量,你可以观察到
对这些向量的影响。函数
matrix_3_by_2_effect() 可以在这里找到。
ax = matrix_3_by_2_effect(A)
# [...] Add styles axes, limits etc.

图8:矩阵 :它将单位圆上的向量和基础向量从二维空间转换到三维空间。
如图8所示,二维的单位圆被转化为三维的椭圆。
你可以注意到的是,输出的向量都落在一个二维平面上。这是因为 的等级是2(关于矩阵等级的更多细节见《数据科学基本数学》第7.6节)。
现在你知道了 ,让我们计算一下
的SVD,看看不同矩阵的影响,就像你在二维的例子中做的那样。
U, Sigma, V_transpose = np.linalg.svd(A)
左边奇异向量()的形状是mm乘mm,右边奇异向量(
)的形状是
乘
。矩阵
中有两个奇异值。
与 相关的变换被分解为
的第一次旋转(与
相关,在例子中为
),从
到
的缩放(在例子中为从
到
),以及在输出空间IRmIRm 的旋转(在例子中为
)。
让我们开始检查 对单位圆的影响。在这一步,你停留在二维空间。
matrix_2d_effect(V_transpose)

图9:矩阵的效果 :在这一步,你仍然处于二维空间。
然后,你需要重新塑造 ,因为函数
np.linalg.svd() 给出了一个包含奇异值的一维数组。你想要一个与 相同形状的矩阵:一个3乘2的矩阵来从二维到三维。这个矩阵包含对角线的奇异值,其他的值为零。
让我们来创建这个矩阵。
Sigma_full = np.zeros((A.shape[0], A.shape[1]))
Sigma_full[:A.shape[1], :A.shape[1]] = np.diag(Sigma)
Sigma_full
array([[9.99274669, 0. ],
[0. , 4.91375758],
[0. , 0. ]])
现在你可以加上 的变换,在图10中看到三维的结果。
ax = matrix_3_by_2_effect(Sigma_full @ V_transpose)
# [...] Add styles axes, limits etc.

图10:矩阵 和
的效果:由于
是一个三乘以二的矩阵,它将二维向量转化为三维向量。
最后,你需要操作最后一个变化的基础。你保持在三维状态,因为矩阵是一个3乘3的矩阵。
ax = matrix_3_by_2_effect(U @ Sigma_full @ V_transpose)
# [...] Add styles axes, limits etc.

图11:三个矩阵的效果,
和
: 从三维空间转换到三维空间。
你可以在图11中看到,其结果与矩阵 的相关变换是相同的。
总结

图12:二维空间的SVD。
图12总结了矩阵AA的SVD分解为三个矩阵的过程。与 相关的变换是由三个子变换完成的。符号与图12相同,说明了SVD的几何角度。