SVD 应用

矩阵最小二乘法推导

最小二乘法(Least Squares)用于求解线性方程组 A \mathbf{x} = \mathbf{b} 的近似解,尤其是在方程组没有精确解时。其目标是最小化误差的平方和。只适用于非齐次方程解,对于齐次方程总有非平凡解\mathbf{x} = 0

1. 问题描述

给定矩阵 A \in \mathbb{R}^{m \times n} 和向量 \mathbf{b} \in \mathbb{R}^m,我们希望找到向量 \mathbf{x} \in \mathbb{R}^n,使得 A\mathbf{x} \approx \mathbf{b},即最小化以下目标函数:
\min_{\mathbf{x}} \|A\mathbf{x} - \mathbf{b}\|_2^2
其中,\|A\mathbf{x} - \mathbf{b}\|_2表示 A\mathbf{x} - \mathbf{b} 向量的 2 范数,即欧几里得距离。

2. 目标函数展开

目标函数 f(\mathbf{x}) = \|A\mathbf{x} - \mathbf{b}\|_2^2 是平方误差,可以展开如下:

f(\mathbf{x}) = (A\mathbf{x} - \mathbf{b})^\top (A\mathbf{x} - \mathbf{b})
展开后得到:
f(\mathbf{x}) = \mathbf{x}^\top A^\top A \mathbf{x} - 2 \mathbf{b}^\top A \mathbf{x} + \mathbf{b}^\top \mathbf{b}
其中,\mathbf{b}^\top \mathbf{b} 是常数项,和 \mathbf{x} 无关。

3. 对 \mathbf{x} 求导

为了找到使得 f(\mathbf{x}) 最小的 \mathbf{x},我们对 f(\mathbf{x}) 关于 \mathbf{x} 求导数,并令其为 0。

求导得到:
\frac{\partial f(\mathbf{x})}{\partial \mathbf{x}} = 2 A^\top A \mathbf{x} - 2 A^\top \mathbf{b}
令其等于 0:
A^\top A \mathbf{x} = A^\top \mathbf{b}

4. 结果

通过上述推导,我们得到常见的 正规方程
A^\top A \mathbf{x} = A^\top \mathbf{b}
这是求解最小二乘问题的标准方程。

5. 解的存在与唯一性

  • 存在性:正规方程有解的条件是 A^\top A 是可逆的。
  • 唯一性:如果 A^\top A 可逆,则解是唯一的。通常,如果 A 的列满秩(即\text{rank}(A) = n),则 A^\top A 是可逆的。

6. 解的形式

A^\top A 可逆时,最小二乘解可以表示为:
\mathbf{x} = (A^\top A)^{-1} A^\top \mathbf{b}

7. 总结

  1. 最小二乘法通过最小化误差平方和来求解线性方程组的近似解。
  2. 通过正规方程 A^\top A \mathbf{x} = A^\top \mathbf{b} 可以求得最小二乘解。

SVD 求解最小二乘法

使用 奇异值分解(SVD)求解 最小二乘法 是一种常见的数值方法。它通过分解矩阵 ( A ) 来获得解,尤其在矩阵 ( A ) 不满秩或近似满秩时,使用 SVD 可以更稳定地求解。

1. 问题定义

给定矩阵 A \in \mathbb{R}^{m \times n}和向量 \mathbf{b} \in \mathbb{R}^m,我们要解最小二乘问题:
\min_{\mathbf{x}} \| A \mathbf{x} - \mathbf{b} \|_2^2
这个问题的目标是找到一个向量 \mathbf{x} \in \mathbb{R}^n,使得 A \mathbf{x} 尽量接近 \mathbf{b}

2. 使用奇异值分解(SVD)

奇异值分解(SVD)将矩阵 ( A ) 分解为三个矩阵的乘积:
A = U \Sigma V^T

  • U 是一个 m \times m 的正交矩阵(包含左奇异向量);
  • \Sigma 是一个 m \times n 的对角矩阵,其中对角线上的元素是奇异值;
  • V^T 是一个 n \times n 的正交矩阵(包含右奇异向量)。

对于最小二乘问题,我们通过 SVD 进行分解后,可以得到解的表达式。

3. 最小二乘解的推导

3.1 使用 SVD 分解

我们首先用 SVD 将 ( A ) 分解:
A \mathbf{x} = U \Sigma V^T \mathbf{x}
要求解最小二乘问题 \min_{\mathbf{x}} \| A \mathbf{x} - \mathbf{b} \|_2^2,即:
\min_{\mathbf{x}} \| U \Sigma V^T \mathbf{x} - \mathbf{b} \|_2^2
由于 U 是正交矩阵,U^T U = I,我们可以将其作用到方程的两边:U^T (A \mathbf{x} - \mathbf{b}) = U^T \mathbf{b}
得到:\Sigma V^T \mathbf{x} = U^T \mathbf{b}
这里 U^T \mathbf{b} 是新的向量,记作 \mathbf{c} = U^T \mathbf{b},于是方程变为:\Sigma V^T \mathbf{x} = \mathbf{c}

3.2 解决方程

现在我们需要求解:
\Sigma V^T \mathbf{x} = \mathbf{c}
注意到 \Sigma 是对角矩阵,它包含了 A 的奇异值,记为 \sigma_1, \sigma_2, \dots, \sigma_r(其中 rA的秩)。我们可以将其表示为:
\Sigma = \begin{bmatrix} \sigma_1 & 0 & \dots & 0 \\ 0 & \sigma_2 & \dots & 0 \\ \vdots & \vdots & \ddots & \vdots \\ 0 & 0 & \dots & \sigma_r \end{bmatrix}
因此,我们有:
\begin{bmatrix} \sigma_1 v_1^T \mathbf{x} \\ \sigma_2 v_2^T \mathbf{x} \\ \vdots \\ \sigma_r v_r^T \mathbf{x} \end{bmatrix} = \mathbf{c}
对每个 ( i ),有:
\sigma_i v_i^T \mathbf{x} = c_i \quad \text{其中} \quad c_i = (U^T \mathbf{b})_i
因此,得到:
v_i^T \mathbf{x} = \frac{c_i}{\sigma_i} \quad \text{(对 \( \sigma_i \neq 0 \))}
所以最小二乘解 \mathbf{x} 可以通过:
\mathbf{x} = V \Sigma^+ U^T \mathbf{b}
其中,\Sigma^+\Sigma 的伪逆,定义为:
\Sigma^+ = \begin{bmatrix} \frac{1}{\sigma_1} & 0 & \dots & 0 \\ 0 & \frac{1}{\sigma_2} & \dots & 0 \\ \vdots & \vdots & \ddots & \vdots \\ 0 & 0 & \dots & \frac{1}{\sigma_r} \end{bmatrix}
即对于每个非零奇异值 \sigma_i,其倒数成为 \Sigma^+ 中相应位置的元素。

4. 最小二乘解的表达式

最终,最小二乘解 \mathbf{x} 为:
\mathbf{x} = V \Sigma^+ U^T \mathbf{b}
其中,U, \Sigma, V 是矩阵 A 的 SVD 分解结果,\Sigma^+\Sigma 的伪逆。

5. 数值解法

通过 SVD 来求解最小二乘法可以有效地处理奇异矩阵或者近似奇异矩阵的问题。SVD 是一种非常稳定的数值方法,尤其适用于解决欠定或超定线性方程组。

在实际应用中,可以使用 Python 的 numpyscipy 库中的 svd 函数来进行 SVD 分解,然后计算最小二乘解。

示例代码(Python):

import numpy as np

# 示例矩阵 A 和向量 b
A = np.array([[1, 2], [3, 4], [5, 6]])
b = np.array([7, 8, 9])

# 计算 SVD
U, Sigma, Vt = np.linalg.svd(A)

# 构造 Sigma 的伪逆
Sigma_plus = np.zeros((A.shape[1], A.shape[0]))  # 创建与 A.T 尺寸相同的矩阵
np.fill_diagonal(Sigma_plus, 1 / Sigma)          # 填充对角线

# 计算最小二乘解 x
x = Vt.T @ Sigma_plus @ U.T @ b

print("最小二乘解 x:")
print(x)

齐次矩阵最小二乘法

齐次矩阵最小二乘法是用来求解形如 A \mathbf{h} = 0 的齐次方程组的问题。这里 A 是一个已知的矩阵,而 \mathbf{h} 是待求解的向量。

1. 问题定义

给定矩阵 A \in \mathbb{R}^{m \times n},我们需要找到非零向量 \mathbf{h} \in \mathbb{R}^n,使得:
A \mathbf{h} = 0

直接解此方程可能存在平凡解(即 \mathbf{h} = 0)。为了避免平凡解,我们将问题重新表述为约束优化问题:
\min_{\mathbf{h}} \| A \mathbf{h} \|_2^2 \quad \text{subject to} \quad \| \mathbf{h} \|_2 = 1

这里添加了 \| \mathbf{h} \|_2 = 1 的约束,用于排除平凡解。

2. 使用奇异值分解(SVD)

2.1 矩阵 A 的 SVD 分解

对矩阵 A 进行奇异值分解:
A = U \Sigma V^T
其中:

  • U \in \mathbb{R}^{m \times m} 是正交矩阵,包含左奇异向量;
  • \Sigma \in \mathbb{R}^{m \times n} 是对角矩阵,包含奇异值 \sigma_1, \sigma_2, \dots
  • V \in \mathbb{R}^{n \times n} 是正交矩阵,包含右奇异向量。

2.2 最优解的确定

在约束优化问题中,目标是最小化 \| A \mathbf{h} \|_2^2。将 A 替换为其 SVD 分解后:
\| A \mathbf{h} \|_2^2 = \| U \Sigma V^T \mathbf{h} \|_2^2

由于 U 是正交矩阵,不改变向量的范数,因此有:
\| A \mathbf{h} \|_2^2 = \| \Sigma V^T \mathbf{h} \|_2^2

\mathbf{z} = V^T \mathbf{h},因为 V 也是正交矩阵,有 \| \mathbf{z} \|_2 = \| \mathbf{h} \|_2。约束条件 \| \mathbf{h} \|_2 = 1 等价于 \| \mathbf{z} \|_2 = 1

于是问题变为:
\min_{\mathbf{z}} \| \Sigma \mathbf{z} \|_2^2 \quad \text{subject to} \quad \| \mathbf{z} \|_2 = 1

矩阵 \Sigma 的形式为:
\Sigma = \text{diag}(\sigma_1, \sigma_2, \dots, \sigma_r, 0, \dots, 0)
其中 \sigma_1 \geq \sigma_2 \geq \dots \geq \sigma_r > 0,其余部分为零。

为了最小化 \| \Sigma \mathbf{z} \|_2^2\mathbf{z} 应对应于 \Sigma 中最小奇异值的位置。因此,最优解为:
\mathbf{h} = \mathbf{v}_n
其中 \mathbf{v}_nV 的最后一列(对应于最小奇异值的右奇异向量)。

3. 结果总结

对于A \mathbf{h} = 0 的齐次问题,非平凡解可以通过 SVD 求解:

  1. 计算 A 的奇异值分解 A = U \Sigma V^T
  2. \mathbf{h}V中对应最小奇异值的列向量。

4. 示例代码

以下是用 Python 实现的示例代码:

import numpy as np

# 示例矩阵 A
A = np.array([[1, 2, 3],
              [4, 5, 6],
              [7, 8, 9]])

# 计算 SVD
U, Sigma, Vt = np.linalg.svd(A)

# 最小奇异值对应的右奇异向量
h = Vt[-1, :]  # V 的最后一列是 Vt 的最后一行

print("非平凡解 h:")
print(h)

\mathbf{v}_n 为最小奇异值对应右奇异向量的数学推导

给定矩阵 A,我们希望求解线性系统A \mathbf{h} = 0 的非零解。由线性代数理论,该问题可转化为寻找 \mathbf{h} 使得:
\| A \mathbf{h} \|_2 = 0.

1. 将问题转化为\Sigma V^T \mathbf{h} = 0

\mathbf{h} \in \mathbb{R}^n,代入奇异值分解 A = U \Sigma V^T,有:
A \mathbf{h} = 0 \implies U \Sigma V^T \mathbf{h} = 0.

由于 U 是正交矩阵,其列向量为正交基,满足 \|U\mathbf{z}\|_2 = \|\mathbf{z}\|_2,因此对齐次方程的求解不会影响解的性质。等式两边左乘 U^T,化简得:
\Sigma V^T \mathbf{h} = 0.

\mathbf{g} = V^T \mathbf{h},有:
\Sigma \mathbf{g} = 0.

2. \mathbf{g} 的性质

根据 \Sigma 的结构,\Sigma \mathbf{g} = 0 等价于 \mathbf{g} 的非零解只可能出现在最小奇异值对应的方向上,即最后一列的奇异向量方向。此时:
\mathbf{g} = [0, 0, \dots, 1]^T.

回代 \mathbf{g} = V^T \mathbf{h} 可得:
\mathbf{h} = V \mathbf{g}.

结合 \mathbf{g} 的取值,\mathbf{h} 是矩阵 V 的最后一列 \mathbf{v}_n,即:
\mathbf{h} = \mathbf{v}_n.


Homography 矩阵求解

Homography 矩阵(单应性矩阵)描述了两个平面之间的点到点的投影关系,是计算图像变换(如透视变换)的核心工具。设两幅图像中的对应点为 [x, y][x', y'],它们满足以下关系:
\begin{bmatrix} x' \\ y' \\ 1 \end{bmatrix} = H \begin{bmatrix} x \\ y \\ 1 \end{bmatrix}

其中 H3 \times 3 的单应性矩阵,包含 8 个自由度(因比例因子可省略一个自由度)。


1. 问题定义

将齐次坐标展开后,得以下约束关系:
x' = \frac{h_{11}x + h_{12}y + h_{13}}{h_{31}x + h_{32}y + h_{33}}, \quad y' = \frac{h_{21}x + h_{22}y + h_{23}}{h_{31}x + h_{32}y + h_{33}}

移项并整理为线性方程:
\begin{aligned} h_{11}x + h_{12}y + h_{13} - h_{31}xx' - h_{32}yx' - h_{33}x' &= 0, \\ h_{21}x + h_{22}y + h_{23} - h_{31}xy' - h_{32}yy' - h_{33}y' &= 0. \end{aligned}

每对对应点 [x, y] \leftrightarrow [x', y'] 提供两条约束,求解 H 需要至少 4 对点(共 8 条约束)。

定义参数向量 \mathbf{h} = [h_{11}, h_{12}, \dots, h_{33}]^T,上述方程可以写成矩阵形式:
A \mathbf{h} = 0,
其中 A 是由点坐标构成的 2n \times 9 矩阵。


2. 使用 SVD 求解

要解方程 A \mathbf{h} = 0,采用齐次最小二乘法:

2.1 奇异值分解

对矩阵 A 进行奇异值分解(SVD):
A = U \Sigma V^T
其中:

  • U \in \mathbb{R}^{m \times m} 是正交矩阵,包含左奇异向量;
  • \Sigma \in \mathbb{R}^{m \times n} 是对角矩阵,包含奇异值;
  • V \in \mathbb{R}^{n \times n} 是正交矩阵,包含右奇异向量。

2.2 最优解

V 的最后一列(对应最小奇异值的右奇异向量)作为 \mathbf{h},即:
\mathbf{h} = \mathbf{v}_n,
将其重新排列为 3 \times 3 矩阵,得到 H


3. 归一化处理

由于 H 是齐次矩阵,不受比例因子的影响,计算结果常需要归一化处理。将 H 的元素整体除以 H_{33},使得:
H_{33} = 1.


4. 实现代码

以下是用 Python 实现 Homography 矩阵求解的代码:

import numpy as np

def compute_homography(points_src, points_dst):
    """
    计算单应性矩阵 H,使得 points_dst ≈ H * points_src。
    
    :param points_src: 源图像点坐标 (Nx2)
    :param points_dst: 目标图像点坐标 (Nx2)
    :return: 单应性矩阵 H (3x3)
    """
    assert points_src.shape == points_dst.shape, "点集尺寸不一致"
    assert points_src.shape[0] >= 4, "至少需要4对点"
    
    n = points_src.shape[0]
    A = []
    
    for i in range(n):
        x, y = points_src[i]
        x_prime, y_prime = points_dst[i]
        A.append([-x, -y, -1, 0, 0, 0, x*x_prime, y*x_prime, x_prime])
        A.append([0, 0, 0, -x, -y, -1, x*y_prime, y*y_prime, y_prime])
    
    A = np.array(A)
    
    # SVD 分解
    U, Sigma, Vt = np.linalg.svd(A)
    
    # 最小奇异值对应的右奇异向量
    H = Vt[-1, :].reshape((3, 3))
    
    # 归一化,使得 H[2, 2] = 1
    H /= H[-1, -1]
    return H

# 示例点
points_src = np.array([[0, 0], [1, 0], [1, 1], [0, 1]])
points_dst = np.array([[0, 0], [2, 0], [2, 2], [0, 2]])

H = compute_homography(points_src, points_dst)
print("单应性矩阵 H:")
print(H)

图片压缩

import cv2
import numpy as np

top_k = 360  # 保留的奇异值数量

# 读取彩色图像
image = cv2.imread("test.jpg")
print(image.shape)  # 输出图像的形状

# 分离颜色通道 (BGR)
blue_channel = image[:, :, 0]
green_channel = image[:, :, 1]
red_channel = image[:, :, 2]

# 对每个通道进行SVD
U_b, Sigma_b, Vt_b = np.linalg.svd(blue_channel, full_matrices=False)
U_g, Sigma_g, Vt_g = np.linalg.svd(green_channel, full_matrices=False)
U_r, Sigma_r, Vt_r = np.linalg.svd(red_channel, full_matrices=False)

# 保留前 top_k 个奇异值,并重构每个通道
Sigma_b = np.diag(Sigma_b[:top_k])
Sigma_g = np.diag(Sigma_g[:top_k])
Sigma_r = np.diag(Sigma_r[:top_k])

blue_reconstructed = np.dot(U_b[:, :top_k], np.dot(Sigma_b, Vt_b[:top_k, :]))
green_reconstructed = np.dot(U_g[:, :top_k], np.dot(Sigma_g, Vt_g[:top_k, :]))
red_reconstructed = np.dot(U_r[:, :top_k], np.dot(Sigma_r, Vt_r[:top_k, :]))

# 将重构的通道合并为一张彩色图像
new_image = np.stack([blue_reconstructed, green_reconstructed, red_reconstructed], axis=-1)

# 显示重构的彩色图像
cv2.imshow("Reconstructed Image", new_image.astype(np.uint8))
cv2.waitKey(0)
cv2.destroyAllWindows()

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,539评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,911评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,337评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,723评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,795评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,762评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,742评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,508评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,954评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,247评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,404评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,104评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,736评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,352评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,557评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,371评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,292评论 2 352

推荐阅读更多精彩内容