线性代数弥合了理论与概念实际实施之间的差距。对线性代数的掌握理解打开了我们认为无法理解的机器学习算法的大门。线性代数的一种这样的用途是奇异值分解(SVD)用于降维。
矩阵的秩
矩阵的秩是矩阵中线性无关的行(或列)向量的最大数量。如果向量r不能表示为r1和r2的线性组合,则称向量r与向量r1和r2线性无关。
SVD
SVD将矩阵分解为3个矩阵的乘积,如下所示:
如果A是m x n矩阵:
- U是左奇异向量的m×m矩阵
- S是以递减顺序排列的奇异值的m×n对角矩阵
- V是右奇异向量的n×n矩阵
为什么SVD用于降维?
你可能想知道我们为什么要经历这种看似辛苦的分解。可以通过分解的替代表示来理解原因。见下图:
分解允许我们将原始矩阵表示为低秩矩阵的线性组合。
在实际应用中,你将观察到的只有前几个(比如k)奇异值很大。其余的奇异值接近于零。因此,可以忽略除前几个之外而不会丢失大量信息。
总结以下3点:
- 使用SVD,我们能够用3个较小的矩阵U,S和V表示我们的大矩阵A
- 这在大型计算中很有用
- 我们可以得到A的k-秩近似。为此,选择前k个奇异值并相应地截断3个矩阵。
3种在Python中使用SVD的方法:
1. numpy中的SVD
import numpy as np
from numpy.linalg import svd
# 定义二维矩阵
A = np.array([[4, 0], [3, -5]])
U, S, VT = svd(A)
print("Left Singular Vectors:")
print(U)
print("Singular Values:")
print(np.diag(S))
print("Right Singular Vectors:")
print(VT)
# 检查分解是否正确
# @ 表示矩阵乘法
print(U @ np.diag(S) @ VT)
2. scikit-learn中的Truncated SVD
n_components参数指定所需的特征数量输出。n_components应严格小于输入矩阵中的特征数:
import numpy as np
from sklearn.decomposition import TruncatedSVD
A = np.array([[-1, 2, 0], [2, 0, -2], [0, -2, 1]])
print("Original Matrix:")
print(A)
svd = TruncatedSVD(n_components = 2)
A_transf = svd.fit_transform(A)
print("Singular values:")
print(svd.singular_values_)
print("Transformed Matrix after reducing to 2 features:")
print(A_transf)
3. scikit-learn中的Randomized SVD
import numpy as np
from sklearn.utils.extmath import randomized_svd
A = np.array([[-1, 2, 0], [2, 0, -2], [0, -2, 1]])
u, s, vt = randomized_svd(A, n_components = 2)
print("Left Singular Vectors:")
print(u)
print("Singular Values:")
print(np.diag(s))
print("Right Singular Vectors:")
print(vt)
奇异值分解(SVD)的应用
我们将在此处遵循自上而下的方法并首先讨论SVD应用。如果你对它如何工作感兴趣的,我在下面会讲解SVD背后的数学原理。现在你只需要知道四点来理解这些应用:
- SVD是将矩阵A分解为3个矩阵--U,S和V。
- S是奇异值的对角矩阵。将奇异值视为矩阵中不同特征的重要性值
- 矩阵的秩是对存储在矩阵中的独特信息的度量。秩越高,信息越多
- 矩阵的特征向量是数据的最大扩展或方差的方向
在大多数应用中,我们希望将高秩矩阵缩减为低秩矩阵,同时保留重要信息。
1. SVD用于图像压缩
2. SVD用于图像恢复
3. SVD用于特征脸
4. SVD用于谱聚类
5. SVD用于从视频中删除背景
参考:
【1】https://zhuanlan.zhihu.com/p/80372137?utm_source=wechat_session
【2】https://zhuanlan.zhihu.com/p/42896542
【3】https://www.bilibili.com/video/av36965169/