Featured image of post SVD 与 NMF:矩阵分解的两种方法

SVD 与 NMF:矩阵分解的两种方法

本文将深入探讨两种流行的矩阵分解技术:奇异值分解(SVD)和非负矩阵分解(NMF)。我们将详细解析它们的理论基础,以及如何在实际问题中应用它们。

# SVD 与 NMF:矩阵分解的两种方法

在数据科学中,矩阵分解技术是一种强大的工具,可以用于各种应用,如推荐系统、图像处理和自然语言处理。在这篇文章中,我们将深入探讨两种流行的矩阵分解技术:奇异值分解(SVD)和非负矩阵分解(NMF)。我们将详细解析它们的理论基础,以及如何在实际问题中应用它们。

# 一、奇异值分解(SVD)

奇异值分解是一种在线性代数中常用的矩阵分解方法。对于给定的 $m\times n$ 矩阵 A,我们可以将其分解为三个矩阵的乘积:

$$ A = U\Sigma V^T $$

这里,$U$ 是一个 $m\times m$ 的正交矩阵,$V$ 是一个 $n\times n$ 的正交矩阵,$\Sigma$ 是一个 $m\times n$ 的对角矩阵。对角线上的元素称为奇异值,它们是 $A^T A$ 的特征值的平方根。它们是按降序排列的,代表了原始矩阵中的“能量”或信息量。。我们可以将奇异值分解看作是一种特征值分解,其中 $U$ 和 $V$ 是特征向量,$\Sigma$ 是特征值的对角矩阵。

计算 SVD 的基本步骤如下:

  1. 构造矩阵 A 的 Gram 矩阵:对于给定的 $m\times n$ 矩阵 A,我们可以构造一个 $n\times n$ 的矩阵 $A^T A$,称为 A 的 Gram 矩阵。Gram 矩阵是一个对称半正定矩阵,因此它的特征值都是非负的。
  2. 计算 Gram 矩阵的特征值和特征向量:我们可以使用任何标准的特征值分解算法来计算 Gram 矩阵的特征值和特征向量。这些特征值就是 A 的奇异值的平方,特征向量则构成了右奇异向量和左奇异向量。我们将特征值按降序排列,将特征向量按相同的顺序排列。
  3. 构造奇异值矩阵 $\Sigma$ :我将特征值的平方根按照从大到小的顺序排列在对角线上,构成 $m\times n $ 的对角矩阵 $\Sigma$ 。
  4. 构造左奇异向量矩阵 $U$ 和右奇异向量矩阵 $V$ :将对应于特征值的特征向量按照特征值的顺序排列,构成 $n\times n$ 的矩阵 $V$ 和 $m\times m$ 的矩阵 $U$ 。这些特征向量是标准化的,即它们的长度为 1,并且互相正交。

这样,我们就得到了 A 的奇异值分解。在 Python 中,我们可以使用 NumPy 的np.linalg.svd 函数来计算 SVD,这个函数会自动执行上述步骤,并返回 $ U, \Sigma, V^T $ 。如下所示:

import numpy as np
U, S, Vt = np.linalg.svd(A)

需要注意的是,虽然理论上 SVD 总是存在的,但在实际计算中可能会遇到数值稳定性的问题。此外,对于非常大的矩阵,计算 SVD 可能会非常耗时。在这些情况下,我们可能需要使用一些更高效的算法或者近似方法,如随机 SVD。

SVD 的一个重要应用是在推荐系统中进行矩阵补全。在推荐系统中,我们通常有一个用户-商品评分矩阵,但这个矩阵通常是非常稀疏的,因为大多数用户只评价了少数商品。SVD 可以用于预测用户对未评价商品的评分,从而提供个性化的推荐。

# 二、非负矩阵分解(NMF)

由于维度的复杂性和维度诅咒,直接处理高维数据需要大量的计算资源。非负矩阵分解(NMF)作为一种降维技术被提出,在图像处理中得到了重要的应用。通过采用 NMF,非负的高维矩阵可以被分解成两个非负的低维矩阵,其中一个包括列向量,可以被视为数据空间中的基向量,另一个则包含缩放这些基向量的系数行。此外,NMF 也可用于文本数据处理。我们可以检查系数矩阵中的每一列,并确定具有最大系数的行号,其中行号表示原始矩阵中各列的聚类 ID。这种聚类特性意味着 NMF 可以用于数据聚类。

NMF 对矩阵的元素有一个额外的非负约束。对于给定的 $K\times N$ 非负矩阵 $M\in R^{K\times N}$ ,我们可以找到两个非负矩阵 $W$ 和 $H$ ,使得 $M\approx WH$ 。其中 $W\in R^{K\times r}$ 和 $H\in R^{r\times N}$ 是两个非负矩阵,即 $W\geq 0$ 和 $H\geq 0$ 。矩阵 $W$ 代表捕捉数据特征的基向量,而矩阵 $H$ 是表示每个基向量对重建原始数据的贡献的权重。NMF 中的非负约束允许学习整体数据的部分表征,而这种约束在 SVD 中是不允许的。为了找到 $M\approx WH$的近似解,定义基于欧氏距离的成本函数来量化近似的质量,即:

$$ Q=\Vert M-WH\Vert^2_F=\sum_{i,j}(M_{ij}-(WH)_{ij})^2 $$

由于成本函数 $Q$ 在 $W$ 和 $H$ 中都是非凸的,所以在求解 $Q$ 的最小值过程中找到全局最小值是不现实的。一些数值优化技术,如梯度下降和共轭梯度,可以被用来寻找局部最小值。然而,梯度下降的收敛速度很慢,共轭梯度的实现很复杂。此外,基于梯度的方法对步长的参数设置很敏感,这对现实应用来说并不方便。为此,可以利用 $W$ 和 $H$ 的 multiplicative update rules,作为收敛速度和实现复杂性之间的折中方案,具体如下:

$$ H_{aj} \leftarrow H_{aj} \frac{W^T M_{aj}}{W^T W H_{aj}}, W_{ia} \leftarrow W_{ia} \frac{M H^T_{ia}}{W H H^T_{ia}} $$

其中,矩阵 $W$ 和 $H$ 可以被随机初始化,然后通过迭代更新来优化 $Q$ 。这些更新规则可以保证 $Q$ 在每次迭代中都会减少,因此可以保证收敛到局部最小值。

在 Python 中,我们可以使用sklearn.decomposition.NMF 类来计算 NMF。如下所示:

from sklearn.decomposition import NMF
model = NMF(n_components=2, init='random', random_state=0)
W = model.fit_transform(X)
H = model.components_

# 三、SVD 与 NMF 的比较

虽然 SVD 和 NMF 都是矩阵分解技术,但它们有一些重要的区别。

  1. 数据类型和约束:SVD 可以应用于任何矩阵,而 NMF 只能应用于非负矩阵。其次,SVD 提供了一种最优的低秩近似,而 NMF 则没有这种保证。然而,NMF 的非负约束使得它的分解更具解释性,这在许多应用中是非常有用的。
  2. 分解的解释性:虽然 SVD 和 NMF 都可以将原始矩阵分解为一些基本的“构成元素”,但 NMF 的分解通常更具解释性。这是因为 NMF 的非负约束使得分解的结果更容易解释和理解。在许多应用中,如主题模型或社区发现,NMF 的分解可以直接解释为数据的一些基本模式或特征。
  3. 优化和稳定性:SVD 的优化问题有闭式解,这意味着我们可以直接计算出最优解。而 NMF 的优化问题通常需要使用迭代方法来求解,如梯度下降或坐标下降。这使得 NMF 的计算过程可能更复杂,而且可能需要更多的时间。而且 SVD 的结果是唯一的(除了奇异向量的符号),而 NMF 的结果可能依赖于初始化和优化算法。这意味着对同一个数据集,NMF 可能会给出不同的结果。
  4. 近似质量:SVD 提供了一种最优的低秩近似,即它可以找到最接近原始矩阵的低秩矩阵。而 NMF 则没有这种保证,它的近似质量可能会比 SVD 差。然而,NMF 的非负约束使得它的近似可能更符合实际的需求,尤其是在那些原始数据是非负的情况下。
  5. 计算复杂性:SVD 和 NMF 的计算复杂性也有所不同。对于一个 $m\times n$ 的矩阵,SVD 的计算复杂性大约为 $\mathbf{O}(\min {m^2n, mn^2})$ ,而 NMF 的计算复杂性则取决于迭代次数和所选的优化算法。在实践中,NMF 通常比 SVD 更慢,但也有一些高效的 NMF 算法可以缩短计算时间。

总的来说,SVD 和 NMF 各有优势,选择使用哪一种技术取决于具体的应用和需求。

# 四、实战:图像压缩

让我们通过一个实战演示来看看如何使用 SVD 和 NMF 进行图像压缩。我们将使用 Python 的 NumPy 和 scikit-learn 库来执行这些任务。

首先,我们需要导入必要的库,并加载一张图像:

import numpy as np
from sklearn.decomposition import NMF
from PIL import Image

# 加载图像
img = Image.open('image.jpg')
width, height = img.size
img = np.array(img)
r, g, b = img[:, :, 0], img[:, :, 1], img[:, :, 2]
img_matrix = []
img_matrix.extend([r.flatten(), g.flatten(), b.flatten()])

M = np.array(img_matrix).T

然后,我们可以使用 NumPy 的np.linalg.svd 函数来进行 SVD,得到 $U, S, V^T$ :

# 执行 SVD
U, s, Vt = np.linalg.svd(M, full_matrices=False)

我们可以选择前 $r$ 个奇异值和对应的 $U$ 和 $V^T$ 的列来进行低秩近似:

d = 16
U_d = U[:, :d]
s_d = s[:d]
Vt_d = Vt[:d, :]
M_d = U_d @ np.diag(s_d) @ Vt_d

r, g, b = M_d[:, 0], M_d[:, 1], M_d[:, 2]
img = np.dstack((r, g, b)).reshape(height, width, 3)
img[img < 0] = 0
img[img > 255] = 255
img = Image.fromarray(np.uint8(img), mode='RGB')
img.show()

同样,我们也可以使用 scikit-learn 的 NMF 类来进行 NMF:

# 执行 NMF
model = NMF(n_components=16, init='random', random_state=0)
W = model.fit_transform(M)
H = model.components_

M_d = W @ H
r, g, b = M_d[:, 0], M_d[:, 1], M_d[:, 2]
img = np.dstack((r, g, b)).reshape(height, width, 3)
img[img < 0] = 0
img[img > 255] = 255
img = Image.fromarray(np.uint8(img), mode='RGB')
img.show()

最后,我们可以比较原始图像和重构图像的差异,以及 SVD 和 NMF 的压缩效果。这种压缩方法的优点是可以大大减少存储和传输图像所需的数据量,而且如果选择的秩 r 足够大,压缩后的图像的质量也可以接受。

# 五、结论

总的来说,SVD 和 NMF 都是强大的矩阵分解技术,它们在许多数据科学应用中都有广泛的用途。虽然 SVD 提供了一种最优的低秩近似,但 NMF 的非负约束使得它的分解更具解释性。在选择使用哪一种技术时,我们需要考虑我们的具体需求,以及我们的数据是否满足这些技术的要求。

# 参考资料

[1] Lee, Daniel, and H. Sebastian Seung. “Unsupervised learning by convex and conic coding. " Advances in neural information processing systems 9 (1996).

[2] Lee, Daniel D., and H. Sebastian Seung. “Learning the parts of objects by non-negative matrix factorization.” Nature 401.6755 (1999): 788-791.

[3] Lee, Daniel, and H. Sebastian Seung. “Algorithms for non-negative matrix factorization. " Advances in neural information processing systems 13 (2000).

本博客已稳定运行
总访客数: Loading
总访问量: Loading
发表了 73 篇文章 · 总计 323.73k

使用 Hugo 构建
主题 StackJimmy 设计
基于 v3.27.0 分支版本修改