快速迭代收缩-阈值算法(FISTA)
文章目录
- 1. 数学与优化基础
- 2. FISTA 算法的原理、推导与机制
- 3. Matlab 实现
- 4. FISTA 在图像处理与压缩感知中的应用
- 4.1. 基于小波稀疏先验的图像去噪
- 4.2 压缩感知图像重建
1. 数学与优化基础
在许多信号处理与机器学习问题中,我们希望获得稀疏解,即解向量中非零元素很少。直接以 L0 “范数” (非零元素个数)作为稀疏性度量会导致非凸优化难题。一个常用的替代是采用 L1 范数(||x||1是各元素绝对值之和)作为正则项,它是 L0的凸松弛,可以鼓励稀疏解。与 L2 正则化不同,L1 正则化对小系数给予恒定的惩罚减少,这使得较小的系数更容易被压缩到0,从而产生稀疏性。简言之,L1 范数由于在零点处的尖锐拐角(梯度不连续)会诱导解的许多分量为零。
假设你有 5 个箱子,里面分别放了 x 1 , x 2 , x 3 , x 4 , x 5 x_1, x_2, x_3, x_4, x_5 x1,x2,x3,x4,x5 个苹果。L0“范数”就是这 5 个箱子里有苹果的箱子的数量。
- 若 x 2 = 0 , x 4 = 0 x_2 = 0, x_4 = 0 x2=0,x4=0,其它 3 个箱子里苹果不为 0,那么 L0 “范数”就是 3。
- 想要让 L0 变小,就要“尽量让更多箱子变成空箱子”,从而达到稀疏(空箱子越多,非零元素越少)。
- L0“范数”本身是不连续、不光滑的(要么 0,要么 1),在数学优化中很难直接求解(优化过程不易“沿着梯度”慢慢变化,一下跳零一下跳非零)。这会导致“最小化 L0”时比较棘手。
L1 范数是一个凸函数,有很好处理的数学性质(可以使用梯度或次梯度等优化算法)。虽然它并不会像 L0 一样“明确地”只算非零数量,但在最小化 L1 范数时,有很多解会自动出现“某些元素被压到正好为 0”——这就是所谓的“稀疏解”。依然用“箱子”来打比方。
- L1 范数就是把每个箱子里的苹果数量(绝对值)加起来之和,努力让这个总和尽量小。
- 当某个箱子里的苹果数量比较小,L1 优化就会倾向于“干脆把这个箱子的苹果数量压到 0”,以进一步降低总和。
- 于是就会出现类似 L0 的“有些箱子空了”的效果(稀疏解)。
L2 范数是各元素平方和的开方,即 ∥ x ∥ 2 = x 1 2 + x 2 2 + ⋯ + x n 2 \|x\|_2 = \sqrt{x_1^2 + x_2^2 + \cdots + x_n^2} ∥x∥2=x12+x22+⋯+xn2。它可以让解趋向于“总体较小”,但不会把任何一维直接压到完全 0。若还以箱子比方,L2 更像是在“平均地”减小每个箱子的苹果数量,而不会直接把其中某些箱子砍到空箱。
典型例子包括LASSO(最小绝对收缩选择算子)和**基础追踪(Basis Pursuit)**等,它们通过在最小二乘误差目标后加上 L1 范数惩罚来实现稀疏信号的估计。这种 L1 正则化问题属于凸优化,通常可转化为线性规划或二阶锥规划来求解。例如,有噪声情况下的基础追踪去噪(BPDN)和 LASSO 都考虑求解形如
min x 1 2 ∥ A x − b ∥ 2 2 + λ ∥ x ∥ 1 , \min_x \frac{1}{2}\|Ax - b\|_2^2 + \lambda \|x\|_1, xmin21∥Ax−b∥22+λ∥x∥1,
的凸问题,其中 λ 为权衡稀疏度的正则化参数。
像上面这样的目标函数 F ( x ) = f ( x ) + g ( x ) F(x) = f(x) + g(x) F(x)=f(x)+g(x) 中, f ( x ) = 1 2 ∥ A x − b ∥ 2 2 f(x)=\frac{1}{2}\|Ax - b\|_2^2 f(x)=21∥Ax−b∥22 是光滑凸函数,具有Lipschitz连续的梯度,而 g ( x ) = λ ∥ x ∥ 1 g(x)=\lambda\|x\|_1 g(x)=λ∥x∥1 是连续凸函数但在0点不可微。
凸函数的一个重要性质是局部极小即全局极小,这为设计算法提供了可靠性保障。
梯度下降法是求解光滑凸优化的基本一阶方法:反复沿负梯度方向迭代。对于二次损失这样的 f ( x ) f(x) f(x),梯度为 ∇ f ( x ) = A T ( A x − b ) \nabla f(x)=A^T(Ax - b) ∇f(x)=AT(Ax−b),直接的梯度迭代为 x ← x − η ∇ f ( x ) x \leftarrow x - \eta \nabla f(x) x←x−η∇f(x)。然而,当存在非光滑项 g ( x ) g(x) g(x)时(例如 L1 正则化),我们不能简单对其求梯度,而需借助次梯度或近端算法。
近端梯度(Proximal Gradient)方法通过引入近端算子来处理非光滑项,每步对光滑部分做梯度更新后,对非光滑部分应用一个近端映射(即求解一个带L2范数惩罚的最优问题)。对于 L1 项,其近端映射就是**软阈值(soft-thresholding)**操作,其公式为:
prox λ ∥ ⋅ ∥ 1 ( v i ) = { 0 , ∣ v i ∣ ≤ λ , v i − λ sign ( v i ) , ∣ v i ∣ > λ , \operatorname{prox}_{\lambda \|\cdot\|_1}(v_i) = \begin{cases}0, & |v_i| \le \lambda,\\ v_i - \lambda\,\operatorname{sign}(v_i), & |v_i| > \lambda~, \end{cases} proxλ∥⋅∥1(vi)={0,vi−λsign(vi),∣vi∣≤λ,∣vi∣>λ ,
即将向量 v v v 中每个分量按上述规则收缩。软阈值操作也通常写为 S λ ( v ) = sign ( v ) ⋅ max ( ∣ v ∣ − λ , 0 ) S_{\lambda}(v) = \operatorname{sign}(v)\cdot\max(|v|-\lambda,0) Sλ(v)=sign(v)⋅max(∣v∣−λ,0),把绝对值低于阈值 λ \lambda λ的系数设为0,其余系数减小 λ \lambda λ。软阈值是 L1 非光滑项的近端,因为它正是最小化 1 2 ∥ x − v ∥ 2 2 + λ ∥ x ∥ 1 \frac{1}{2}\|x-v\|_2^2 + \lambda\|x\|_1 21∥x−v∥22+λ∥x∥1 所得的解。这个操作在稀疏信号重建中可视为一种“去噪”步骤:减小信号中的小幅成分,同时保留/突出大幅成分,从而促进稀疏性。
2. FISTA 算法的原理、推导与机制
在引入 FISTA 前,先看其基础算法——迭代收缩阈值算法 (ISTA)。ISTA 是一种近端梯度下降方法,每次迭代包括一个梯度下降步骤和一个近端(软阈值)步骤。对目标 F ( x ) = f ( x ) + g ( x ) F(x)=f(x)+g(x) F(x)=f(x)+g(x),给定梯度Lipschitz常数为 L L L,ISTA 的每步更新可表示为:
- 梯度步: y k = x k − 1 − 1 L ∇ f ( x k − 1 ) y_{k} = x_{k-1} - \frac{1}{L}\nabla f(x_{k-1}) yk=xk−1−L1∇f(xk−1),即从上一步解 x k − 1 x_{k-1} xk−1 沿负梯度方向前进一步长度 1 / L 1/L 1/L。
- 近端步: x k = prox 1 L g ( y k ) x_k = \operatorname{prox}_{\frac{1}{L}g}(y_k) xk=proxL1g(yk),即对 y k y_k yk 应用非光滑项 g g g 的近端算子。如果 g ( x ) = λ ∥ x ∥ 1 g(x)=\lambda\|x\|_1 g(x)=λ∥x∥1,这一步就是对 y k y_k yk 进行软阈值 S λ / L ( y k ) S_{\lambda/L}(y_k) Sλ/L(yk)。
如此迭代产生序列 x k {x_k} xk 收敛于全局最优解。当 f f f 为Lipschitz光滑凸函数且 g g g 为凸函数时,ISTA 可保证 F ( x k ) F(x_k) F(xk) 以 O ( 1 / k ) O(1/k) O(1/k) 的速率逼近最优值。然而,ISTA 在实践中往往收敛较慢,需要大量迭代。
快速迭代收缩-阈值算法 (FISTA) 是 Beck 和 Teboulle (2009) 提出的对 ISTA 的加速改进。它借鉴了Nesterov在1983年提出的加速梯度思想,引入了动量项来加速收敛。具体来说,FISTA并不直接对上一次的解 x k − 1 x_{k-1} xk−1 进行近端梯度,而是构造一个加速序列 y k y_k yk,使其包含了前两次迭代解的线性组合信息。FISTA 的迭代步骤如下:
- 初始化: 取初始解 x 0 x_0 x0(可取零向量),设 y 1 = x 0 y_1 = x_0 y1=x0,并设动量参数 t 1 = 1 t_1 = 1 t1=1。
- 循环迭代: 对于 k = 1 , 2 , 3 , … k = 1, 2, 3, \dots k=1,2,3,…:
- (近端梯度步) 先对当前辅助变量 y k y_k yk 执行与 ISTA 相同的近端梯度更新: x k = prox 1 L g ( y k − 1 L ∇ f ( y k ) ) . x_k = \operatorname{prox}_{\frac{1}{L}g}\!\Big(y_k - \frac{1}{L}\nabla f(y_k)\Big). xk=proxL1g(yk−L1∇f(yk)). 对于 L1 情况,这一步仍是 x k = S λ / L ( y k − 1 L ∇ f ( y k ) ) x_k = S_{\lambda/L}\Big(y_k - \frac{1}{L}\nabla f(y_k)\Big) xk=Sλ/L(yk−L1∇f(yk))。
- (动量更新步) 计算新的动量系数: t k + 1 = 1 + 1 + 4 t k 2 2 t_{k+1} = \frac{1 + \sqrt{1+4t_k^2}}{2} tk+1=21+1+4tk2。然后更新加速序列: y k + 1 = x k + t k − 1 t k + 1 ( x k − x k − 1 ) . y_{k+1} = x_k + \frac{t_k - 1}{\,t_{k+1}\,}\,(x_k - x_{k-1}). yk+1=xk+tk+1tk−1(xk−xk−1). 这一步利用了当前解 x k x_k xk和前一步解 x k − 1 x_{k-1} xk−1的线性组合来得到新的搜索点 y k + 1 y_{k+1} yk+1。
可以看出,与 ISTA 每次仅利用 x k − 1 x_{k-1} xk−1 来迭代不同,FISTA 在 y k + 1 y_{k+1} yk+1 中加入了 ( x k − x k − 1 ) (x_k - x_{k-1}) (xk−xk−1)项,也就是利用最近两次迭代的解的差值作为“动量”。这种设计看似“魔法般”, 实则源自对迭代过程几何性质的精巧分析。通过恰当选择 t k t_k tk 序列( t k t_{k} tk 的递推形式来源于求解二次方程,保证后续分析中一个递推不等式的最优收敛速率),FISTA 能在理论上将收敛速度提升一个数量级。
FISTA 保持了与 ISTA 相近的每步计算复杂度,但其全局收敛速率提高到 O ( 1 / k 2 ) O(1/k^2) O(1/k2)。也就是说,达到同样精度所需的迭代次数大大减少。具体定理表明:对于 k ≥ 1 k\ge1 k≥1, F ( x k ) − F ( x ∗ ) ≤ 2 L ∥ x 0 − x ∗ ∥ 2 ( k + 1 ) 2 , F(x_k) - F(x^*) \le \frac{2L \,\|x_0 - x^*\|^2}{(k+1)^2}, F(xk)−F(x∗)≤(k+1)22L∥x0−x∗∥2, 其中 x ∗ x^* x∗为最优解, L L L为 ∇ f \nabla f ∇f的Lipschitz常数。相较之下,ISTA只有 O ( 1 / k ) O(1/k) O(1/k) 的渐进速率。因此在大量迭代后,FISTA 会显著优于 ISTA。
引入的辅助序列 y k y_k yk 可以看作在常规梯度下降基础上添加了一种“加速动量”策略,类似于物理中的动量累积,使算法在谷底附近不至于过于保守地缓慢逼近,而是带着惯性前进,从而快速逼近最优解。这与Nesterov加速梯度法在纯光滑优化中的作用类似。
下面用伪代码总结 FISTA 的核心步骤:
% 给定A, b, 正则权重lambda, Lipschitz常数L, 初始化x0
x = x0;
y = x0;
t = 1;
for k = 1:MaxIter% 近端梯度步:梯度下降 + 软阈值grad = A'*(A*y - b); % 计算∇f(y) = A^T(Ay - b)x_new = sign(y - grad/L) .* max(abs(y - grad/L) - lambda/L, 0);% 动量更新步t_new = (1 + sqrt(1 + 4*t^2)) / 2;y = x_new + ((t - 1) / t_new) * (x_new - x);% 更新迭代变量x = x_new;t = t_new;
end
上述代码实现了不带回溯的 FISTA 算法框架:首先计算基于当前 y y y 的梯度下降点,然后对其应用软阈值(对应 prox λ / L \operatorname{prox}_{\lambda/L} proxλ/L 操作),接着根据动量公式更新 y y y。经过多次迭代, x x x 将收敛到稀疏解。值得注意的是,该算法需要估计合理的 L L L(例如,可取 L = ∣ A T A ∣ L=|A^T A| L=∣ATA∣ 的最大特征值)。若 L L L 不易获得,也可以在每步迭代中采用回溯线搜索调整步长,这也是 FISTA 论文中提到的变体,但基本思想不变。
FISTA 的详尽收敛性证明较为复杂,涉及构造恰当的辅助序列和能量函数。其核心在于证明 y k y_k yk 的选取使得 F ( x k ) − F ( x ∗ ) F(x_k) - F(x^*) F(xk)−F(x∗) 符合所需的 O ( 1 / k 2 ) O(1/k^2) O(1/k2) 上界。这里不赘述完整推导,但强调两点:(1) t k t_{k} tk 的递推形式 1 + 1 + 4 t k 2 2 \frac{1+\sqrt{1+4t_k^2}}{2} 21+1+4tk2 是精心设计的,使得动量项权重逐渐减小,避免过冲;(2) FISTA 的形式也可从将 Nesterov 加速应用于 ISTA 的等价形式推导得到,一些后续研究表明FISTA可以被视为对近端梯度法在最坏情况下加速的“最优”方法。
3. Matlab 实现
假设我们要解决一个简单的压缩感知重建问题: A x ≈ b Ax \approx b Ax≈b,其中 A A A 是测量矩阵, b b b 是观测到的信号,我们希望通过最小化 F ( x ) = 1 2 ∥ A x − b ∥ 2 2 + λ ∥ x ∥ 1 F(x)=\frac{1}{2}\|Ax-b\|_2^2 + \lambda\|x\|_1 F(x)=21∥Ax−b∥22+λ∥x∥1 来求得稀疏解 x x x。FISTA 可高效地求解此问题。
Matlab 函数构造:
function x = FISTA_L1(A, b, lambda, L, maxIter)% 初始化x = zeros(size(A,2), 1); % 初始解 x0y = x; t = 1; for k = 1:maxIter% 计算梯度并执行梯度下降一步grad = A' * (A * y - b);z = y - (1/L) * grad;% 执行 L1 近端(软阈值)操作x_new = sign(z) .* max(abs(z) - lambda/L, 0);% 更新动量系数和辅助变量t_new = (1 + sqrt(1 + 4 * t^2)) / 2;y = x_new + ((t - 1) / t_new) * (x_new - x);% 准备下次迭代x = x_new;t = t_new;end
end
上述函数 FISTA_L1
实现了 FISTA 的主要迭代流程。其中:
- 初始化部分,将初始解设为全零向量,并初始化辅助变量 y = x y=x y=x 及动量参数 t = 1 t=1 t=1。
- 每次迭代首先计算当前 y y y 下的梯度
grad
,对应 ∇ f ( y ) = A T ( A y − b ) \nabla f(y)=A^T(Ay - b) ∇f(y)=AT(Ay−b)。 - 然后令
z = y - (1/L)*grad
,这一步是普通梯度下降的结果。 - 接着对
z
执行软阈值:x_new = sign(z).*max(abs(z)-lambda/L, 0)
,得到当前迭代的稀疏估计 x k x_k xk。 - 计算新的动量系数
t_new
并更新辅助变量:y = x_new + ((t-1)/t_new)*(x_new - x)
,对应 y k + 1 = x k + t k − 1 t k + 1 ( x k − x k − 1 ) y_{k+1} = x_k + \frac{t_k-1}{t_{k+1}}(x_k - x_{k-1}) yk+1=xk+tk+1tk−1(xk−xk−1)。 - 循环更新直到达到最大迭代次数(或其它收敛判据,如迭代前后 ∣ x ∣ |x| ∣x∣相对变化很小)。
使用该函数时,需要提供合理的 L L L(一般可取为 A T A A^TA ATA 的最大特征值近似)。这里我们可以测试一个小例子:生成随机高斯矩阵 A A A 以及稀疏的真实信号 x true x_{\text{true}} xtrue,计算 b = A x true b=A x_{\text{true}} b=Axtrue(可加噪声),然后调用 FISTA_L1(A,b,lambda,L,maxIter)
重建,并与真值比较。
%% FISTA_L1_demo.m
% 使用 FISTA + L1 进行稀疏信号重建。clear; clc; close all;%% 准备数据
rng('default'); % 固定随机种子,方便复现
m = 80; % 测量数
n = 100; % 信号长度
A = randn(m, n); % 随机生成测量矩阵 A% 生成一个稀疏的 x_true
k0 = 10; % 希望的非零项数
permIdx = randperm(n); % 随机打乱下标
supp = permIdx(1:k0);
x_true = zeros(n,1);
x_true(supp)= randn(k0,1); % 在这 k0 个位置上放一些随机值% 生成观测 b
b = A * x_true;%% 设置 FISTA 参数
lambda = 0.1; % L1 惩罚系数
[U, S, ~] = svd(A, 'econ');
L = max(diag(S))^2; % 步长倒数,近似取 A 的最大奇异值平方
maxIter = 100; % 最大迭代次数%% 调用 FISTA_L1 求解
x_est = FISTA_L1(A, b, lambda, L, maxIter);%% 比较结果
recovery_error = norm(x_est - x_true) / norm(x_true);
fprintf('重建相对误差 = %.4e\n', recovery_error);%% 作图比较 x_true 与 x_est
figure('Name', 'FISTA-L1 Reconstruction', 'NumberTitle', 'off');
plot(1:n, x_true, '-o', 'LineWidth', 1.5);
hold on;
plot(1:n, x_est, '--', 'LineWidth', 1.5);grid on;
legend('x\_true', 'x\_est', 'Location', 'best');
xlabel('Index (n)');
ylabel('Signal Value');
title('FISTA + L1 Sparse Reconstruction');% 设置坐标轴字体
set(gca, 'FontName', 'Times New Roman', 'FontSize', 13);
用到的函数如下
function x = FISTA_L1(A, b, lambda, L, maxIter)
% FISTA_L1 使用 FISTA 迭代来求解
% min_x 0.5*||A*x - b||^2 + lambda * ||x||_1
%
% 输入:
% A, b 线性系统和观测
% lambda L1 惩罚系数
% L 步长因子,通常可取近似的最大特征值 A'*A
% maxIter 最大迭代次数
%
% 输出:
% x 稀疏重建后的解向量% 初始化x = zeros(size(A,2),1); % 初始解 x0y = x; % 初始化辅助变量 yt = 1; % 动量参数 t0for k = 1:maxIter% 计算梯度 grad = A'*(A*y - b)grad = A' * (A*y - b);% 常规梯度下降一步: z = y - (1/L)*gradz = y - (1/L)*grad;% 执行软阈值(shrinkage)操作,得到 x_newx_new = sign(z) .* max(abs(z) - lambda/L, 0);% 更新动量参数 t_newt_new = (1 + sqrt(1 + 4*t^2)) / 2;% 更新辅助变量 yy = x_new + ((t - 1)/t_new) * (x_new - x);% 准备下一次迭代x = x_new;t = t_new;end
end
结果如下:
4. FISTA 在图像处理与压缩感知中的应用
FISTA 自提出以来已在图像处理领域的诸多逆问题中显示出强大能力,包括去去噪、欠采样重建等。其优势在于算法简单、易于实现,却又兼具接近于最优的一阶收敛速度,使其非常适合求解大规模问题。下面结合具体应用谈几点:
4.1. 基于小波稀疏先验的图像去噪
我们将把去噪问题写成
min x 1 2 ∥ x − y ∥ 2 2 + λ ∥ W x ∥ 1 \min_{x}\;\frac12\|x - y\|_2^2 \;+\;\lambda\|W x\|_1 xmin21∥x−y∥22+λ∥Wx∥1
其中
- y y y 是加噪图像
- W W W 是二维小波变换算子
- λ \lambda λ 是稀疏惩罚参数
对于这个问题,
- f ( x ) = 1 2 ∥ x − y ∥ 2 f(x)=\frac12\|x-y\|^2 f(x)=21∥x−y∥2,梯度 ∇ f ( x ) = x − y \nabla f(x)=x-y ∇f(x)=x−y,Lipschitz 常数 L = 1 L=1 L=1。
- g ( x ) = λ ∥ W x ∥ 1 g(x)=\lambda\|W x\|_1 g(x)=λ∥Wx∥1,其近端算子就是对小波系数做软阈值。
实现上述去噪问题的主函数为
function x = fista_wavelet_denoise(y, lambda, waveletName, levels, maxIter)
%FISTA_WAVELET_DENOISE 用 FISTA+小波稀疏做图像去噪
% 输入:
% y - 加噪图像(二维灰度,double)
% lambda - 惩罚系数
% waveletName - 小波类型,如 'db4'
% levels - 分解层数
% maxIter - 最大迭代次数
% 输出:
% x - 去噪后图像% 参数检查if nargin<5, maxIter = 200; end% 初始化xk = y;yk = xk;tk = 1;L = 1; % f 的 Lipschitz 常数% 预分解一次(仅获取尺寸)[C0, S] = wavedec2(yk, levels, waveletName);for k = 1:maxIter% —— 1. 梯度步 —— grad = yk - y; % ∇f(yk)zk = yk - (1/L)*grad; % 梯度下降% —— 2. 近端步 —— 小波域软阈值 —— C = wavedec2(zk, levels, waveletName);Cthr = soft_thresh(C, lambda/L);x_next = waverec2(Cthr, S, waveletName);% —— 3. FISTA 加速步 —— t_next = (1 + sqrt(1 + 4*tk^2))/2;y_next = x_next + ((tk-1)/t_next)*(x_next - xk);% 更新xk = x_next;yk = y_next;tk = t_next;endx = xk;
end
上面用到的软阈值函数为:
function z = soft_thresh(v, thresh)
%SOFT_THRESH 对向量 v 执行元素级软阈值z = sign(v) .* max(abs(v) - thresh, 0);
end
然后我们就可以测试这个去噪程序了,如下
%% demo_fista_denoise.m
clc; clear; close all;% 1. 读取并归一化
I = im2double(imread('cameraman.tif'));% 2. 加高斯噪声
sigma = 0.05;
yn = I + sigma*randn(size(I));% 3. 参数设置
lambda = 0.1; % 惩罚强度,可根据噪声调节
waveletName = 'db4'; % Daubechies4 小波
levels = 3; % 分解层数
maxIter = 100; % 迭代次数% 4. 运行 FISTA 去噪
xd = fista_wavelet_denoise(yn, lambda, waveletName, levels, maxIter);% 5. 显示对比
figure('Position',[100 100 800 300]);
subplot(1,3,1);
imshow(I); title('原始图像');
subplot(1,3,2);
imshow(yn); title(['加噪图像 (σ=',num2str(sigma),')']);
subplot(1,3,3);
imshow(xd); title('FISTA+小波 去噪结果');
4.2 压缩感知图像重建
在压缩感知(Compressed Sensing, CS)框架中,我们以远低于奈奎斯特采样率的线性测量来重建图像。经典CS理论指出,当图像在某种域(如小波)是稀疏的时,可以通过求解 L1 正则化的凸优化精确重建图像。FISTA 正是求解这类问题的理想算法之一。举例来说,在MRI成像中采集不完备k空间数据时,常建立 min x 1 2 ∥ A x − b ∥ 2 + λ ∥ W ( x ) ∥ 1 \min_x \frac{1}{2}\|Ax-b\|^2 + \lambda \|W(x)\|_1 minx21∥Ax−b∥2+λ∥W(x)∥1( W ( x ) W(x) W(x)表示小波变换系数)模型来重建图像;实践表明利用FISTA求解该模型能够在保持高重建质量的同时大幅减少迭代时间。即使在深度学习蓬勃发展的今天,研究者仍关注传统CS重建的潜力,通过合理优化,经典L1-范数重建在某些情况下仍然有竞争力。这也证明了FISTA等算法在成像领域的持久价值。
我们以最简单的“稀疏先验+小波变换”为例,解决
min x 1 2 ∥ Φ x − y ∥ 2 2 + λ ∥ W x ∥ 1 , \min_{x}\;\frac12\|\Phi x - y\|_2^2 \;+\;\lambda\|W x\|_1, xmin21∥Φx−y∥22+λ∥Wx∥1,
其中
- x ∈ R N x\in\mathbb{R}^N x∈RN 是待重建的灰度图像(展开成向量),
- Φ ∈ R M × N \Phi\in\mathbb{R}^{M\times N} Φ∈RM×N 是测量矩阵( M ≪ N M\ll N M≪N),
- y ∈ R M y\in\mathbb{R}^M y∈RM 是测量向量,
- W W W 和 W − 1 W^{-1} W−1 分别是二维小波变换算子和其逆算子。
实现上述稀疏重建的主函数为
function x_rec = fista_cs_wavelet(Phi, y, lambda, waveletName, levels, imgSize, opts)
%FISTA_CS_WAVELET 用 FISTA+小波稀疏做压缩传感重建
% 输入:
% Phi - M×N 测量矩阵
% y - M×1 测量向量
% lambda - 稀疏惩罚系数
% waveletName - 小波类型,如 'db4'
% levels - 小波分解层数
% imgSize - [h, w] 原图高宽
% opts - 可选结构体
% .maxIter (默认 200)
% .tol (默认 1e-4)
% 输出:
% x_rec - 重建后图像(h×w)if nargin<7, opts = struct(); endif ~isfield(opts,'maxIter'), opts.maxIter = 200; endif ~isfield(opts,'tol'), opts.tol = 1e-4; end% 初始化N = prod(imgSize);xk = zeros(N,1);yk = xk;tk = 1;L = norm(Phi,2)^2; % Lipschitz 常数% 预计算小波分解结构[~, S] = wavedec2(reshape(yk,imgSize), levels, waveletName);for k = 1:opts.maxIter% 1) 梯度下降grad = Phi'*(Phi*yk - y);z = yk - (1/L)*grad;% 2) 小波软阈值Cz = wavedec2(reshape(z,imgSize), levels, waveletName);Cthr = soft_thresh(Cz, lambda/L);x_next = waverec2(Cthr, S, waveletName);x_next = x_next(:);% 3) FISTA 加速t_next = (1 + sqrt(1 + 4*tk^2)) / 2;y_next = x_next + ((tk - 1)/t_next)*(x_next - xk);% 收敛判断if norm(x_next - xk) < opts.tolxk = x_next; break;end% 更新xk = x_next;yk = y_next;tk = t_next;end% 输出重建图像x_rec = reshape(xk, imgSize);
end
然后我们就可以用于演示一个采样率为50%的图像重建,
% demo_fista_cs.m
clc; clear; close all;% 1. 原始图像及展平
I = im2double(imread('cameraman.tif'));
I = imresize(I, 0.25);
imgSize = size(I);
x_true = I(:);% 2. 构造测量矩阵 Φ(随机高斯或 0/1 伯努利)
M = round(0.5 * numel(x_true)); % 50% 采样率
Phi = randn(M, numel(x_true));
Phi = bsxfun(@rdivide, Phi, sqrt(sum(Phi.^2,2))); % 每行归一化% 3. 生成测量 y
noise_sigma = 1e-3;
y = Phi * x_true + noise_sigma*randn(M,1);% 4. 重建参数
lambda = 0.01;
waveletName = 'db4';
levels = 3;
opts.maxIter= 300;
opts.tol = 1e-5;% 5. 调用 FISTA-CS 重建
tic;
x_rec = fista_cs_wavelet(Phi, y, lambda, waveletName, levels, imgSize, opts);
toc;% 6. 显示结果
figure('Position',[100 100 900 300]);
subplot(1,2,1);
imshow(I); title('原始图像');
subplot(1,2,2);
imshow(x_rec,[]); title('FISTA-CS 重建');
相关文章:
快速迭代收缩-阈值算法(FISTA)
文章目录 1. 数学与优化基础2. FISTA 算法的原理、推导与机制3. Matlab 实现4. FISTA 在图像处理与压缩感知中的应用4.1. 基于小波稀疏先验的图像去噪4.2 压缩感知图像重建 1. 数学与优化基础 在许多信号处理与机器学习问题中,我们希望获得稀疏解,即解向…...
XC6SLX100T-2FGG484I 赛灵思 XilinxFPGA Spartan-6
XC6SLX100T-2FGG484I 是Xilinx 推出的Spartan-6 LXT 系列FPGA芯片,采用45nm工艺设计,以高性价比和低功耗为核心 系列定位:Spartan‑6 LXT,中端逻辑与 DSP 加速 逻辑资源:101 261 个逻辑单元(LE࿰…...
DP 32bit位宽数据扰码实现和仿真
关于DisplayPort 1.4协议中扰码用的16-bit LFSR的移位8个时钟周期后的输出表达式我们已经用迭代的方法推导过,那么移位32个时钟周期的输出表达式同样可以迭代32次推导出,或者将移位8个时钟的输出表达式迭代3次也可以得到。以下就是移位32个时钟周期的输出…...
Electricity Market Optimization 探索系列(V)
本文参考链接link \hspace{1.6em} 众所周知, 社会福利是指消费者剩余和生产者剩余的和,也等价于产品的市值减去产品的成本,在电力市场中也非常关注社会福利这一概念,基于电力商品的同质性的特点,我们引入反价格需求函数来形象地刻…...
vue3 element-plus el-time-picker控制只显示时 分,并且控制可选的开始结束时间
只显示时分 控制只显示时分 HH:mm 控制只显示时分秒 HH:mm:ss 全部代码: <template><el-time-pickerstyle"width: 220px !important;"v-model"timeValue"format"HH:mm"value-format"HH:mm"/> </template&…...
从技术本质到未来演进:全方位解读Web的过去、现在与未来
一、Web的本质定义 Web(万维网)是一种基于**超文本传输协议(HTTP)和统一资源标识符(URI)**构建的分布式信息系统。它的核心在于通过超链接将全球范围内的信息资源连接成网状结构,使任何接入互联网的设备都能访问这些资源。Web的本质特征体现在三个方面: 跨平台性:无论…...
C++十进制与十六进制
在C中,可以使用不同的方式来表示十进制和十六进制数值。下面是一个简单的示例代码,展示了如何在C中表示和输出十进制和十六进制数值: #include <iostream> #include <iomanip>int main() {int decimalValue 255; // 十进制数值…...
MySQL基本语法
本地登录:mysql -u 用户名 -p 查看数据库:show databeases 创建库:create database 名字; 删除库:drop database 名字; 选择库:use 名字; 创建表:create table 表名 在…...
机器学习有多少种算法?当下入门需要全部学习吗?
机器学习算法如同工具箱中的器械——种类繁多却各有专攻。面对数百种公开算法,新手常陷入"学不完"的焦虑。本文将拆解算法体系,为初学者指明高效学习路径。 一、算法森林的全景地图 机器学习算法可按四大维度分类: 监督学习&#…...
【c语言】深入理解指针2
文章目录 一、指针数组指针数组模拟二维数组 二、数组指针二维数组传参的本质 三、字符指针变量四、函数指针变量4.1. 函数指针的应用4.2 两端有趣的代码4.3. typedef关键字4.3.1 typedef 的使用4.3.2. typedef与#define对比 五、函数指针数组函数指针数组的应用 一、指针数组 …...
Nacos
Nacos是阿里巴巴的产品, 现在是SpringCloud中的一个组件。相比Eureka功能更加丰富,在国内受欢迎程度较高。 官网地址:Redirecting to: https://nacos.io/ GitHub: https://github.com/alibaba/nacos 1.Nacos快入门 Nacos可以直…...
Linux,redis群集模式,主从复制,读写分离
redis的群集模式 主从模式 (单项复制,主复制到从) 一主两从 一台主机上的一主两从 需要修改三个配置文件 主要端口不一样 redis-8001.conf redis-8002.conf redis-8003.conf 哨兵模式 分布式集群模式 redis 安装部署 1,下载…...
《手环表带保养全攻略:材质、清洁与化学品避坑指南》
系列文章目录 文章目录 系列文章目录前言一、表带材质特性与专属养护方案二、清洁剂使用红黑榜三、家庭清洁实验:化学反应警示录四、保养实践方法论总结 前言 手环作为现代生活的智能伴侣,表带材质选择丰富多样。从柔软亲肤的皮质到耐用耐磨的金属&…...
【Leetcode 每日一题 - 补卡】1534. 统计好三元组
问题背景 给你一个整数数组 a r r arr arr,以及 a 、 b 、 c a、b 、c a、b、c 三个整数。请你统计其中好三元组的数量。 如果三元组 ( a r r [ i ] , a r r [ j ] , a r r [ k ] ) (arr[i], arr[j], arr[k]) (arr[i],arr[j],arr[k]) 满足下列全部条件ÿ…...
医疗设备预测性维护合规架构:从法规遵循到技术实现的深度解析
在医疗行业数字化转型加速推进的当下,医疗设备预测性维护已成为提升设备可用性、保障医疗安全的核心技术。然而,该技术的有效落地必须建立在严格的合规框架之上。医疗设备直接关乎患者生命健康,其维护过程涉及医疗法规、数据安全、质量管控等…...
如何在 IntelliJ IDEA 中安装 FindBugs-IDEA 1.0.1
以下是 FindBugs-IDEA 1.0.1 插件在 IntelliJ IDEA 中的安装步骤(适用于较旧版本的 IDEA,新版本可能需使用替代插件如 SpotBugs): 方法一:手动下载安装(适用于无法通过市场安装的情况) 下载插件…...
小车正常但是加载不出地图 找不到mapserver
Request for map failed; trying again... 找不到mapserver 原因: bash [ERROR] [1744895448.714854952]: failed to open image file "/home/liyb/catkin_ws/src/nav_demo/map/crossing.pgm": Couldnt open /home/xxx/catkin_ws/src/nav_demo/map/cr…...
无头开发模式
“无头”开发模式(Headless Development Mode)是指在没有直接连接物理显示器(monitor)、键盘或鼠标等输入输出设备的情况下,通过远程工具(如 SSH、SCP、rsync、VNC 或 Web 界面)对设备进行开发、…...
DAY 47 leetcode 232--栈与队列.用栈实现队列
题号232 请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty): class MyQueue {Stack<Integer> stackIn;Stack<Integer> stackOut;/** Initialize your data structure here. */pu…...
SpringAI+DeepSeek大模型应用开发——4 对话机器人
目录 项目初始化 pom文件 配置模型 ChatClient 同步调用 流式调用 日志功能 对接前端 解决跨域 会话记忆功能 ChatMemory 添加会话记忆功能 会话历史 管理会话id 保存会话id 查询会话历史 完善会话记忆 定义可序列…...
leetcode0058. 最后一个单词的长度-easy
1 题目:最后一个单词的长度 官方标定难度:易 给你一个字符串 s,由若干单词组成,单词前后用一些空格字符隔开。返回字符串中 最后一个 单词的长度。 单词 是指仅由字母组成、不包含任何空格字符的最大子字符串。 示例 1&#x…...
深入理解 Linux top 命令:从字段解读到性能诊断
系统或产品都需要部署到服务器或容器上运行,而服务器的运行效率直接影响到系统的稳定性和用户体验。因此,服务器的性能监控与分析就显得尤为重要。 在实际运维和性能测试过程中,我们可以从以下关键的几个方面入手进行系统监控与分析(网络延迟分析暂时先略过): CPU 使用率…...
[特殊字符] UnionFS(联合文件系统)原理解析:容器背后的存储技术
🔍 UnionFS(联合文件系统)原理解析:容器背后的存储技术 💡 什么是 UnionFS? UnionFS(联合文件系统) 是一种可以将多个不同来源的文件系统“合并”在一起的技术。它的核心思想是&am…...
部署若依前后端分离
参考部署:https://blog.csdn.net/qq_46073825/article/details/128716794?spm1001.2014.3001.5502 1.连接mysql(windows版本) 2.更新数据库用户为远程可连接 3.redis下载地址 https://github.com/tporadowski/redis/releases 5执行npm init 或者npm install --r…...
用Python Pandas高效操作数据库:从查询到写入的完整指南
一、环境准备与数据库连接 1.1 安装依赖库 pip install pandas sqlalchemy psycopg2 # PostgreSQL # 或 pip install pandas sqlalchemy pymysql # MySQL # 或 pip install pandas sqlalchemy # SQLite 1.2 创建数据库引擎 通过SQLAlchemy创建统一接口:…...
eventBus 事件中心管理组件间的通信
EventBus(事件总线)是Vue中用于实现非父子组件间通信的轻量级方案,通过一个中央Vue实例管理事件的发布与订阅。 一、基本使用步骤 1.创建EventBus实例 推荐单独创建文件(如event-bus.js)导出实例,避免全…...
某客户ORA-600 导致数据库反复重启问题分析
上班期间,收到业务反馈,测试环境数据库连接报错。 查看数据库alert日志,发现从中午的时候就出现了重启。并且在17时20分左右又发生了重启: 同时,在重启前alert日志中出现了ORA-600报错,相关报错在trc文件中…...
LeetCode 2176.统计数组中相等且可以被整除的数对:两层遍历模拟
【LetMeFly】2176.统计数组中相等且可以被整除的数对:两层遍历模拟 力扣题目链接:https://leetcode.cn/problems/count-equal-and-divisible-pairs-in-an-array/ 给你一个下标从 0 开始长度为 n 的整数数组 nums 和一个整数 k ,请你返回满足…...
Vue项目Webpack Loader全解析:从原理到实战配置指南
Vue项目Webpack Loader全解析:从原理到实战配置指南 前言 在Vue项目的开发与构建中,Webpack Loader扮演着资源转换的核心角色。无论是单文件组件(SFC)的解析、样式预处理,还是静态资源的优化,都离不开Loa…...
Vscode --- LinuxPrereqs │远程主机可能不符合 glibc 和 libstdc++ Vs code 服务器的先决条件
打开vscode连接远程linux服务器,发现连接失败,并出现如下报错信息: 原因是: vscode 官网公告如下:2025 年 3 月 (版本 1.99) - VSCode 编辑器 版本1.97 官网公告如下:链接 版本1.98 官网公告如下&am…...
大数据常见的模型定义及应用场景建议╮(╯▽╰)╭
以下是常见的大数据模型类型及其分析方法: 1. 描述性模型 1.1 定义 描述性模型:用于描述数据的现状和历史趋势,帮助理解数据的特征和模式。 1.2 常见模型 统计摘要:均值、中位数、标准差等。数据可视化:直方图、散…...
红宝书第四十八讲:实时通信双雄:Socket.IO Meteor 的奇妙旅程
红宝书第四十八讲:实时通信双雄:Socket.IO & Meteor 的奇妙旅程 资料取自《JavaScript高级程序设计(第5版)》。 查看总目录:红宝书学习大纲 一、实时通信基础 1. WebSocket与HTTP对比 传统HTTP请求类似送信&…...
【数字图像处理】图像分割(1)
图像分割定义 把图像分成若干个特定的、具有独特性质的区域,并提出感兴趣目标的技术和过程 图像分割概述 一幅图像通常是由代表物体的图案与背景组成,简称物体与背景 图像分割的本质:将图像按照区域内的一致性和区域间的不一致性进行分类的过…...
VFlash的自动化和自定义动作
文章目录 一、automation 自动化二、custom actions 自定义动作常用方法如何选择要发送的诊断请求CustomActionValueList 作用Pre Action和Post Action之间交换信息 提示:如何打印软件中变量报错:无法打开源文件 Windows.h stdio.h conio.h报错ÿ…...
pytorch学习02
自动微分 自动微分模块torch.autograd负责自动计算张量操作的梯度,具有自动求导功能。自动微分模块是构成神经网络训练的必要模块,可以实现网络权重参数的更新,使得反向传播算法的实现变得简单而高效。 1. 基础概念 张量 Torch中一切皆为张…...
TV板卡维修技术【四】
【一】热成像松香的结合快速定位短路位置 发现电路短路,但是无法定位到大概位置,可以采用烧机法: 热成像大致定位,松香准确定位: 可以很快找到这种小陶瓷电容短路的故障: 测量电路是否有大短路,…...
Rust生命周期、文件与IO
文章目录 Rust生命周期生命周期注释结构体如何使用字符串静态生命周期 Rust文件与IO接收命令行参数命令行输入文件读取文件写入 Rust生命周期 终于讲到Rust最重要的机制之一了,生命周期机制 我们先复习一下垂悬引用 {let r;{let x 5;r &x;}println!("…...
22、字节与字符的概念以及二者有什么区别?
1、概念 字节(byte) 定义:字节是计算机信息技术中用于计量存储容量和传输容量的一种单位,通常由8个二进制位(bit)组成。 作用:字节是计算机存储和处理信息的基本单位,用于衡量数据…...
APP端测试
一、功能测试 1. 核心测试点 安装/卸载/升级:验证不同安装方式(应用商店/APK/IPA) 注册登录:多种登录方式测试(手机号、第三方账号) 核心业务流程:支付流程、内容发布等关键路径 中断测试&a…...
Langchain-构建向量数据库和检索器
向量数据库安装 pip install langchain-chroma 文档》向量存储》向量数据库。 和0416 提示词工程相同。 初始化 import osfrom langchain_chroma import Chroma from langchain_community.chat_message_histories import ChatMessageHistory from langchain_core.documents im…...
PPT无法编辑怎么办?原因及解决方法全解析
在日常办公中,我们经常会遇到需要编辑PPT的情况。然而,有时我们会发现PPT文件无法编辑,这可能由多种原因引起。今天我们来看看PPT无法编辑的几种常见原因,并提供实用的解决方法,帮助你轻松应对。 原因1:文…...
PH热榜 | 2025-04-17
1. Mailgo 标语:一款利用人工智能的冷邮件平台,能够提升邮件送达率。 介绍:Mailgo将AI线索寻找助手、智能日程安排和预热账户集成到一个直观的平台上——帮助销售团队和创业者高效到达客户邮箱,轻松扩展业务,并加快转…...
maptalks矩形绘制结束后,获取最大经度最大纬度,最小经度最小纬度,从左上角开始依次获取并展示坐标
maptalks矩形绘制结束后,获取最大经度最大纬度,最小经度最小纬度,从左上角开始依次获取并展示坐标 重点 // 获取绘制的矩形图形对象const rectangle param.geometry;// 获取矩形外接矩形范围(西南角/东北角坐标)cons…...
网页图像优化:现代格式与响应式技巧
网页图像优化:现代格式与响应式技巧 网页图像如果处理不好,很容易拖慢加载速度,影响用户体验。这篇文章聊聊怎么用现代图像格式和响应式技巧,让你的网站图片加载更快、效果更好。 推荐的图像格式 选对图像格式,能在保…...
python中参数前**的含义
在Python中,参数前的 ** 表示该参数是一个“关键字参数”或者说是“可变关键字参数”。这种参数允许函数接受任意数量的关键字参数,并将这些参数存储在一个名为**kwargs的字典中。这使得函数可以接收任意数量的键值对参数,这在编写需要处理多…...
内存编码手册:整数与浮点数的二进制世界
1.整数在内存中的存储 之前在学习操作符的博文中,我们就已经学习了整数在内存中存储的一些基本知识,我们来快速回忆一下,并开始学习新的知识。 之前的学习中,我们知道整数的二进制表示方法有三种,即原码,…...
铷元素的市场供需情况如何?
铷元素的市场供需格局呈现出显著的稀缺性与战略价值,其供应高度依赖锂矿开采的副产品,而需求则随着高科技产业的快速发展持续攀升。以下从供应、需求、价格、政策及可持续性五个维度展开分析: 一、供应端:资源稀缺与技术瓶颈并存…...
MATLAB 程序实现了一个层次化光网络的数据传输模拟系统
% 主程序 num_pods = 4; % Pod 数量 num_racks_per_pod = 4; % 每个 Pod 的 Rack 数量 num_nodes_per_rack = 4; % 每个 Rack 的 Node 数量 max_wavelength = 50; % 可用波长数(根据冲突图动态调整) num_packets = 1000; % 模拟的…...
LFI to RCE
LFI不止可以来读取文件,还能用来RCE 在多道CTF题目中都有LFItoRCE的非预期解,下面总结一下LFI的利用姿势 1. /proc/self/environ 利用 条件:目标能读取 /proc/self/environ,并且网页中存在LFI点 利用方式: 修改请…...
QT6 源(34):随机数生成器类 QRandomGenerator 的源码阅读
(1)代码来自 qrandom.h ,结合官方的注释: #ifndef QRANDOM_H #define QRANDOM_H#include <QtCore/qalgorithms.h> #include <algorithm> // for std::generate #include <random> // for std::mt1993…...