QR分解
矩阵的列通常是歪的。彼此不垂直,长度也各不相同。QR 把这些列分成两块。先用格拉姆-施密特把列拉直,变成彼此垂直的单位向量,这就是 Q,是既不动长度也不动角度的旋转或反射。拉直时削下来的长度和重叠收在一起,就是 R,而且总是只填上边的三角形。A = QR。一个旋转,一个三角形。这一行是稳定地解最小二乘的路,也是数值线性代数常叫的分解。格子保持正方形,就是 Q 为旋转的证据。歪的列是 A,拉直的列是 Q。误差平方和最小的直线,就是 QR 找到的答案。
用按钮一步步走。0 阶段是 A 的两列 a1、a2。它们是斜的,长度也不同。走到 1 阶段,格拉姆-施密特把这一对拉直。把 a1 的方向缩成单位长度的是 q1,从 a2 减去朝向 q1 的影子、再把剩下的正交分量单位化,就是 q2。现在 q1 和 q2 恰好垂直,两者长度都是 1,点积显示为 0。2 阶段出现 R。R = Qᵀ A,所以自动是上三角,左下角 r21 是 0。A 是歪的列,Q 是拉直的正交列,R 是连接两者的小三角形。这就是 A = QR。
Q 的两列是彼此垂直的单位向量。所以把 Q 作用到平面上,格子不会变形,只是整块转动。用滑块转动角度,格子既不拉长也不压扁,正方形还是正方形。因为长度和角度都保住了。按下反射按钮,像镜子一样翻转,列仍然是正交单位,形状不变。这就是正交矩阵的定义。QᵀQ = I。看画面下方的 QᵀQ,无论哪个角度都停在单位矩阵。这是 Q 只是旋转或反射的证据。
R 为什么总是只填上边的三角形。每一格是 rij = qi · aj,也就是把原来的第 j 列投到第 i 个拉直方向上的影子长度。打开一格,点积的值就得到确认。关键是对角线下面的格子。r21 = q2 · a1,而 q2 是去掉 a1 之后剩下的正交分量,与 a1 恰好垂直。垂直则点积为 0,所以 r21 是 0。后面做出的方向 qi 不会用在更早的列 aj 上,也就是 j 小于 i 的列。那一列已经被前面的方向表达过了。所以对角线下方整块是 0,R 是上三角。
这一次倒过来拿着 R 重建 A。把 Q 固定成 20 度的旋转,用滑块移动 R 的三格,A = QR 就立刻重画。r11 决定第一列 a1 的长度,调大则 a1 变长。r22 是往第二个方向伸多远,也就是正交分量的长度。r12 是剪切,决定第二列朝第一个方向倾多少。这三个数装下长度和倾斜,Q 只是把结果整块转 20 度。R 管形状,Q 管方向,分工看得清楚。
QR 真正干活的地方是最小二乘。最贴合数据的直线,是把竖直虚线也就是残差的平方和变得最小的那条。用滑块移动斜率和截距,可以把这个和减小。通常要造出 AᵀA 来解正规方程,而 AᵀA 对误差敏感,数值上常常不稳定。QR 跳过这一步。放入 A = QR,正规方程就缩成 R x = Qᵀ b。R 是三角形,从后往前代入就结束。按下按钮,跳到那个 QR 解,误差平方和达到最小。不造 AᵀA,却更稳定地得到同一个答案,这就是 QR 的用处。