4.6 QR分解二:Householder变换

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

1 Householder reflector

  Householder反射是这样子的(图片来自瑞典皇家理工学院)
在这里插入图片描述
  图中u是长度为1的向量。x是任意向量H是u的Householder reflector。可见无论x是什么向量 H x Hx Hx始终除于和u正交的平面上。H和u的关系是
H = I − 2 u u ∗ H=I-2uu^* H=I2uu
   u ∗ u^* u是u的共轭转置 u u u是单位向量。在有些书上也写成 u H u^H uH.也就是说H这个矩阵是由 u u u确定的。那么接下来的问题是如何精确控制变换方向了。如果能精确控制把向量投影到标准基的方向上那么QR分解就容易了。
  那么这和QR分解有什么关系呢

2 分解步骤

  首先把矩阵A按列向量分块为 ( a 1 , a 2 , ⋯   , a n ) (a_1,a_2,\cdots,a_n) (a1,a2,,an),设单位矩阵的第一列为 e 1 e_1 e1,取 u u u向量为以下向量
u = a 1 − ∥ a 1 ∥ e 1 ∥ ( a 1 − ∥ a 1 ∥ e 1 ) ∥ u=\frac{a_1-\parallel a_1 \parallel e_1}{\parallel (a_1-\parallel a_1 \parallel e_1)\parallel} u=(a1a1e1)a1a1e1
  用这个 u u u向量构造的Householder矩阵 H H H会把 a 1 a_1 a1投影到 e 1 e_1 e1的方向上。也就是
H a 1 = ∥ a 1 ∥ e 1 Ha_1=\parallel a_1 \parallel e_1 Ha1=∥a1e1
  那么 H A HA HA就是这个样子
H A = H ( a 1 , a 2 , ⋯   , a n ) = ( ∥ a 1 ∥ ⋯ ∗ 0 ⋯ ∗ ⋮ ⋱ ∗ 0 ⋯ ∗ ) HA=H(a_1,a_2,\cdots,a_n)=\begin{pmatrix}\parallel a_1\parallel & \cdots & *\\ 0 &\cdots & * \\ \vdots & \ddots & *\\ 0 & \cdots & * \end{pmatrix} HA=H(a1,a2,,an)= a100
  把右边的矩阵叫做B那么有
H A = B H − 1 H A = H − 1 B A = H − 1 B HA=B\\ H^{-1}HA=H^{-1}B\\ A=H^{-1}B HA=BH1HA=H1BA=H1B
  Householder变换矩阵是自逆矩阵也是对合矩阵所以 H = H − 1 H=H^{-1} H=H1.所以又有
A = H B A=HB A=HB
   B B B矩阵的右下角再当成新的子矩阵继续完成这个过程这样得到一系列的H矩阵编号为 H 1 , H 2 , ⋯   , H n H_1,H_2,\cdots,H_n H1,H2,,Hn.这写矩阵乘以 A A A,得到的结果也是不断把对角线以下的元素变成 0 0 0,所以最终结果就是上三角矩阵 R R R。但是会发现这些Householder矩阵是不同阶的。为了同阶可以在对角线上补1凑成 n n n阶矩阵这种左上角补1的矩阵乘以任何矩阵不会改变左上角的元素。如下面这样处理
H ˜ i = ( 1 1 ⋱ H i ) n \~H_i=\begin{pmatrix}1 \\ & 1\\ & & \ddots\\ & & & H_i\end{pmatrix}_n H˜i= 11Hi n
  所以整个过程就是
H ˜ n H ˜ n − 1 ⋯ H ˜ 2 H ˜ 1 A = R H ˜ 1 − 1 H ˜ 2 − 1 ⋯ H ˜ n − 1 − 1 H ˜ n − 1 H ˜ n H ˜ n − 1 ⋯ H ˜ 2 H ˜ 1 A = H ˜ 1 − 1 H ˜ 2 − 1 ⋯ H ˜ n − 1 − 1 H ˜ n − 1 R A = H ˜ 1 − 1 H ˜ 2 − 1 ⋯ H ˜ n − 1 − 1 H ˜ n − 1 R A = H ˜ 1 H ˜ 2 ⋯ H ˜ n − 1 H ˜ n R \~H_n\~H_{n-1}\cdots \~H_2\~H_1A=R\\ \~H_1^{-1}\~H_2^{-1}\cdots \~H_{n-1}^{-1}\~H_n^{-1}\~H_n\~H_{n-1}\cdots \~H_2\~H_1A=\~H_1^{-1}\~H_2^{-1}\cdots \~H_{n-1}^{-1}\~H_n^{-1}R\\ A=\~H_1^{-1}\~H_2^{-1}\cdots \~H_{n-1}^{-1}\~H_n^{-1}R\\ A=\~H_1\~H_2\cdots \~H_{n-1}\~H_nR\\ H˜nH˜n1H˜2H˜1A=RH˜11H˜21H˜n11H˜n1H˜nH˜n1H˜2H˜1A=H˜11H˜21H˜n11H˜n1RA=H˜11H˜21H˜n11H˜n1RA=H˜1H˜2H˜n1H˜nR
  最终这些拼凑为 n n n阶的矩阵连乘起来就是Q矩阵最终的结果就是R矩阵。

3 举例

  以这个矩阵为例子
( 0 3 1 0 4 − 2 2 1 2 ) \begin{pmatrix}0 & 3 & 1\\ 0 & 4 & -2\\ 2 & 1 & 2\\ \end{pmatrix} 002341122
  第一次分解得到
( 0 3 1 0 4 − 2 2 1 2 ) = ( 0 0 1 0 1 0 1 0 0 ) ( 2 1 2 0 4 − 2 0 3 1 ) \begin{pmatrix}0 & 3 & 1\\ 0 & 4 & -2\\ 2 & 1 & 2\\ \end{pmatrix} = \begin{pmatrix}0 & 0 & 1\\ 0 & 1 & 0\\ 1 & 0 & 0\\ \end{pmatrix} \begin{pmatrix}2 & 1 & 2\\ 0 & 4 & -2\\ 0 & 3 & 1\\ \end{pmatrix} 002341122 = 001010100 200143221
  第二次分解得到
( 2 1 2 0 4 − 2 0 3 1 ) = ( 1 0 0 0 0.8 0.6 0 0.6 − 0.8 ) ( 2 1 2 0 5 − 1 0 0 − 2 ) \begin{pmatrix}2 & 1 & 2\\ 0 & 4 & -2\\ 0 & 3 & 1\\ \end{pmatrix} = \begin{pmatrix}1 & 0 & 0\\ 0 & 0.8 & 0.6\\ 0 & 0.6 & -0.8\\ \end{pmatrix} \begin{pmatrix}2 & 1 & 2\\ 0 & 5 & -1\\ 0 & 0 & -2\\ \end{pmatrix} 200143221 = 10000.80.600.60.8 200150212
  第三次分解得到
( 2 1 2 0 5 − 1 0 0 − 2 ) = ( 1 0 0 0 1 0 0 0 − 1 ) ( 2 1 2 0 5 − 1 0 0 2 ) \begin{pmatrix}2 & 1 & 2\\ 0 & 5 & -1\\ 0 & 0 & -2\\ \end{pmatrix} = \begin{pmatrix}1 & 0 & 0\\ 0 & 1 & 0\\ 0 & 0 & -1\\ \end{pmatrix} \begin{pmatrix}2 & 1 & 2\\ 0 & 5 & -1\\ 0 & 0 & 2\\ \end{pmatrix} 200150212 = 100010001 200150212

4 Python实现

  代码实现如下

    @staticmethod
    def householder_u(x, z, inner_product_matrix=None):
        x_len = vector_len(x, inner_product_matrix)
        xz = mul_num(z, x_len)
        complement = sub(x, xz)
        complement_len = vector_len(complement, inner_product_matrix)
        return mul_num(complement, 1 / complement_len)

    # 获取householder变换的u向量
    def get_householder_u(self, inner_product_matrix=None):
        a1 = self.__vectors[0]
        n = len(a1)
        e1 = [0] * n
        e1[0] = 1
        return Matrix.householder_u(a1, e1, inner_product_matrix)

    # 获取householder矩阵
    def householder_matrix(self, inner_product_matrix=None):
        n = len(self.__vectors)
        unit = Matrix.unit_matrix(n)
        u = self.get_householder_u(inner_product_matrix)
        u_matrix = Matrix([u])
        h = Matrix(unit) - u_matrix * u_matrix.transpose_matrix() * 2
        return h

    # householder变换
    def householder(self, inner_product_matrix=None):
        n = len(self.__vectors)
        r = self
        q = Matrix(Matrix.unit_matrix(n))
        for i in range(n):
            # 子矩阵
            sub_matrix_array = [r.__vectors[j][j:] for j in range(i, n)]
            sub_matrix = Matrix(sub_matrix_array)
            sub_h = sub_matrix.householder_matrix(inner_product_matrix)
            # 左上角补1
            h_array = Matrix.unit_matrix(n)
            for j in range(i, n):
                for k in range(i,n):
                    h_array[j][k] = sub_h.__vectors[j-i][k-i]
            h = Matrix(h_array)
            r = h * r
            print((h * r).to_latex(), '=',h.to_latex(), r.to_latex())
            # sub_r 的内容
            q = q * h
        return q, r
阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6