Kogbetliantz迭代算法计算矩阵奇异值
1. 问题描述
假设我们有一个任意 \(m \times n\) 实矩阵 \(A\),想计算它的所有奇异值(即矩阵 \(A^T A\) 的特征值的平方根)。
一种经典方法是Kogbetliantz迭代算法,也称为双对角化SVD算法的变体。它通过对矩阵反复进行平面旋转(Jacobi旋转),逐步将矩阵对角化,从而直接得到奇异值,而无需先形成 \(A^T A\)。
这个算法特别适合中小规模的稠密矩阵,且数值稳定性较好。
2. 算法基本思想
Kogbetliantz算法是双边Jacobi SVD算法的一种形式。其核心思想是:
- 对 \(A\) 交替左乘和右乘正交矩阵(Givens旋转矩阵),每次消除一对非对角线元素。
- 通过反复的相似变换,使 \(A\) 逐渐趋近于对角矩阵 \(\Sigma\)(其对角线就是奇异值)。
- 最终得到分解:
\[ A = U \Sigma V^T \]
其中 \(U\) 和 \(V\) 是左右奇异向量构成的矩阵。
3. 核心步骤详解
步骤1:问题转换
给定矩阵 \(A \in \mathbb{R}^{m \times n}\),假设 \(m \ge n\)(若 \(m < n\),可对 \(A^T\) 计算)。
目标是找到正交矩阵 \(U\) 和 \(V\),使得:
\[U^T A V = \Sigma = \text{diag}(\sigma_1, \dots, \sigma_n) \in \mathbb{R}^{m \times n} \]
这里 \(\Sigma\) 的上半部分是一个 \(n \times n\) 对角矩阵,下方是零矩阵。
步骤2:基本旋转操作
Kogbetliantz每次选取两个行列索引 \((p, q)\)(\(1 \le p < q \le n\)),构造一对Givens旋转矩阵 \(J_L\) 和 \(J_R\):
- 左乘 \(J_L^T\) 作用于第 \(p\) 行和第 \(q\) 行,使矩阵的 \((p, q)\) 位置元素为零。
- 右乘 \(J_R\) 作用于第 \(p\) 列和第 \(q\) 列,使矩阵的 \((q, p)\) 位置元素为零。
具体来说:
- 设当前矩阵为 \(B\)(初始时 \(B = A\))。
- 取子矩阵:
\[\begin{pmatrix} b_{pp} & b_{pq} \\ b_{qp} & b_{qq} \end{pmatrix} \]
目标是将其对角化,即通过正交变换使其非对角线元素为零。
步骤3:计算旋转参数
对于 \(2 \times 2\) 子矩阵:
\[S = \begin{pmatrix} b_{pp} & b_{pq} \\ b_{qp} & b_{qq} \end{pmatrix} \]
计算其SVD(对 \(2 \times 2\) 矩阵可直接解析求解):
- 找到正交矩阵 \(P, Q\) 使得 \(P^T S Q = D = \text{diag}(d_1, d_2)\)。
实际上,可以这样计算:
- 计算对称矩阵 \(S^T S\) 的特征值和特征向量:
\[S^T S = \begin{pmatrix} b_{pp}^2 + b_{qp}^2 & b_{pp}b_{pq} + b_{qp}b_{qq} \\ b_{pp}b_{pq} + b_{qp}b_{qq} & b_{pq}^2 + b_{qq}^2 \end{pmatrix} \]
- 对 \(S^T S\) 做Jacobi旋转使其对角化,得到旋转矩阵 \(Q\)。
- 类似对 \(S S^T\) 处理得到 \(P\)。
但更常用的简化做法是:
- 直接对 \(S\) 做双边Jacobi旋转:
取左旋 \(J_L\) 和右旋 \(J_R\) 使得:
\[ J_L^T S J_R = \text{diag}(d_1, d_2) \]
参数可通过解一个小型优化问题得到,其闭式解类似于对 \(2 \times 2\) 矩阵做SVD的显式公式。
步骤4:应用旋转到整个矩阵
- 左乘 \(J_L^T\) 作用于 \(B\) 的第 \(p\) 行和第 \(q\) 行,更新 \(B\) 的这两行。
- 右乘 \(J_R\) 作用于 \(B\) 的第 \(p\) 列和第 \(q\) 列,更新 \(B\) 的这两列。
- 同时累计左右变换到 \(U\) 和 \(V\) 中:
\[ U := U \cdot J_L, \quad V := V \cdot J_R \]
初始时 \(U = I_m\), \(V = I_n\)。
步骤5:迭代策略
通常按循环顺序遍历所有索引对 \((p, q)\):
- 经典顺序:\((1,2), (1,3), \dots, (1,n), (2,3), \dots, (n-1,n)\)。
- 重复扫描直到所有非对角线元素小于某个阈值 \(\epsilon\)。
步骤6:收敛判定
计算非对角线范数:
\[\text{off}(B) = \sqrt{ \sum_{i \neq j} b_{ij}^2 } \]
当 \(\text{off}(B) < \epsilon \cdot \|B\|_F\) 时停止。此时 \(B\) 的对角线元素即为奇异值的近似。
4. 数值注意事项
- 每次旋转只改变两行和两列,因此计算量为 \(O(m+n)\) 每次旋转,总体为 \(O(k \cdot (m+n))\),k 是迭代次数。
- 对大型矩阵,Kogbetliantz通常不如分而治之的双对角化SVD快,但对中小矩阵是稳定且精确的。
- 需注意累积正交变换时的数值误差,但Givens旋转本身是数值稳定的。
5. 示例(2×2矩阵单步演示)
设:
\[A = \begin{pmatrix} 3 & 4 \\ 1 & 2 \end{pmatrix} \]
目标:一次Kogbetliantz迭代将其对角化。
- 选 \((p,q) = (1,2)\)。
- 对 \(2 \times 2\) 矩阵自身做SVD:
- 计算旋转矩阵 \(P, Q\) 使 \(P^T A Q\) 对角。
- 这里可直接用解析SVD公式(或2×2 Jacobi SVD)。
- 对 \(A\) 应用 \(P, Q\) 得到对角矩阵 \(\Sigma\),其对角线即为奇异值。
实际计算(简略):
- 奇异值约为 \(\sigma_1 \approx 5.398, \sigma_2 \approx 0.3715\)。
- 一次旋转即完成对角化(因为矩阵本身是2×2)。
6. 总结
Kogbetliantz算法通过一系列双边Jacobi旋转,逐步将矩阵对角化,直接得到奇异值。它避免了显式计算 \(A^T A\),因此数值稳定性优于先求特征值的方法。虽然对大规模矩阵较慢,但它是理解SVD迭代计算的一个经典算法,并且在需要高精度的小矩阵场景中仍有应用价值。