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=I−2uu∗
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=∥(a1−∥a1∥e1)∥a1−∥a1∥e1
用这个
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=∥a1∥e1
那么
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)=
∥a1∥0⋮0⋯⋯⋱⋯∗∗∗∗
把右边的矩阵叫做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=BH−1HA=H−1BA=H−1B
Householder变换矩阵是自逆矩阵,也是对合矩阵,所以
H
=
H
−
1
H=H^{-1}
H=H−1.所以又有:
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=
11⋱Hi
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˜n−1⋯H˜2H˜1A=RH˜1−1H˜2−1⋯H˜n−1−1H˜n−1H˜nH˜n−1⋯H˜2H˜1A=H˜1−1H˜2−1⋯H˜n−1−1H˜n−1RA=H˜1−1H˜2−1⋯H˜n−1−1H˜n−1RA=H˜1H˜2⋯H˜n−1H˜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}
0023411−22
第一次分解得到:
(
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}
0023411−22
=
001010100
2001432−21
第二次分解得到:
(
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}
2001432−21
=
10000.80.600.6−0.8
2001502−1−2
第三次分解得到:
(
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}
2001502−1−2
=
10001000−1
2001502−12
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