. QR分解 | 行列の分解 | プログラマーのための線形代数
QR分解 | 行列の分解 | プログラマーのための線形代数
QR分解 | 行列の分解 | プログラマーのための線形代数

QR分解

まずはグラム・シュミットの正規直交化法を使って、\(A\) を直交行列にします。 \(A\) の列ベクトル \(a_1,a_2,a_3\) が 3 次元の場合、直交行列 \(Q\) のそれぞれの列ベクトル \(q_1, q_2, q_3\) は次のように求められます(ベクトル \(a\) の\(L_2\)ノルムを \(\|a_1 \|\) とします。そしてベクトル \(a\) と \(q\) の内積が \(a \cdot q\) です)。

  • \(q_1 = \dfrac\)
  • \(v_2 = a_2-(a_2 \cdot q_1)q_1\), \(q_2=\dfrac\)
  • \(v_3 =a_3-(a_3 \cdot q_1)q_1-(a_3 \cdot q_2)q_2\), \(q_3= \dfrac\)

実際に行列 \(A\) の直交行列を求めてみましょう。

次に \(q_2\) は次のように求められます(内積の計算は省きます)。

最後に \(q_3\) は次のように求められます。

以上のことから行列 \(A\) の直交行列 \(Q\) は以下の通りになります。

これで直交行列を求められました。次に上三角行列 \(R\) を求めるのですが、その際は、直交行列の次の性質を使います(\(I\) は単位行列です)。

\[Q^T \cdot Q = Q \cdot Q^T = I\]

PythonでQR分解

Python では QR 分解は、NumPy の linalg.qr() 関数として実装されています。デフォルトでは、この関数は、次元削減された Q と R 行列を返します。mode 引数に “complete” と渡すと、\(n \times m\) の \(Q\) と \(m \times n\) の \(R\) を得られます。ただし、多くのアプリケーションでは、そこまでは必要とされていません。

# NumPy と SciPy のインポート import numpy as np from scipy.linalg import qr # 長方行列を定義 A = np.array([ [1,2,], [3,4,], [5,6]]) print(A) [[1 2] [3 4] [5 6]] # QR分解 Q,R = qr(A) print(Q, "complete") [[-0.16903085 0.89708523 0.40824829] [-0.50709255 0.27602622 -0.81649658] [-0.84515425 -0.34503278 0.40824829]] complete print(R) [[-5.91607978 -7.43735744] [ 0. 0.82807867] [ 0. 0. ]] # 元々の行列の再作成 B= Q @ R print(B) [[1. 2.] [3. 4.] [5. 6.]]
📎📎📎📎📎📎📎📎📎📎