5.6 奇异值分解 奇异值分解 (SVD) 具有十分广泛的应用背景, 因此, 如何更好更快地计算一个给定矩阵的 SVD 是科学与工程计算领域中的一个热门研究课题, 吸引了众多专家进行这方面的研究, 也涌现出了许多奇妙的方法. 本章主要介绍计算 SVD 的常用算法.
对任意矩阵 A ∈ R m × n A \in \mathbb{R}^{m \times n} A ∈ R m × n , 其奇异值与对称矩阵 A T A , A A T A^{\mathrm{T}}A, AA^{\mathrm{T}} A T A , A A T 和 [ 0 A T A 0 ] \left[ \begin{array}{cc}0 & A^{\mathrm{T}} \\ A & 0 \end{array} \right] [ 0 A A T 0 ] 的特征值是是密切相关的, 故理论上计算对称特征值的算法都可以用于计算奇异值. 但在实际计算中, 我们需要对算法进行优化, 使得计算过程更加高效, 计算结果更加准确.
当前的SVD算主要可分为两类[33]:一类是基于二对角化的算法,包括Golub-Kahan SVD算法(即QR算法)、DC算法、dqds算法、对分法、MRRR算法等;另一类是Jacobi算法,包括双边Jacobi算法和单边Jacobi算法.
关于SVD的相关参考资料 J. Dongarra, et al., The Singular Value Decomposition: Anatomy of Optimizing an Algorithm for Extreme Scale, 2018. [33]
5.6.1 二对角化 基于二对角化的SVD算法通常分为以下三个步骤:
将 A A A 二对角化: B = U 1 ⊤ A V 1 B = U_{1}^{\top} A V_{1} B = U 1 ⊤ A V 1 , 其中 B B B 为上二对角矩阵, U 1 , V 1 U_{1}, V_{1} U 1 , V 1 为正交阵;
计算 B B B 的SVD: B = U 2 Σ V 2 T B = U_{2}\Sigma V_{2}^{\mathsf{T}} B = U 2 Σ V 2 T , 其中 Σ \Sigma Σ 为对角阵, U 2 , V 2 U_{2}, V_{2} U 2 , V 2 为正交阵;
合并得到 A A A 的SVD: A = U 1 B V 1 T = ( U 1 U 2 ) Σ ( V 1 V 2 ) T A = U_{1}BV_{1}^{\mathsf{T}} = (U_{1}U_{2})\Sigma (V_{1}V_{2})^{\mathsf{T}} A = U 1 B V 1 T = ( U 1 U 2 ) Σ ( V 1 V 2 ) T .
我们知道, 对称矩阵可以通过一系列 Householder 变换转化为对称三对角矩阵. 对于一般矩阵 A ∈ R m × n A \in \mathbb{R}^{m \times n} A ∈ R m × n , 我们也可以通过 Householder 变换, 将其转化为二对角矩阵, 即计算正交矩阵 U 1 U_{1} U 1 和 V 1 V_{1} V 1 使得
U 1 ⊤ A V 1 = B , (5.9) U _ {1} ^ {\top} A V _ {1} = B, \tag {5.9} U 1 ⊤ A V 1 = B , ( 5.9 ) 其中 B B B 是一个实 (上) 二对角矩阵. 这个过程就称为二对角化
需要注意的是, 与对称矩阵的对称三对角化不同, A A A 与 B B B 是不相似的.
设 A ∈ R m × n A\in \mathbb{R}^{m\times n} A ∈ R m × n ,二对角化过程大致如下:
(1) 首先构造一个 Householder 矩阵 H 1 ∈ R m × m H_{1} \in \mathbb{R}^{m \times m} H 1 ∈ R m × m , 使得 H 1 A H_{1}A H 1 A 的第一列除第一个元素外, 其它分量都为零, 即
H 1 A = [ ∗ ∗ ∗ … ∗ 0 ∗ ∗ … ∗ 0 ∗ ∗ … ∗ ⋮ ⋮ ⋮ ⋮ 0 ∗ ∗ … ∗ ] . H _ {1} A = \left[ \begin{array}{c c c c c} * & * & * & \dots & * \\ 0 & * & * & \dots & * \\ 0 & * & * & \dots & * \\ \vdots & \vdots & \vdots & & \vdots \\ 0 & * & * & \dots & * \end{array} \right]. H 1 A = ∗ 0 0 ⋮ 0 ∗ ∗ ∗ ⋮ ∗ ∗ ∗ ∗ ⋮ ∗ … … … … ∗ ∗ ∗ ⋮ ∗ . (2) 再构造一个 Householder 矩阵 H ~ 1 ∈ R ( n − 1 ) × ( n − 1 ) \tilde{H}_1 \in \mathbb{R}^{(n-1) \times (n-1)} H ~ 1 ∈ R ( n − 1 ) × ( n − 1 ) , 把 H 1 A H_1A H 1 A 的第一行的第 3 至第 n n n 个元素化为零, 即
H 1 A [ 1 0 0 H ~ 1 ] = [ ∗ ∗ 0 … 0 0 ∗ ∗ … ∗ 0 ∗ ∗ … ∗ ⋮ ⋮ ⋮ ⋮ 0 ∗ ∗ … ∗ ] . H _ {1} A \left[ \begin{array}{c c} 1 & 0 \\ 0 & \tilde {H} _ {1} \end{array} \right] = \left[ \begin{array}{c c c c c} * & * & 0 & \dots & 0 \\ 0 & * & * & \dots & * \\ 0 & * & * & \dots & * \\ \vdots & \vdots & \vdots & & \vdots \\ 0 & * & * & \dots & * \end{array} \right]. H 1 A [ 1 0 0 H ~ 1 ] = ∗ 0 0 ⋮ 0 ∗ ∗ ∗ ⋮ ∗ 0 ∗ ∗ ⋮ ∗ … … … … 0 ∗ ∗ ⋮ ∗ . (3) 重复上面的过程, 直到把 A A A 最终化为二对角矩阵.
有了分解 (5.6) 以后, 我们可得
A T A = ( U 1 B V 1 T ) T U 1 B V 1 T = V 1 B T B V 1 T , A ^ {\mathsf {T}} A = \left(U _ {1} B V _ {1} ^ {\mathsf {T}}\right) ^ {\mathsf {T}} U _ {1} B V _ {1} ^ {\mathsf {T}} = V _ {1} B ^ {\mathsf {T}} B V _ {1} ^ {\mathsf {T}}, A T A = ( U 1 B V 1 T ) T U 1 B V 1 T = V 1 B T B V 1 T , 即 V 1 T A T A V 1 = B T B . V_{1}^{\mathsf{T}}A^{\mathsf{T}}AV_{1} = B^{\mathsf{T}}B. V 1 T A T A V 1 = B T B . 由于 B T B B^{\mathsf{T}}B B T B 是对称三对角的, 所以这就相当于将 A T A A^{\mathsf{T}}A A T A 三对角化.
整个二对角化过程的运算量约为 4 m n 2 + 4 m 2 n − 4 n 3 / 3 4mn^{2} + 4m^{2}n - 4n^{3} / 3 4 m n 2 + 4 m 2 n − 4 n 3 /3 , 若不需要计算 U 1 U_{1} U 1 和 V 1 V_{1} V 1 , 则运算量约为 4 m n 2 − 4 n 3 / 3 4mn^{2} - 4n^{3} / 3 4 m n 2 − 4 n 3 /3 .
二对角矩阵的奇异值分解 设 B ∈ R n × n B \in \mathbb{R}^{n \times n} B ∈ R n × n 是一个二对角矩阵
B = [ a 1 b 1 ⋱ ⋱ ⋱ b n − 1 a n ] . (5.10) B = \left[ \begin{array}{c c c c} a _ {1} & b _ {1} & & \\ & \ddots & \ddots & \\ & & \ddots & b _ {n - 1} \\ & & & a _ {n} \end{array} \right]. \tag {5.10} B = a 1 b 1 ⋱ ⋱ ⋱ b n − 1 a n . ( 5.10 ) 我们假定二对角矩阵的元素都非负, 即 a k , b k ≥ 0 a_{k}, b_{k} \geq 0 a k , b k ≥ 0 , 否则可以通过在左右分别乘以一个正交矩阵来实现 (见习题 5.8). 下面三种方法均可将计算 B B B 的 SVD 转化成计算对称三对角矩阵的特征分解:
(1) 构造增广矩阵 T = [ 0 B T B 0 ] T = \left[ \begin{array}{cc}0 & B^{\mathsf{T}}\\ B & 0 \end{array} \right] T = [ 0 B B T 0 ] , 取置换矩阵 P = [ e 1 , e n + 1 , e 2 , e n + 2 , … , e n , e 2 n ] P = [e_1,e_{n + 1},e_2,e_{n + 2},\ldots ,e_n,e_{2n}] P = [ e 1 , e n + 1 , e 2 , e n + 2 , … , e n , e 2 n ] , 则 T p s = P T T P T_{ps} = P^{\mathsf{T}}TP T p s = P T TP 是对称三对角矩阵, 且主对角线元素全为 0, 次对角线元素为 a 1 , b 1 , a 2 , b 2 , … , a n − 1 a_1,b_1,a_2,b_2,\ldots ,a_{n - 1} a 1 , b 1 , a 2 , b 2 , … , a n − 1 , b n − 1 , a n b_{n - 1},a_{n} b n − 1 , a n . 设 ( λ i , x i ) (\lambda_i,x_i) ( λ i , x i ) 是 T p s T_{ps} T p s 的一个特征对, 则
λ i = ± σ i , P x i = 1 2 [ v i ± u i ] , \lambda_ {i} = \pm \sigma_ {i}, \quad P x _ {i} = \frac {1}{\sqrt {2}} \left[ \begin{array}{c} v _ {i} \\ \pm u _ {i} \end{array} \right], λ i = ± σ i , P x i = 2 1 [ v i ± u i ] , 其中 σ i \sigma_{i} σ i 为 B B B 一个奇异值, u i u_{i} u i 和 v i v_{i} v i 分别为对应的左和右奇异向量.
(2) 令 T B B ⊺ = B B ⊺ T_{BB^{\intercal}} = BB^{\intercal} T B B ⊺ = B B ⊺ , 则
T B B ⊺ = [ a 1 2 + b 1 2 a 2 b 1 a 2 b 1 ⋱ ⋱ ⋱ a n − 1 2 + b n − 1 2 a n b n − 1 a n b n − 1 a n 2 ] . T _ {B B ^ {\intercal}} = \left[ \begin{array}{c c c c} a _ {1} ^ {2} + b _ {1} ^ {2} & a _ {2} b _ {1} & & \\ a _ {2} b _ {1} & \ddots & \ddots & \\ & \ddots & a _ {n - 1} ^ {2} + b _ {n - 1} ^ {2} & a _ {n} b _ {n - 1} \\ & & a _ {n} b _ {n - 1} & a _ {n} ^ {2} \end{array} \right]. T B B ⊺ = a 1 2 + b 1 2 a 2 b 1 a 2 b 1 ⋱ ⋱ ⋱ a n − 1 2 + b n − 1 2 a n b n − 1 a n b n − 1 a n 2 . T B B ⊺ T_{BB^{\intercal}} T B B ⊺ 的特征值为 B B B 的奇异值的平方, 且 T B B ⊺ T_{BB^{\intercal}} T B B ⊺ 的特征向量为 B B B 的左奇异向量.
(3) 令 T B ⊺ B = B ⊺ B T_{B^{\intercal}B} = B^{\intercal}B T B ⊺ B = B ⊺ B , 则
T B ⊺ B = [ a 1 2 a 1 b 1 a 1 b 1 a 2 2 + b 1 2 ⋱ ⋱ ⋱ a n − 1 b n − 1 a n − 1 b n − 1 a n 2 + b n − 1 2 ] . T _ {B ^ {\intercal} B} = \left[ \begin{array}{c c c c} a _ {1} ^ {2} & a _ {1} b _ {1} & & \\ a _ {1} b _ {1} & a _ {2} ^ {2} + b _ {1} ^ {2} & \ddots & \\ & \ddots & \ddots & a _ {n - 1} b _ {n - 1} \\ & & a _ {n - 1} b _ {n - 1} & a _ {n} ^ {2} + b _ {n - 1} ^ {2} \end{array} \right]. T B ⊺ B = a 1 2 a 1 b 1 a 1 b 1 a 2 2 + b 1 2 ⋱ ⋱ ⋱ a n − 1 b n − 1 a n − 1 b n − 1 a n 2 + b n − 1 2 . T B ⊺ B T_{B^{\intercal}B} T B ⊺ B 的特征值为 B B B 的奇异值的平方, 且 T B ⊺ B T_{B^{\intercal}B} T B ⊺ B 的特征向量为 B B B 的右奇异向量.
Golub & Kahan (1965) 采用前面两种做法. Reinsch (1970) 采用第三种做法, 其巧妙之处是,只需对 B B B 做 Givens 变换即可, 类似隐式 QR 迭代.
理论上, 我们可以直接使用 QR 迭代、分而治之法或带反迭代的对分法, 计算对称三对角矩阵 T p s , T B B ⊺ T_{ps}, T_{BB^{\intercal}} T p s , T B B ⊺ 和 T B ⊺ B T_{B^{\intercal}B} T B ⊺ B 的特征值和特征向量. 但一般来说, 这种做法并不是最佳的, 原因如下:
(1) 对 T p s T_{ps} T p s 做 QR 迭代并不划算, 因为 Q R QR QR 迭代计算所有的特征值和特征向量, 而事实上只要计算正的特征值即可; (2) 直接构成 T B B ⊤ T_{BB^{\top}} T B B ⊤ 或 T B ⊤ B T_{B^{\top}B} T B ⊤ B 是数值不稳定的. 事实上, 这样做可能会使得 B B B 的小奇异值的精度丢失一半.
下面是一些计算奇异值分解的比较实用的算法
Golub-Kahan SVD 算法: 由 Golub 和 Kahan [53] 于 1965 年提出, 并在 1970 年进行了完善 [54], 是一种十分稳定且高效的计算 SVD 的算法, 也是最早的实用 SVD 算法. 主要思想是将带位移的对称 QR 迭代算法隐式地用到 B T B B^{\mathsf{T}} B B T B 上, 在该算法中, 并不需要显示地把 B T B B^{\mathsf{T}} B B T B 计算出来. 该算法也通常就称为 SVD 算法, 是一个基本且实用的算法, 目前仍然是计算小规模矩阵奇异值分解的常用算法. 关于这个算法的详细描述, 也可以参见 [57, 152].
dqds 算法: 由 Fernando 和 Parlett [44] 于 1994 年提出, 是计算二对角矩阵所有奇异值的最快算法, 而且能达到很高的相对精度, 包括奇异值很小的情形. 该算法主要基于对 B T B B^{\mathsf{T}} B B T B 的 Cholesky 迭代, 可以看作是 LR 迭代算法的改进. 由于 LR 迭代算法在一定条件下与对称 QR 算法是等价的, 因此该算法也可以看作是 QR 迭代的变形. 该算法是 LAPACK 中计算二对角矩阵奇异值 (不计算奇异向量) 的标准算法 [33].
分而治之法: 该算法是计算较大规模矩阵的所有奇异值和奇异向量的最快算法, 但不能保证小奇异值的相对精度, 即 σ i \sigma_{i} σ i 的相对精度为 O ( ε ) σ 1 \mathcal{O}(\varepsilon)\sigma_{1} O ( ε ) σ 1 , 而不是 O ( ε ) σ i \mathcal{O}(\varepsilon)\sigma_{i} O ( ε ) σ i .
对分法和反迭代: 主要用于计算某个区间内的奇异值及对应的奇异向量, 能保证较高的相对精度.
Jacobi 迭代: 可隐式地对 A A T AA^{\mathsf{T}} A A T 或 A T A A^{\mathsf{T}}A A T A 实施对称 Jacobi 迭代, 能保证较高的相对精度. 最近, Z. Drmac 和 K. Veselic [34, 35] 改进了最初的 Jacobi 算法, 使其变成一个速度快、精度高的实用算法.
在这里, 我们介绍 Golub-Kahan SVD 算法, dqds 算法和 Jacobi 迭代.
5.6.2 Golub-Kahan SVD算法 该算法主要思想是将带位移的对称QR迭代算法隐式地用到 B T B B^{\mathsf{T}}B B T B 上,而无需将 B T B B^{\mathsf{T}}B B T B 显式地计算出来. Golub-Kahan SVD算法有时也简称SVD算法,其基本框架是:
将矩阵 A A A 二对角化, 得到上二对角矩阵 B B B ;
用隐式 QR 迭代计算 B T B B^{\mathsf{T}} B B T B 的特征值分解, 即
B ⊤ B = Q Λ Q ⊤ , Λ = diag ( σ 1 2 , σ 2 2 , … , σ n 2 ) . (5.11) B ^ {\top} B = Q \Lambda Q ^ {\top}, \quad \Lambda = \operatorname {d i a g} \left(\sigma_ {1} ^ {2}, \sigma_ {2} ^ {2}, \dots , \sigma_ {n} ^ {2}\right). \tag {5.11} B ⊤ B = Q Λ Q ⊤ , Λ = diag ( σ 1 2 , σ 2 2 , … , σ n 2 ) . ( 5.11 ) ( B Q ) P = U R , (5.12) (B Q) P = U R, \tag {5.12} ( BQ ) P = U R , ( 5.12 ) 其中 P P P 是置换矩阵, U U U 是正交矩阵, R R R 是上三角矩阵
由 (5.8) 可知
( B Q ) T B Q = Λ , \left(B Q\right) ^ {\mathsf {T}} B Q = \Lambda , ( BQ ) T BQ = Λ , 因此 B Q BQ BQ 是列正交矩阵 (但不是单位列正交). 再由 (5.9) 可知 R = U T ( B Q ) P R = U^{\mathsf{T}}(BQ)P R = U T ( BQ ) P 也是列正交矩阵. 又 R R R 是上三角矩阵, 所以 R R R 必定是对角矩阵. 令 V = Q P V = QP V = QP , 则由 (5.9) 可知
U ⊺ B V = R . U ^ {\intercal} B V = R. U ⊺ B V = R . 这就是二对角矩阵 B B B 的奇异值分解
算法的具体实现可参见[57,152].
5.6.3 dqds算法 我们首先介绍针对实对称正定矩阵的LR算法,该算法思想与QR迭代算法类似,但提出时间更早.
算法5.9.带位移的LR算法 1: Let T 0 T_0 T 0 be a given real symmetric positive definite matrix 2: set i = 0 i = 0 i = 0 3: while not converge do 4: choose a shift τ i 2 \tau_i^2 τ i 2 satisfying τ i 2 < min { λ ( T i ) } \tau_i^2 < \min \{\lambda (T_i)\} τ i 2 < min { λ ( T i )} 5: compute B i B_i B i such that T i − τ i 2 I = B i ⊤ B i T_i - \tau_i^2 I = B_i^\top B_i T i − τ i 2 I = B i ⊤ B i . % Cholesky factorization 6: T i + 1 = B i B i ⊤ + τ i 2 I T_{i + 1} = B_iB_i^\top +\tau_i^2 I T i + 1 = B i B i ⊤ + τ i 2 I 7: i = i + 1 i = i + 1 i = i + 1 8: end while
LR迭代算法在形式上与QR迭代算法非常类似.事实上,对于不带位移的LR迭代算法,我们可以证明,两步LR迭代等价于一步QR迭代.
引理5.13 设 T ~ \tilde{T} T ~ 是不带位移的LR算法迭代两步后生成的矩阵, T ^ \hat{T} T ^ 是不带位移的QR算法迭代一步后生成的矩阵, 则 T ~ = T ^ \tilde{T} = \hat{T} T ~ = T ^ .
(1) LR 算法中要求 T 0 T_{0} T 0 对称正定, 但并不一定是三对角矩阵;
(2) 由该引理可知, QR 算法与 LR 算法有相同的收敛性.
下面我们介绍 dqds (differential quotient difference with shifts) 算法. 该算法是针对三对角的对称正定矩阵 B T B B^{\mathsf{T}}B B T B , 其中 B B B 是二对角矩阵. 在数学上, dqds 算法与 LR 算法是等价的, 但在该算法中, 我们是直接通过 B i B_{i} B i 来计算 B i + 1 B_{i+1} B i + 1 , 从而避免计算中间矩阵 T i + 1 T_{i+1} T i + 1 , 这样也就尽可能地避免了由于计算 B i B i T B_{i}B_{i}^{\mathsf{T}} B i B i T 而可能带来的数值不稳定性.
下面推导如何从 B i B_{i} B i 直接计算 B i + 1 B_{i + 1} B i + 1 . 设
B i = [ a 1 b 1 a 2 ⋱ ⋱ b n − 1 a n ] , B i + 1 = [ a ~ 1 b ~ 1 a ~ 2 ⋱ ⋱ b ~ n − 1 a ~ n ] . B _ {i} = \left[ \begin{array}{c c c c} a _ {1} & b _ {1} & & \\ & a _ {2} & \ddots & \\ & & \ddots & b _ {n - 1} \\ & & & a _ {n} \end{array} \right], B _ {i + 1} = \left[ \begin{array}{c c c c} \tilde {a} _ {1} & \tilde {b} _ {1} & & \\ & \tilde {a} _ {2} & \ddots & \\ & & \ddots & \tilde {b} _ {n - 1} \\ & & & \tilde {a} _ {n} \end{array} \right]. B i = a 1 b 1 a 2 ⋱ ⋱ b n − 1 a n , B i + 1 = a ~ 1 b ~ 1 a ~ 2 ⋱ ⋱ b ~ n − 1 a ~ n . 为了书写方便, 我们记 b 0 = b n = b ~ 0 = b ~ n = 0 b_{0} = b_{n} = \tilde{b}_{0} = \tilde{b}_{n} = 0 b 0 = b n = b ~ 0 = b ~ n = 0 . 由 LR 算法 5.9 可知
B i + 1 T B i + 1 + τ i + 1 2 I = B i B i T + τ i 2 I . B _ {i + 1} ^ {\mathsf {T}} B _ {i + 1} + \tau_ {i + 1} ^ {2} I = B _ {i} B _ {i} ^ {\mathsf {T}} + \tau_ {i} ^ {2} I. B i + 1 T B i + 1 + τ i + 1 2 I = B i B i T + τ i 2 I . 比较等式两边矩阵的对角线和上对角线元素,可得
a ~ k 2 + b ~ k − 1 2 + τ i + 1 2 = a k 2 + b k 2 + τ i 2 , k = 1 , 2 , … , n \tilde {a} _ {k} ^ {2} + \tilde {b} _ {k - 1} ^ {2} + \tau_ {i + 1} ^ {2} = a _ {k} ^ {2} + b _ {k} ^ {2} + \tau_ {i} ^ {2}, k = 1, 2, \ldots , n a ~ k 2 + b ~ k − 1 2 + τ i + 1 2 = a k 2 + b k 2 + τ i 2 , k = 1 , 2 , … , n a ~ k b ~ k = a k + 1 b k 或 a ~ k 2 b ~ k 2 = a k + 1 2 b k 2 , k = 1 , 2 , … , n − 1. \tilde {a} _ {k} \tilde {b} _ {k} = a _ {k + 1} b _ {k} \quad \text {或} \quad \tilde {a} _ {k} ^ {2} \tilde {b} _ {k} ^ {2} = a _ {k + 1} ^ {2} b _ {k} ^ {2}, \quad k = 1, 2, \ldots , n - 1. a ~ k b ~ k = a k + 1 b k 或 a ~ k 2 b ~ k 2 = a k + 1 2 b k 2 , k = 1 , 2 , … , n − 1. 记 δ = τ i + 1 2 − τ i 2 , p k = a k 2 , q k = b k 2 , p ~ k = a ~ k 2 , q ~ k = b ~ k 2 \delta = \tau_{i + 1}^{2} - \tau_{i}^{2},p_{k} = a_{k}^{2},q_{k} = b_{k}^{2},\tilde{p}_{k} = \tilde{a}_{k}^{2},\tilde{q}_{k} = \tilde{b}_{k}^{2} δ = τ i + 1 2 − τ i 2 , p k = a k 2 , q k = b k 2 , p ~ k = a ~ k 2 , q ~ k = b ~ k 2 ,则可得下面的qds算法.
算法5.10.qds算法的单步 ( B i → B i + 1 ) (B_{i}\to B_{i + 1}) ( B i → B i + 1 )
1: δ = τ i + 1 2 − τ i 2 \delta = \tau_{i + 1}^{2} - \tau_{i}^{2} δ = τ i + 1 2 − τ i 2 2: for k = 1 k = 1 k = 1 to n − 1 n - 1 n − 1 do 3: p ~ k = p k + q k − q ~ k − 1 − δ \tilde{p}_k = p_k + q_k - \tilde{q}_{k - 1} - \delta p ~ k = p k + q k − q ~ k − 1 − δ 4: q ~ k = q k ⋅ ( p k + 1 / p ~ k ) \tilde{q}_k = q_k\cdot (p_{k + 1} / \tilde{p}_k) q ~ k = q k ⋅ ( p k + 1 / p ~ k ) 5: end for 6: p ~ n = p n − q ~ n − 1 − δ \tilde{p}_n = p_n - \tilde{q}_{n - 1} - \delta p ~ n = p n − q ~ n − 1 − δ
qds算法中的每个循环仅需5个浮点运算,所以运算量较少
为了提高算法的精确性, 我们引入一个辅助变量 d k ≜ p k − q ~ k − 1 − δ d_k \triangleq p_k - \tilde{q}_{k-1} - \delta d k ≜ p k − q ~ k − 1 − δ , 则
d k = p k − q ~ k − 1 − δ = p k − q k − 1 p k p ~ k − 1 − δ = p k ⋅ p ~ k − 1 − q k − 1 p ~ k − 1 − δ \begin{array}{l} d _ {k} = p _ {k} - \tilde {q} _ {k - 1} - \delta \\ = p _ {k} - \frac {q _ {k - 1} p _ {k}}{\tilde {p} _ {k - 1}} - \delta \\ = p _ {k} \cdot \frac {\tilde {p} _ {k - 1} - q _ {k - 1}}{\tilde {p} _ {k - 1}} - \delta \\ \end{array} d k = p k − q ~ k − 1 − δ = p k − p ~ k − 1 q k − 1 p k − δ = p k ⋅ p ~ k − 1 p ~ k − 1 − q k − 1 − δ = p k ⋅ p k − 1 − q ~ k − 2 − δ p ~ k − 1 − δ = p k p ~ k − 1 ⋅ d k − 1 − δ . = p _ {k} \cdot \frac {p _ {k - 1} - \tilde {q} _ {k - 2} - \delta}{\tilde {p} _ {k - 1}} - \delta = \frac {p _ {k}}{\tilde {p} _ {k - 1}} \cdot d _ {k - 1} - \delta . = p k ⋅ p ~ k − 1 p k − 1 − q ~ k − 2 − δ − δ = p ~ k − 1 p k ⋅ d k − 1 − δ . 于是就可得到 dqds 算法:
算法5.11.dqds算法的单步 ( B i → B i + 1 ) (B_{i}\to B_{i + 1}) ( B i → B i + 1 ) 1: δ = τ i + 1 2 − τ i 2 \delta = \tau_{i + 1}^{2} - \tau_{i}^{2} δ = τ i + 1 2 − τ i 2 2: d 1 = p 1 − δ d_{1} = p_{1} - \delta d 1 = p 1 − δ 3: for k = 1 k = 1 k = 1 to n − 1 n - 1 n − 1 do 4: p ~ k = d k + q k \tilde{p}_k = d_k + q_k p ~ k = d k + q k 5: t = p k + 1 / p ~ k t = p_{k + 1} / \tilde{p}_k t = p k + 1 / p ~ k 6: q ~ k = q k ⋅ t \tilde{q}_k = q_k\cdot t q ~ k = q k ⋅ t 7: d k + 1 = d k ⋅ t − δ d_{k + 1} = d_k\cdot t - \delta d k + 1 = d k ⋅ t − δ 8: end for 9: p ~ n = d n \tilde{p}_n = d_n p ~ n = d n
dqds算法的运算量与dqs差不多,但更精确
关于 dqds 算法中位移的选取, 以及如何判断收敛性, 可以参见 [44].
A \mathcal{A} A dqds算法是求解二对角矩阵所有奇异值的主要方法之一,2000年就被加入到LAPACK中[2,102].关于dqds的最新改进可以参见[90].
5.6.4 Jacobi算法 本节讨论对矩阵 M = A T A M = A^{\mathrm{T}}A M = A T A 实施隐式的Jacobi算法来计算 A A A 的奇异值.
我们知道, Jaboci 算法的每一步就是对矩阵作 Jacobi 旋转, 即 A T A → J T A T A J A^{\mathsf{T}}A \to J^{\mathsf{T}}A^{\mathsf{T}}AJ A T A → J T A T A J , 其中 J J J 的选取将某两个非对角元化为 0. 在实际计算中, 我们只需计算 A J AJ A J , 故该算法称为单边 Jacobi 旋转.
算法5.12.单边Jacobi旋转的单步 % \% % 对 M = A T A M = A^{\mathsf{T}}A M = A T A 作Jacobi旋转, 将 M ( i , j ) , M ( j , i ) M(i,j), M(j,i) M ( i , j ) , M ( j , i ) 化为0
1: Compute m i i = ( A T A ) i i m_{ii} = (A^{\mathsf{T}}A)_{ii} m ii = ( A T A ) ii , m i j = ( A T A ) i j m_{ij} = (A^{\mathsf{T}}A)_{ij} m ij = ( A T A ) ij , m j j = ( A T A ) j j m_{jj} = (A^{\mathsf{T}}A)_{jj} m jj = ( A T A ) jj . 2: if m i j m_{ij} m ij is not small enough then 3: τ = ( m i i − m j j ) / ( 2 ⋅ m i j ) \tau = (m_{ii} - m_{jj}) / (2\cdot m_{ij}) τ = ( m ii − m jj ) / ( 2 ⋅ m ij ) 4: t = s i g n ( τ ) / ( ∣ τ ∣ + 1 + τ 2 ) t = \mathrm{sign}(\tau) / (|\tau| + \sqrt{1 + \tau^2}) t = sign ( τ ) / ( ∣ τ ∣ + 1 + τ 2 ) 5: c = 1 / 1 + t 2 c = 1 / \sqrt{1 + t^2} c = 1/ 1 + t 2 6: s = c ⋅ t s = c\cdot t s = c ⋅ t 7: A = A G ( i , j , θ ) A = AG(i,j,\theta) A = A G ( i , j , θ ) % G ( i , j , θ ) \% G(i,j,\theta) % G ( i , j , θ ) 为Givens变换 8: if eigenvectors are desired then 9: J = J ⋅ G ( i , j , θ ) J = J\cdot G(i,j,\theta) J = J ⋅ G ( i , j , θ )
10: end if 11: end if
在上面算法的基础上, 我们可以给出完整的单边 Jacobi 算法.
算法5.13.单边Jacobi:计算 A = U Σ V T A = U\Sigma V^{\mathsf{T}} A = U Σ V T
1: while A T A A^{\mathsf{T}}A A T A is not diagonal enough do 2: for i = 1 i = 1 i = 1 to n − 1 n - 1 n − 1 do 3: for j = i + 1 j = i + 1 j = i + 1 to n n n do 4: 调用单边 Jacobi 旋转 5: end for 6: end for 7: end while 8: compute σ i = ∥ A ( : , i ) ∥ 2 , i = 1 , 2 , … n \sigma_{i} = \| A(:,i)\|_{2}, i = 1,2,\ldots n σ i = ∥ A ( : , i ) ∥ 2 , i = 1 , 2 , … n 9: U = [ u 1 , … , u n ] U = [u_{1}, \dots, u_{n}] U = [ u 1 , … , u n ] with u i = A ( : , i ) / σ i u_{i} = A(:, i) / \sigma_{i} u i = A ( : , i ) / σ i 10: V = J V = J V = J
Jacobi算法的特点:
不需要双对角化,这样可以避免双对角化引入的误差;
可达到相对较高的计算精度;
速度较慢. (目前已有快速的改进算法, 参见 [34, 35])
定理5.14 设 A = D X ∈ R n × n A = DX \in \mathbb{R}^{n \times n} A = D X ∈ R n × n , 其中 D D D 为非奇异对角阵, X X X 非奇异. 设 A ^ \hat{A} A ^ 是按浮点运算单边 Jacobi 旋转 m m m 次后所得到的矩阵. 若 A A A 和 A ^ \hat{A} A ^ 的奇异值分别为 σ 1 ≥ σ 2 ≥ … ≥ σ n \sigma_{1} \geq \sigma_{2} \geq \ldots \geq \sigma_{n} σ 1 ≥ σ 2 ≥ … ≥ σ n 和 σ ^ 1 ≥ σ ^ 2 ≥ … ≥ σ ^ n \hat{\sigma}_{1} \geq \hat{\sigma}_{2} \geq \ldots \geq \hat{\sigma}_{n} σ ^ 1 ≥ σ ^ 2 ≥ … ≥ σ ^ n , 则
∣ σ ^ i − σ i ∣ σ i ≤ O ( m ε ) κ ( X ) . \frac {\left| \hat {\sigma} _ {i} - \sigma_ {i} \right|}{\sigma_ {i}} \leq \mathcal {O} (m \varepsilon) \kappa (X). σ i ∣ σ ^ i − σ i ∣ ≤ O ( m ε ) κ ( X ) . 故 X X X 的条件数越小, 计算矩阵 A A A 的奇异值时相对误差越小.