当前位置: 首页 > news >正文

ADMM原理及应用

文章目录

  • 1. ADMM原理
  • 2. ADMM应用
    • 2.1. ADMM求解最小绝对偏差(Least Absolute Deviations)
      • 2.1.1. 数学形式
      • 2.1.2. 将问题转换成ADMM形式
      • 2.1.3. ADMM迭代步骤
      • 2.1.4. 停止准则
      • 2.1.5 Matlab程序和例子
    • 2.2. ADMM求解基追踪(Basis Pursuit)问题
      • 2.2.1 数学形式
      • 2.2.2 将问题转换为 ADMM 形式
      • 2.2.3 ADMM迭代步骤
      • 2.2.4 Matlab程序和例子
    • 2.3. ADMM求解Lasso问题
      • 2.3.1 数学形式
      • 2.3.2 将问题转换为ADMM形式
      • 2.3.3 ADMM 的迭代步骤
      • 2.3.4 Matlab程序和例子
  • 附录1. Cholesky 分解
  • 附录2. 基追踪里 x x x更新
  • 附录3. Woodbury 恒等式(Sherman–Morrison–Woodbury 公式)
  • 参考文献

1. ADMM原理

1.1. 数学形式

我们要解的优化问题长这样:
min ⁡ x ∈ R n , z ∈ R m f ( x ) + g ( z ) subject to A x + B z = c . \min_{x \in \mathbf{R}^n,\; z \in \mathbf{R}^m} \quad f(x) + g(z) \quad\text{subject to}\quad A x + B z = c. xRn,zRmminf(x)+g(z)subject toAx+Bz=c.
这意味着我们想同时让 f ( x ) f(x) f(x) g ( z ) g(z) g(z)尽可能小,但它们又要满足一个线性约束 A x + B z = c A x + B z = c Ax+Bz=c

  • x x x z z z分别是不同的变量,
  • f f f g g g都是凸函数(这保证了算法更容易收敛),
  • A A A B B B 是已知的矩阵,
  • c c c 是已知的常量。

为什么要分成 x x x z z z 两组变量?通常是因为 f f f g g g 可能各自有特殊结构,例如一个是稀疏正则项( L 1 L_1 L1 范数),另一个可能是平方和之类的简单函数。要是把它们混在一起难以统一求解,就可以“拆开”来做。

1.2. 传统“乘子法”和它的不足

在最经典的拉格朗日乘子法里,我们会先把约束放进一个“增强过”的目标函数里,称为“增广拉格朗日函数”(augmented Lagrangian),它一般长这样:
L ρ ( x , z , y ) = f ( x ) + g ( z ) + y T ( A x + B z − c ) + ρ 2 ∥ A x + B z − c ∥ 2 2 , L_\rho(x, z, y) = f(x) + g(z) + y^T(Ax + Bz - c) + \frac{\rho}{2}\|Ax + Bz - c\|_2^2, Lρ(x,z,y)=f(x)+g(z)+yT(Ax+Bzc)+2ρAx+Bzc22,
其中 y y y 是所谓的“对偶变量”或者“拉格朗日乘子”, ρ > 0 \rho>0 ρ>0 是个参数(它决定惩罚力度)。

传统乘子法里,每次迭代要同时对 x x x z z z 都做一个“联合最小化”(joint minimization):
( x k + 1 , z k + 1 ) = arg ⁡ min ⁡ x , z L ρ ( x , z , y k ) , (x^{k+1}, z^{k+1}) = \arg\min_{x,z} \; L_\rho(x, z,\, y^k), (xk+1,zk+1)=argx,zminLρ(x,z,yk),
然后再更新对偶变量
y k + 1 = y k + ρ ( A x k + 1 + B z k + 1 − c ) . y^{k+1} = y^k + \rho\bigl(Ax^{k+1} + Bz^{k+1} - c\bigr). yk+1=yk+ρ(Axk+1+Bzk+1c).
这样做当然可以,但如果 f f f g g g的形式比较复杂,或者维度较大,那这个“联合最小化”就不好算(可能很耗时,或者甚至求不出来)。

1.3. ADMM 的核心思想:分步做

ADMM(Alternating Direction Method of Multipliers,“交替方向乘子法”)最主要的特色就是不再让 x x x z z z 同时做大的联合求解,而是“先算 x x x,再算 z z z”的交替方式。它的三步更新如下:

  1. x x x-更新:固定住旧的 z k z^k zk y k y^k yk,只对 x x x​ 做一个最优更新:
    x k + 1 = arg ⁡ min ⁡ x L ρ ( x , z k , y k ) . x^{k+1} = \arg\min_x \; L_\rho(x,\; z^k,\; y^k). xk+1=argxminLρ(x,zk,yk).
    由于 z k 、 y k z^k、y^k zkyk 不变,这一步就是在一个比较“简化了”的函数里找最优 x x x

  2. z z z-更新:拿到更新后的 x k + 1 x^{k+1} xk+1,再固定它和 y k y^k yk,对 z z z​ 做最优更新:
    z k + 1 = arg ⁡ min ⁡ z L ρ ( x k + 1 , z , y k ) . z^{k+1} = \arg\min_z \; L_\rho\bigl(x^{k+1},\; z,\; y^k\bigr). zk+1=argzminLρ(xk+1,z,yk).

  3. 对偶变量 y y y 更新:有了新的 x k + 1 x^{k+1} xk+1 z k + 1 z^{k+1} zk+1,再更新对偶变量 y y y​:
    y k + 1 = y k + ρ ( A x k + 1 + B z k + 1 − c ) . y^{k+1} = y^k + \rho\bigl(Ax^{k+1} + Bz^{k+1} - c\bigr). yk+1=yk+ρ(Axk+1+Bzk+1c).

这样一来,每一步都只是对一个变量做最小化,问题规模往往更小,如果 f ( x ) f(x) f(x) g ( z ) g(z) g(z) 还是那种可以分开处理的“友好”函数,求解起来也更容易、更快。

1.4. Scaled Form of ADMM

Scaled Form 里,我们把对偶变量 换一种等价的表示。为了方便,我们先定义一个所谓的残差(residual):
r = A x + B z − c . r = Ax + Bz - c. r=Ax+Bzc.
同时,定义“缩放后的对偶变量”(scaled dual variable) u u u​:
u = 1 ρ y . u = \frac{1}{\rho}y. u=ρ1y.
这样,原先的项 y T r + ρ 2 ∥ r ∥ 2 y^T r + \frac{\rho}{2}\|r\|^2 yTr+2ρr2可以用 u u u​ 来重写成
( ρ / 2 ) ∥ r + u ∥ 2 2 ⏟ 重新打包 − ( ρ / 2 ) ∥ u ∥ 2 2 ⏟ 校正 . \underbrace{(\rho/2)\|\,r + u\,\|^2_2}_\text{重新打包} \;-\; \underbrace{(\rho/2)\|u\|^2_2}_\text{校正}. 重新打包 (ρ/2)r+u22校正 (ρ/2)u22.
这个结论的得来类似于高中学到的凑平方项。

“用 u = 1 ρ y u = \tfrac{1}{\rho}y u=ρ1y 替换后,线性和二次项可以组合到一个“ ρ 2 ∥ r + u ∥ 2 \frac{\rho}{2}\|r + u\|^2 2ρr+u2”形式里,看起来更整洁。”

在这个新的记号下,ADMM 的迭代过程可以写成(省去常数项):

  1. x x x-更新
    x k + 1 = arg ⁡ min ⁡ x ( f ( x ) + ρ 2 ∥ A x + B z k − c + u k ∥ 2 2 ) . x^{k+1} = \arg\min_x \Bigl(f(x) \;+\; \frac{\rho}{2}\,\bigl\|\;Ax \;+\; Bz^k \;-\; c \;+\; u^k\bigr\|_2^2\Bigr). xk+1=argxmin(f(x)+2ρ Ax+Bzkc+uk 22).

  2. z z z-更新
    z k + 1 = arg ⁡ min ⁡ z ( g ( z ) + ρ 2 ∥ A x k + 1 + B z − c + u k ∥ 2 2 ) . z^{k+1} = \arg\min_z \Bigl(g(z) \;+\; \frac{\rho}{2}\,\bigl\|\;A x^{k+1} \;+\; Bz \;-\; c \;+\; u^k\bigr\|_2^2\Bigr). zk+1=argzmin(g(z)+2ρ Axk+1+Bzc+uk 22).

  3. u u u-更新
    u k + 1 = u k + ( A x k + 1 + B z k + 1 − c ) . u^{k+1} = u^k \;+\; \bigl(Ax^{k+1} + Bz^{k+1} - c\bigr). uk+1=uk+(Axk+1+Bzk+1c).

你会发现,现在对偶更新变得很简单,直接是对旧的 u u u 加上“残差” r = A x + B z − c r = Ax + Bz - c r=Ax+Bzc​。而在 unscaled form 里则是
y k + 1 = y k + ρ r k . ⟺ u k + 1 = u k + r k , 因为  u = 1 ρ y . y^{k+1} = y^k + \rho\,r^k. \quad\Longleftrightarrow\quad u^{k+1} = u^k + r^k, \quad\text{因为 }u=\tfrac{1}{\rho}y. yk+1=yk+ρrk.uk+1=uk+rk,因为 u=ρ1y.
也就是说,两个形式做的事情完全一样,只是在对偶变量上做一个因子 1 ρ \tfrac{1}{\rho} ρ1 的缩放。

1.5. 迭代过程中主要检查的两大残差

两个残差(residual):

  1. 主(primal)残差
    r k + 1 = A x k + 1 + B z k + 1 − c . r^{k+1} \;=\; A\,x^{k+1} \;+\; B\,z^{k+1} \;-\; c. rk+1=Axk+1+Bzk+1c.
    这是用来度量“原约束   A x + B z = c A x + B z = c Ax+Bz=c”在迭代第 k + 1 k+1 k+1 步时的偏差。若 r k + 1 r^{k+1} rk+1 越接近 0,说明越接近可行。

  2. 对偶(dual)残差
    s k + 1 = ρ A T B ( z k + 1 − z k ) . s^{k+1} \;=\; \rho\,A^T\,B\,(z^{k+1} - z^k). sk+1=ρATB(zk+1zk).
    这是用来度量对偶可行性。若 s k + 1 s^{k+1} sk+1 越接近 0,说明越接近对偶可行。

在 ADMM 中,你会看到在每次迭代完 x k + 1 , z k + 1 x^{k+1}, z^{k+1} xk+1,zk+1​ 后,会“顺手”计算这两个残差,用来判断收敛程度。

1.6. 怎么设置停止准则(Stopping Criteria)?

一个常见且实用的做法就是直接对主残差和对偶残差设置阈值
∥ r k ∥ 2 ≤ ε pri and ∥ s k ∥ 2 ≤ ε dual , \|r^k\|_2 \;\le\; \varepsilon_{\text{pri}} \quad\text{and}\quad \|s^k\|_2 \;\le\; \varepsilon_{\text{dual}}, rk2εpriandsk2εdual,

  • ε pri > 0 \varepsilon_{\text{pri}} > 0 εpri>0(主可行性余量)
  • ε dual > 0 \varepsilon_{\text{dual}} > 0 εdual>0(对偶可行性余量)

只要这两个残差都小于各自阈值,就认定收敛

但是,上述设置也会存在如下问题:

  • 如果问题中 ∥ c ∥ \|c\| c ∥ A x k ∥ \|A x^k\| Axk ∥ B z k ∥ \|B z^k\| Bzk 值很大,仅仅用一个小绝对值判断误差会显得“吹毛求疵”,或者数值上不稳定;
  • 如果问题中变量本身特别小,仅用相对误差也可能不够;

所以可以采用下面一个典型设置
ε pri = p ε abs + ε rel max ⁡ { ∥ A x k ∥ 2 , ∥ B z k ∥ 2 , ∥ c ∥ 2 } , ε dual = n ε abs + ε rel ∥ A T y k ∥ 2 , \varepsilon_{\text{pri}} =\sqrt{p}\,\varepsilon_{\text{abs}} \;+\; \varepsilon_{\text{rel}}\, \max\,\{\,\|A x^k\|_2,\;\|B z^k\|_2,\;\|c\|_2\},\\ \varepsilon_{\text{dual}} =\sqrt{n}\,\varepsilon_{\text{abs}} \;+\; \varepsilon_{\text{rel}}\, \|A^T y^k\|_2, εpri=p εabs+εrelmax{Axk2,Bzk2,c2},εdual=n εabs+εrelATyk2,

  • ε abs \varepsilon_{\text{abs}} εabs(absolute tolerance)是绝对误差上限,
  • ε rel \varepsilon_{\text{rel}} εrel(relative tolerance)是相对误差系数,
  • p \sqrt{p} p n \sqrt{n} n 分别考虑了残差向量所在的维度(主问题中是 R p \mathbf{R}^p Rp,对偶中是 R n \mathbf{R}^n Rn)。
  • 通常在应用中,会选 ε rel = 1 0 − 3 \varepsilon_{\text{rel}} = 10^{-3} εrel=103 1 0 − 4 10^{-4} 104​ 之类,视需求和数值规模而定。

1.7. 自适应调整罚参数 ρ \rho ρ(又称“变步长”技巧)

在标准 ADMM 中, ρ \rho ρ(也叫增广拉格朗日里的“罚参数”)一般是个固定常数。它控制着算法对原约束违背 r k = A x k + B z k − c r^k = A x^k + B z^k - c rk=Axk+Bzkc 的惩罚力度:

  • ρ \rho ρ:更严厉地惩罚主可行性的违背,因此更容易让 r k r^k rk 变得较小,但对偶残差 s k s^k sk可能相对变大。
  • ρ \rho ρ:相对减少对主可行性的惩罚,往往会导致 r k r^k rk 可能大一点,但好处是 s k s^k sk 会小一些。

如果在迭代过程中主残差和对偶残差差距太大,会让 ADMM 收敛变慢。自适应调节 ρ \rho ρ 的目标就是让主、对偶残差同时保持在一个“类似量级”,这样往往能得到更均衡、更快的收敛。

常用方案是:在第 k + 1 k+1 k+1 步开始前,根据上一轮迭代的残差 ∥ r k ∥ \|r^k\| rk ∥ s k ∥ \|s^k\| sk 的大小比较来决定 ρ k + 1 \rho^{k+1} ρk+1​ 的取值:
ρ k + 1 : = { τ incr ρ k , 如果  ∥ r k ∥ 2 > μ ∥ s k ∥ 2 , ρ k / τ decr , 如果  ∥ s k ∥ 2 > μ ∥ r k ∥ 2 , ρ k , 否则. \rho^{k+1} \;:=\; \begin{cases} \tau_{\text{incr}}\,\rho^k, &\text{如果 }\|r^k\|_2 > \mu\,\|s^k\|_2,\\[6pt] \rho^k/\tau_{\text{decr}}, &\text{如果 }\|s^k\|_2 > \mu\,\|r^k\|_2,\\[6pt] \rho^k, &\text{否则.} \end{cases} ρk+1:= τincrρk,ρk/τdecr,ρk,如果 rk2>μsk2,如果 sk2>μrk2,否则.
这里:

  • μ > 1 \mu>1 μ>1 通常是一个常数(比如 μ = 10 \mu=10 μ=10),用来判断两种残差谁大很多;
  • τ incr > 1 \tau_{\text{incr}}>1 τincr>1 τ decr > 1 \tau_{\text{decr}}>1 τdecr>1 是用来放大或缩小 ρ \rho ρ 的倍数(如 τ incr = 2 , τ decr = 2 \tau_{\text{incr}}=2,\tau_{\text{decr}}=2 τincr=2,τdecr=2)。

根据这个公式

  • 当“主残差大”( ∥ r k ∥ > μ ∥ s k ∥ \|r^k\|>\mu\|s^k\| rk>μsk) 时,就把 ρ \rho ρ 增大 τ incr \tau_{\text{incr}} τincrr 倍,以便在后续迭代中对主可行性的违背更严厉些,让 r k + 1 r^{k+1} rk+1 尽可能降下来;
  • 当“对偶残差大” ( ∥ s k ∥ > μ ∥ r k ∥ \|s^k\|>\mu\|r^k\| sk>μrk) 时,就把 ρ \rho ρ 减小 τ decr \tau_{\text{decr}} τdecr 倍,让对偶可行性得到更多纠正,力图让 s k + 1 s^{k+1} sk+1 得到控制;
  • 否则就保持 ρ \rho ρ 不变,说明主、对偶残差的量级相对平衡,没必要动 ρ \rho ρ

这样做的核心思路是:“让 ∥ r k ∥ \|r^k\| rk ∥ s k ∥ \|s^k\| sk 保持在一个大致相当的范围”。当它们差距太大时,就通过调节 ρ \rho ρ 来“补救”。

需要注意的细节

Scaled Form 中的对偶变量要重缩放
如果你用的是 Scaled Form(即 u k = 1 ρ y k u^k = \frac{1}{\rho} y^k uk=ρ1yk 这种),当 ρ \rho ρ 改变时,就要相应地更新 u k u^k uk​:
u k + 1 = 1 ρ k + 1 y k + 1 . u^{k+1} \;=\;\frac{1}{\rho^{k+1}}\,y^{k+1}. uk+1=ρk+11yk+1.
在代码实现里,这往往意味着:如果你决定把 ρ k \rho^k ρk 改为 ρ k + 1 = 1 2 ρ k \rho^{k+1} = \tfrac12\rho^k ρk+1=21ρk,就要把 u k u^k uk 乘以 2(因为 1 ρ \frac1{\rho} ρ1 这一项翻倍了)。
否则会导致对偶变量与新的 ρ \rho ρ​ 不一致、破坏算法正确性。

1.8. Over-relaxation (过松弛)

在 ADMM 的 z z z-update 和 y y y-update 里,常常会出现表达式 A x k + 1 A x^{k+1} Axk+1Over-relaxation (过松弛) 指的是用下面这种线性组合替代 A x k + 1 A x^{k+1} Axk+1
α k A x k + 1 − ( 1 − α k ) ( B z k − c ) , \alpha^k\,A x^{k+1}\;-\;(1-\alpha^k)\,\bigl(B z^k - c\bigr), αkAxk+1(1αk)(Bzkc),
其中 α k ∈ ( 0 , 2 ) \alpha^k \in (0,2) αk(0,2) 是一个松弛因子。当 α k > 1 \alpha^k>1 αk>1 时称为 over-relaxation (过松弛);当 α k < 1 \alpha^k<1 αk<1 称为 under-relaxation (欠松弛)。

实验现象

  • 在许多应用里,选择 α k \alpha^k αk 稍大于 1(比如 1.5 到 1.8 之间)可以加快收敛。它有点类似在某些迭代算法里“加一点动量”或“加速项”的感觉。
  • 但过度 over-relaxation 又可能导致不稳定,所以一般不会取太大。

2. ADMM应用

2.1. ADMM求解最小绝对偏差(Least Absolute Deviations)

2.1.1. 数学形式

在回归或拟合问题中,常见的目标是最小化
∥ A x − b ∥ 2 2 , \|Ax - b\|_2^2, Axb22,
即最小二乘(Least Squares)。但有时候数据中会有较大的“离群点”(outliers),这时最小二乘可能会被几个特别极端的数据“拉偏”,并不能很好地反映整体趋势。最小绝对偏差(Least Absolute Deviations) 的想法,是用
∥ A x − b ∥ 1 \|Ax - b\|_1 Axb1
来衡量误差。因为 L 1 L_1 L1-范数对极端值的敏感程度不如二范数大,从而得到更鲁棒的(robust)结果。

2.1.2. 将问题转换成ADMM形式

引入变量 z z z​,令
z = A x − b z = Ax - b z=Axb
于是原问题就可以写成
min ⁡ x , z ∥ z ∥ 1 , subject to A x − z = b . \begin{aligned} &\min_{x,z}\quad \|z\|_1, \\ &\text{subject to}\quad Ax - z = b. \end{aligned} x,zminz1,subject toAxz=b.
为了使用 ADMM,需要将目标函数写成 f ( x ) + g ( z ) f(x)+g(z) f(x)+g(z) 加一个线性约束,这里我们定义

  • f ( x ) = 0 f(x) = 0 f(x)=0,它“管”着变量 x x x 但没有额外的目标值(因为真正的目标全在 ∥ z ∥ 1 \|z\|_1 z1 里);
  • g ( z ) = ∥ z ∥ 1 g(z) = \|z\|_1 g(z)=z1,这是要最小化的部分;
  • 约束 A x − z = b Ax - z = b Axz=b 则成为 ADMM 中要处理的那条等式。

2.1.3. ADMM迭代步骤

  1. x x x​-update

x k + 1 = arg ⁡ min ⁡ x f ( x ) + ρ 2 ∥ A x − b − z k + u k ∥ 2 2 = arg ⁡ min ⁡ x 0 + ρ 2 ∥ A x − b − z k + u k ∥ 2 2 = arg ⁡ min ⁡ x ∥ A x − b − z k + u k ∥ 2 2 . \begin{align} x^{k+1} &= \arg\min_{x} \; f(x) + \frac{\rho}{2} \|Ax - b - z^k + u^k\|_2^2 \\ &=\arg\min_{x} \; 0 + \frac{\rho}{2} \|Ax - b - z^k + u^k\|_2^2 \\ &=\arg\min_{x} \|Ax - b - z^k + u^k\|_2^2. \end{align} xk+1=argxminf(x)+2ρAxbzk+uk22=argxmin0+2ρAxbzk+uk22=argxminAxbzk+uk22.

这基本上就是一个最小二乘问题:
min ⁡ x ∥ A x − ( b + z k − u k ) ∥ 2 2 . \min_x \;\; \|Ax - (b + z^k - u^k)\|_2^2. xminAx(b+zkuk)22.
如果 A T A A^TA ATA​ 可逆,那么可以直接用
x k + 1 = ( A T A ) − 1 A T ( b + z k − u k ) . x^{k+1} = (A^T A)^{-1} A^T \bigl(b + z^k - u^k\bigr). xk+1=(ATA)1AT(b+zkuk).
这一步也可以用因式分解(比如对 A T A A^T A ATA 做一次 Cholesky 分解等【见附录1】),后续迭代中重复使用,从而加速计算。做完Cholesky 分解后得到的 x x x更新公式如下
x k + 1 = R − 1 ( R T ) − 1 A T ( b + z k − u k ) . x^{k+1} = R^{-1}(R^T)^{-1} A^T \bigl(b + z^k - u^k\bigr). xk+1=R1(RT)1AT(b+zkuk).

  1. z z z​-update

z k + 1 = arg ⁡ min ⁡ z ∥ z ∥ 1 + ρ 2 ∥ A x k + 1 − b − z + u k ∥ 2 2 . z^{k+1} = \arg\min_{z} \; \|z\|_1 + \frac{\rho}{2}\|Ax^{k+1} - b - z + u^k\|_2^2 . zk+1=argzminz1+2ρAxk+1bz+uk22.

这个子问题的解可以用**软阈值(soft thresholding)**算出来,即
z k + 1 = S 1 / ρ ( A x k + 1 − b + u k ) , z^{k+1} = \mathrm{S}_{1/\rho}\,(Ax^{k+1} - b + u^k), zk+1=S1/ρ(Axk+1b+uk),
其中 S α ( ⋅ ) \mathrm{S}_{\alpha}(\cdot) Sα()是元素逐个的软阈值算子(对每个分量做 z i = sign ( w i ) max ⁡ ( ∣ w i ∣ − α , 0 ) z_i = \text{sign}(w_i)\max(|w_i| - \alpha,\,0) zi=sign(wi)max(wiα,0)​)。关于软阈值算子的详细介绍,可以参考我这篇文章。

  1. u u u​-update

u k + 1 = u k + ( A x k + 1 − b − z k + 1 ) . u^{k+1} = u^k + \bigl(Ax^{k+1} - b - z^{k+1}\bigr). uk+1=uk+(Axk+1bzk+1).

这一步是标准的拉格朗日乘子更新,会在迭代中不断逼近约束 A x − z = b Ax - z = b Axz=b

注意:

在ADMM介绍中,我们也提到,在 ADMM 的 z z z-update 和 u u u-update 里,常常会出现表达式 A x k + 1 A x^{k+1} Axk+1Over-relaxation (过松弛) 指的是用下面这种线性组合替代 A x k + 1 A x^{k+1} Axk+1
α k A x k + 1 − ( 1 − α k ) ( B z k − c ) , \alpha^k\,A x^{k+1}\;-\;(1-\alpha^k)\,\bigl(B z^k - c\bigr), αkAxk+1(1αk)(Bzkc),
其中 α k ∈ ( 0 , 2 ) \alpha^k \in (0,2) αk(0,2) 是一个松弛因子。当 α k > 1 \alpha^k>1 αk>1 时称为 over-relaxation (过松弛);当 α k < 1 \alpha^k<1 αk<1 称为 under-relaxation (欠松弛)。在许多应用里,选择 α k \alpha^k αk 稍大于 1(比如 1.5 到 1.8 之间)可以加快收敛。

如果采用这一替代,那么 z z z u u u的更新就变为
A x k + 1 ^ = α k A x k + 1 − ( 1 − α k ) ( B z k − c ) , \hat{Ax^{k+1}} = \alpha^k\,A x^{k+1}\;-\;(1-\alpha^k)\,\bigl(B z^k - c\bigr), Axk+1^=αkAxk+1(1αk)(Bzkc),

z k + 1 = S 1 / ρ ( A x k + 1 ^ − b + u k ) , z^{k+1} = \mathrm{S}_{1/\rho}\,(\hat{Ax^{k+1}} - b + u^k), zk+1=S1/ρ(Axk+1^b+uk),

u k + 1 = u k + ( A x k + 1 ^ − b − z k + 1 ) . u^{k+1} = u^k + \bigl(\hat{Ax^{k+1}} - b - z^{k+1}\bigr). uk+1=uk+(Axk+1^bzk+1).

2.1.4. 停止准则

首先计算两个残差:

  1. 主残差

r k + 1 = A x k + 1 + B z k + 1 − c = A x k + 1 − z k + 1 − b . \begin{align} r^{k+1} \;&=\; A\,x^{k+1} \;+\; B\,z^{k+1} \;-\; c \\ &= \; A\,x^{k+1} -z^{k+1} - b. \end{align} rk+1=Axk+1+Bzk+1c=Axk+1zk+1b.

  1. 对偶残差
    s k + 1 = ρ A T B ( z k + 1 − z k ) = − ρ A T ( z k + 1 − z k ) . \begin{align} s^{k+1} \;&=\; \rho\,A^T\,B\,(z^{k+1} - z^k)\\ &= \; -\rho A^T(z^{k+1} - z^k). \end{align} sk+1=ρATB(zk+1zk)=ρAT(zk+1zk).

然后根据停止准则的典型设置,有
ε pri = p ε abs + ε rel max ⁡ { ∥ A x k ∥ 2 , ∥ B z k ∥ 2 , ∥ c ∥ 2 } , ε dual = n ε abs + ε rel ∥ A T y k ∥ 2 , \varepsilon_{\text{pri}} =\sqrt{p}\,\varepsilon_{\text{abs}} \;+\; \varepsilon_{\text{rel}}\, \max\,\{\,\|A x^k\|_2,\;\|B z^k\|_2,\;\|c\|_2\},\\ \varepsilon_{\text{dual}} =\sqrt{n}\,\varepsilon_{\text{abs}} \;+\; \varepsilon_{\text{rel}}\, \|A^T y^k\|_2, εpri=p εabs+εrelmax{Axk2,Bzk2,c2},εdual=n εabs+εrelATyk2,
那么当
∥ r k ∥ 2 ≤ ε pri and ∥ s k ∥ 2 ≤ ε dual , \|r^k\|_2 \;\le\; \varepsilon_{\text{pri}} \quad\text{and}\quad \|s^k\|_2 \;\le\; \varepsilon_{\text{dual}}, rk2εpriandsk2εdual,
满足时,就可以输出结果了。

2.1.5 Matlab程序和例子

ADMM_lad函数如下

function [x, history] = ADMM_lad(A, b, rho, alpha)
% ADMM_lad   Least Absolute Deviations fitting via ADMM
% 
% [x, history] = ADMM_lad(A, b, rho, alpha)
%
% Solves the following problem via ADMM:
%   minimize ||Ax - b||_1
%
% Input:
%   A      - m x n matrix of coefficients
%   b      - m x 1 vector of observations
%   rho    - augmented Lagrangian parameter
%   alpha  - over-relaxation parameter (1.0 <= alpha <= 1.8, typical value: 1.5)
%
% Output:
%   x       - solution vector of size n x 1
%   history - structure containing iteration details:
%             - objective value at each iteration
%             - primal and dual residual norms
%             - tolerances for convergence criteria
%
% Algorithm Overview:
%   The goal is to solve the Least Absolute Deviations (LAD) problem:
%       minimize ||Ax - b||_1,
%   which is robust to outliers compared to the least squares approach. This is achieved
%   by introducing an auxiliary variable z and reformulating the problem as:
%       minimize ||z||_1,
%       subject to Ax - z = b.
%
%   Using the Alternating Direction Method of Multipliers (ADMM), the augmented Lagrangian is:
%       L(x, z, u) = ||z||_1 + (rho / 2) * ||Ax - z - b + u||_2^2,
%   where u is the scaled dual variable. The optimization proceeds in the following steps:
%     1. x-update: Solve a least squares problem for x:
%          x^{k+1} = argmin_x (1/2)||Ax - b - z^k + u^k||_2^2.
%          This step is implemented efficiently using the Cholesky factorization of A^T A.
%     2. z-update: Use the soft-thresholding operator to minimize ||z||_1:
%          z^{k+1} = S_{1/\rho}(Ax^{k+1} - b + u^k),
%          where S_{\kappa}(\cdot) is the soft-thresholding operator.
%     3. u-update: Update the dual variable to enforce the constraint Ax - z = b:
%          u^{k+1} = u^k + (Ax^{k+1} - z^{k+1} - b).
%   These steps are repeated until convergence criteria based on primal and dual residuals are met.
%
% Reference:
%   Boyd et al., "Distributed Optimization and Statistical Learning via the ADMM" (2011)%% Constants and initializationt_start = tic;               % Start timerMAX_ITER = 1000;             % Maximum number of iterationsABSTOL   = 1e-4;             % Absolute tolerance for convergenceRELTOL   = 1e-2;             % Relative tolerance for convergence[m, n] = size(A);            % Dimensions of the problem% Initialize variablesx = zeros(n, 1);             % Optimization variable xz = zeros(m, 1);             % Auxiliary variable zu = zeros(m, 1);             % Dual variable (scaled Lagrange multiplier)% Precompute Cholesky factorization of A^T A for efficient least squaresR = chol(A' * A);% Print table header for iteration logsfprintf('%-5s %-12s %-12s %-12s %-12s %-12s\n',...'Iter', 'r_norm', 'eps_pri', 's_norm', 'eps_dual', 'Objective');%% ADMM iterationsfor k = 1:MAX_ITER% Step 1: x-update (solve least squares problem)% Solve (A^T A) x = A^T (b + z - u)x = R \ (R' \ (A' * (b + z - u)));% Step 2: z-update (soft-thresholding)z_old = z;  % Save previous value of zAx_hat = alpha * A * x + (1 - alpha) * (z_old + b);  % Over-relaxation stepz = shrinkage(Ax_hat - b + u, 1 / rho);  % Soft-thresholding operator% Step 3: u-update (dual variable update)u = u + (Ax_hat - z - b);  % Update scaled Lagrange multiplier% Diagnostics and reportinghistory.objval(k)  = norm(z, 1);  % Objective function valuehistory.r_norm(k)  = norm(A * x - z - b);  % Primal residual normhistory.s_norm(k)  = norm(-rho * A' * (z - z_old));  % Dual residual norm% Convergence toleranceshistory.eps_pri(k) = sqrt(m) * ABSTOL + RELTOL * max([norm(A * x), norm(z), norm(b)]);history.eps_dual(k) = sqrt(n) * ABSTOL + RELTOL * norm(rho * A' * u);% Print iteration detailsfprintf('%-5d %-12.4f %-12.4f %-12.4f %-12.4f %-12.2f\n', k, ...history.r_norm(k), history.eps_pri(k), ...history.s_norm(k), history.eps_dual(k), history.objval(k));% Check for convergenceif (history.r_norm(k) < history.eps_pri(k) && ...history.s_norm(k) < history.eps_dual(k))break;endend% Print total computation timefprintf('Total time: %.2f seconds\n', toc(t_start));
endfunction y = shrinkage(a, kappa)
% Soft-thresholding operatory = sign(a) .* max(abs(a) - kappa, 0);
end

一个简单的调用例子

clear; close all; clc;% Example of ADMM for Least Absolute Deviations (LAD) fitting
rng(0);  % Set random seed for reproducibility% Problem dimensions
m = 500;  % Number of rows (observations)
n = 100;  % Number of columns (features)% Generate random data
A = randn(m, n);          % Coefficient matrix
x0 = 10 * randn(n, 1);    % True signal
b = A * x0;               % Observed data without noise% Add large outliers to simulate real-world noisy data
idx = randsample(m, ceil(m/50));  % Randomly pick ~2% of rows
b(idx) = b(idx) + 1e2 * randn(size(idx));  % Add large noise% Call ADMM LAD solver
rho = 1;   % ADMM parameter
alpha = 1; % Over-relaxation parameter
[x, history] = ADMM_lad(A, b, rho, alpha);% Plot results
figure('Position', [500, 200, 800, 600]);  % Set figure size% Plot original signal and reconstructed signal
subplot(2, 1, 1);
plot(1:n, x0, 'b-', 'LineWidth', 1.5); hold on;
plot(1:n, x, 'r--', 'LineWidth', 1.5);
xlabel('Index', 'FontSize', 12, 'FontWeight', 'bold');
ylabel('Value', 'FontSize', 12, 'FontWeight', 'bold');
title('Original Signal vs. Reconstructed Signal', 'FontSize', 14, 'FontWeight', 'bold');
legend({'True Signal (x_0)', 'Reconstructed Signal (x)'}, 'FontSize', 12);
grid on;
set(gca, 'FontSize', 12, 'LineWidth', 1.2);  % Adjust axis font size and line width% Plot convergence history
subplot(2, 1, 2);
semilogy(1:length(history.objval), history.objval, 'k-', 'LineWidth', 1.5); hold on;
semilogy(1:length(history.r_norm), history.r_norm, 'r-', 'LineWidth', 1.5);
semilogy(1:length(history.s_norm), history.s_norm, 'b-', 'LineWidth', 1.5);
xlabel('Iteration', 'FontSize', 12, 'FontWeight', 'bold');
ylabel('Log Scale', 'FontSize', 12, 'FontWeight', 'bold');
title('Convergence History', 'FontSize', 14, 'FontWeight', 'bold');
legend({'Objective Value', 'Primal Residual', 'Dual Residual'}, 'FontSize', 12);
grid on;
set(gca, 'FontSize', 12, 'LineWidth', 1.2);  % Adjust axis font size and line width% Display results in the console
fprintf('Original Signal (x0):\n');
disp(x0(1:10));  % Display first 10 values
fprintf('Reconstructed Signal (x):\n');
disp(x(1:10));   % Display first 10 values

运行结果为

在这里插入图片描述

2.2. ADMM求解基追踪(Basis Pursuit)问题

2.2.1 数学形式

Basis Pursuit 的数学形式如下:
min ⁡ x ∥ x ∥ 1 subject to  A x = b , \min_x \|x\|_1 \quad \text{subject to } Ax = b, xminx1subject to Ax=b,
其中:

  • x ∈ R n x \in \mathbf{R}^n xRn 是优化变量;
  • A ∈ R m × n , b ∈ R m A \in \mathbf{R}^{m \times n}, b \in \mathbf{R}^m ARm×n,bRm
  • 通常情况下, m < n m < n m<n,即这是一个欠定问题(未知数多于方程数)。

2.2.2 将问题转换为 ADMM 形式

为了用 ADMM 求解,需要将原问题拆分成两个部分:

  1. 第一部分处理 ℓ 1 \ell_1 1 范数最小化;
  2. 第二部分处理等式约束 A x = b Ax = b Ax=b

引入一个辅助变量 z z z​,重写为:
min ⁡ x ∥ z ∥ 1 , subject to  x − z = 0 , A x = b . \begin{aligned} & \min_x \|z\|_1, \\ & \text{subject to } x - z = 0, \; Ax = b. \end{aligned} xminz1,subject to xz=0,Ax=b.
将这个问题写成 ADMM 框架:
min ⁡ x , z f ( x ) + ∥ z ∥ 1 subject to  x − z = 0 , \min_{x, z} f(x) + \|z\|_1 \quad \text{subject to } x - z = 0, x,zminf(x)+z1subject to xz=0,
其中:

  • f ( x ) f(x) f(x) 是约束 A x = b Ax = b Ax=b 的指示函数:
    f ( x ) = { 0 , if  A x = b , + ∞ , otherwise . f(x) = \begin{cases} 0, & \text{if } Ax = b, \\ +\infty, & \text{otherwise}. \end{cases} f(x)={0,+,if Ax=b,otherwise.

Augmented Lagrangian(增广拉格朗日函数):
L ( x , z , u ) = ∥ z ∥ 1 + ρ 2 ∥ x − z + u ∥ 2 2 , L(x, z, u) = \|z\|_1 + \frac{\rho}{2}\|x - z + u\|_2^2, L(x,z,u)=z1+2ρxz+u22,
其中 u u u 是拉格朗日乘子, ρ > 0 \rho > 0 ρ>0 是增广拉格朗日参数。

2.2.3 ADMM迭代步骤

  1. x x x​-update:
    x k + 1 = arg ⁡ min ⁡ x f ( x ) + ρ 2 ∥ x − z k + u k ∥ 2 2 . x^{k+1} = \arg\min_x \; f(x) + \frac{\rho}{2} \|x - z^k + u^k\|_2^2. xk+1=argxminf(x)+2ρxzk+uk22.

由于 f ( x ) f(x) f(x)是约束 A x = b Ax = b Ax=b​ 的指示函数,优化约束为:
min ⁡ x ρ 2 ∥ x − z k + u k ∥ 2 2 subject to  A x = b . \min_x \; \frac{\rho}{2} \|x - z^k + u^k\|_2^2 \quad \text{subject to } Ax = b. xmin2ρxzk+uk22subject to Ax=b.
这个问题可以写成:
x k + 1 = Π { x ∣ A x = b } ( z k − u k ) , x^{k+1} = \Pi_{\{x | Ax = b\}}(z^k - u^k), xk+1=Π{xAx=b}(zkuk),
其中 Π { x ∣ A x = b } \Pi_{\{x | Ax = b\}} Π{xAx=b} 表示投影到约束集 { x ∣ A x = b } \{x | Ax = b\} {xAx=b}

通过计算可得【见附录2】
x k + 1 = ( I − A T ( A A T ) − 1 A ) ( z k − u k ) + A T ( A A T ) − 1 b , x^{k+1} = \left(I - A^T(AA^T)^{-1}A\right)(z^k - u^k) + A^T(AA^T)^{-1}b, xk+1=(IAT(AAT)1A)(zkuk)+AT(AAT)1b,

  1. z z z​-update:
    z k + 1 : = arg ⁡ min ⁡ z ∥ z ∥ 1 + ρ 2 ∥ x k + 1 − z + u k ∥ 2 2 . z^{k+1} := \arg\min_z \; \|z\|_1 + \frac{\rho}{2}\|x^{k+1} - z + u^k\|_2^2. zk+1:=argzminz1+2ρxk+1z+uk22.

这一步是一个标准的 ℓ 1 \ell_1 1​-范数最小化问题,解可以通过 软阈值(soft-thresholding) 算子计算:
z k + 1 = S 1 / ρ ( x k + 1 + u k ) , z^{k+1} = S_{1/\rho}(x^{k+1} + u^k), zk+1=S1/ρ(xk+1+uk),
其中 S κ ( ⋅ ) S_\kappa(\cdot) Sκ()​是软阈值操作:
S κ ( a ) = sign ( a ) ⋅ max ⁡ ( ∣ a ∣ − κ , 0 ) . S_\kappa(a) = \text{sign}(a) \cdot \max(|a| - \kappa, 0). Sκ(a)=sign(a)max(aκ,0).

  1. u u u-update:

u k + 1 = u k + x k + 1 − z k + 1 . u^{k+1} = u^k + x^{k+1} - z^{k+1}. uk+1=uk+xk+1zk+1.

2.2.4 Matlab程序和例子

ADMM_bp的函数

function [z, history] = ADMM_bp(A, b, rho, alpha)
% ADMM_bp   Basis Pursuit solver using ADMM
% 
% [x, history] = ADMM_bp(A, b, rho, alpha)
%
% This function solves the Basis Pursuit problem:
%     minimize ||x||_1
%     subject to Ax = b
%
% Basis Pursuit is widely used for finding sparse solutions to underdetermined
% systems of linear equations. This problem is reformulated in ADMM form as:
%     minimize f(x) + ||z||_1
%     subject to x - z = 0
% where:
%     - f(x) is the indicator function of the affine constraint Ax = b:
%          f(x) = 0 if Ax = b, +inf otherwise.
%
% The augmented Lagrangian for this problem is:
%     L(x, z, u) = ||z||_1 + (rho/2)||x - z + u||_2^2
% where u is the scaled dual variable.
%
% ADMM iteratively updates variables as follows:
%  1. x-update: Solve
%         x^{k+1} = argmin_x f(x) + (rho/2)||x - z^k + u^k||_2^2
%         Using projection onto {x | Ax = b}, the explicit solution is:
%         x^{k+1} = (I - A^T(AA^T)^-1A)(z^k - u^k) + A^T(AA^T)^-1b
%
%  2. z-update: Solve
%         z^{k+1} = argmin_z ||z||_1 + (rho/2)||x^{k+1} - z + u^k||_2^2
%         This is a standard l1 minimization problem solved via soft-thresholding:
%         z^{k+1} = S_{1/rho}(x^{k+1} + u^k)
%
%  3. u-update:
%         u^{k+1} = u^k + x^{k+1} - z^{k+1}
%
% Input:
%   A      - m x n coefficient matrix (m < n for underdetermined systems)
%   b      - m x 1 vector of observations
%   rho    - augmented Lagrangian parameter
%   alpha  - over-relaxation parameter (1.0 <= alpha <= 1.8 typical)
%
% Output:
%   x       - n x 1 solution vector
%   history - structure containing:
%               - objective value at each iteration
%               - primal and dual residuals
%               - tolerances for convergence%% Constants and initializationt_start = tic;               % Start timerMAX_ITER = 1000;             % Maximum number of iterationsABSTOL   = 1e-4;             % Absolute tolerance for convergenceRELTOL   = 1e-2;             % Relative tolerance for convergence[~, n] = size(A);            % Dimensions of the problem% Initialize variablesz = zeros(n, 1);             % Auxiliary variable zu = zeros(n, 1);             % Dual variable (scaled Lagrange multiplier)% precompute static variables for x-update (projection on to Ax=b)AAt = A * A';P = eye(n) - A' * (AAt \ A);q = A' * (AAt \ b);% Print table header for iteration logsfprintf('%-5s %-12s %-12s %-12s %-12s %-12s\n',...'Iter', 'r_norm', 'eps_pri', 's_norm', 'eps_dual', 'Objective');for k = 1:MAX_ITER% x-update: Projection onto {x | Ax = b}x = P * (z - u) + q;% z-update: Soft-thresholdingzold = z;x_hat = alpha * x + (1 - alpha) * zold;z = shrinkage(x_hat + u, 1/rho);% u-update: Dual variableu = u + (x_hat - z);% Diagnostics and reportinghistory.objval(k)  = norm(z, 1);  % Objective function valuehistory.r_norm(k)  = norm(x - z);  % Primal residual normhistory.s_norm(k)  = norm(-rho * (z - zold));  % Dual residual norm% Convergence toleranceshistory.eps_pri(k) = sqrt(n) * ABSTOL + RELTOL * max([norm(x), norm(-z)]);history.eps_dual(k) = sqrt(n) * ABSTOL + RELTOL * norm(rho * u);% Print iteration detailsfprintf('%-5d %-12.4f %-12.4f %-12.4f %-12.4f %-12.2f\n', k, ...history.r_norm(k), history.eps_pri(k), ...history.s_norm(k), history.eps_dual(k), history.objval(k));% Check for convergenceif (history.r_norm(k) < history.eps_pri(k) && ...history.s_norm(k) < history.eps_dual(k))break;endend% Print total computation timefprintf('Total time: %.2f seconds\n', toc(t_start));
endfunction y = shrinkage(a, kappa)
% Soft-thresholding operatory = sign(a) .* max(abs(a) - kappa, 0);
end

一个调用的例子

clear; close all; clc;% Example of ADMM for Basis Pursuit (BP)
rng(0);  % Set random seed for reproducibility% Problem dimensions
n = 30;  % Number of variables
m = 30;  % Number of equations% Generate random data
A = randn(m, n);               % Measurement matrix
x = sprandn(n, 1, 0.1 * n);    % Sparse true signal
b = A * x;                     % Observed measurementsxtrue = double(x);  % Save true signal for comparison% Solve Basis Pursuit problem using ADMM
rho = 1.0;   % Augmented Lagrangian parameter
alpha = 1.0; % Over-relaxation parameter
[x, history] = ADMM_bp(A, b, rho, alpha);% Plot results
figure('Position', [100, 100, 800, 600]);% Plot original signal and reconstructed signal
subplot(2, 1, 1);
stem(1:n, xtrue, 'b', 'LineWidth', 1.5); hold on;
stem(1:n, x, 'r--', 'LineWidth', 1.5);
xlabel('Index', 'FontSize', 12, 'FontWeight', 'bold');
ylabel('Value', 'FontSize', 12, 'FontWeight', 'bold');
title('Original Signal vs. Reconstructed Signal', 'FontSize', 14, 'FontWeight', 'bold');
legend({'True Signal', 'Reconstructed Signal'}, 'FontSize', 12);
grid on;
set(gca, 'FontSize', 12, 'LineWidth', 1.2);% Plot convergence history
subplot(2, 1, 2);
semilogy(1:length(history.objval), history.objval, 'k-', 'LineWidth', 1.5); hold on;
semilogy(1:length(history.r_norm), history.r_norm, 'r-', 'LineWidth', 1.5);
semilogy(1:length(history.s_norm), history.s_norm, 'b-', 'LineWidth', 1.5);
xlabel('Iteration', 'FontSize', 12, 'FontWeight', 'bold');
ylabel('Log Scale', 'FontSize', 12, 'FontWeight', 'bold');
title('Convergence History', 'FontSize', 14, 'FontWeight', 'bold');
legend({'Objective Value', 'Primal Residual', 'Dual Residual'}, 'FontSize', 12);
grid on;
set(gca, 'FontSize', 12, 'LineWidth', 1.2);% Display results
fprintf('True Signal with none zero element:\n');
disp(xtrue(1:10));fprintf('Reconstructed Signal (first 10 values):\n');
disp(x(1:10));

运行结果

在这里插入图片描述

2.3. ADMM求解Lasso问题

2.3.1 数学形式

Lasso 是一种带有 ℓ 1 \ell_1 1​ 正则化的线性回归问题,其目标是平衡数据拟合误差和模型的稀疏性。数学形式为:
min ⁡ x 1 2 ∥ A x − b ∥ 2 2 + λ ∥ x ∥ 1 , \min_x \; \frac{1}{2}\|Ax - b\|_2^2 + \lambda \|x\|_1, xmin21Axb22+λx1,
其中:

  • x ∈ R n x \in \mathbf{R}^n xRn
  • A ∈ R m × n , b ∈ R m A \in \mathbf{R}^{m \times n}, b \in \mathbf{R}^m ARm×n,bRm:数据矩阵和观测向量;
  • λ > 0 \lambda > 0 λ>0​:正则化参数,用于控制稀疏性。

2.3.2 将问题转换为ADMM形式

Lasso 问题可以通过引入辅助变量 z z z​ 转化为:
min ⁡ x , z f ( x ) + g ( z ) , subject to  x − z = 0 , \min_{x, z} \; f(x) + g(z), \quad \text{subject to }\; x - z = 0, x,zminf(x)+g(z),subject to xz=0,
其中:

  • f ( x ) = 1 2 ∥ A x − b ∥ 2 2 f(x) = \frac{1}{2}\|Ax - b\|_2^2 f(x)=21Axb22:用于拟合数据;
  • g ( z ) = λ ∥ z ∥ 1 g(z) = \lambda \|z\|_1 g(z)=λz1:用于实现稀疏性约束。

增广拉格朗日函数为:
L ( x , z , u ) = f ( x ) + g ( z ) + ρ 2 ∥ x − z + u ∥ 2 2 , L(x, z, u) = f(x) + g(z) + \frac{\rho}{2}\|x - z + u\|_2^2, L(x,z,u)=f(x)+g(z)+2ρxz+u22,
其中:

  • u u u:是缩放的拉格朗日乘子;
  • ρ > 0 \rho > 0 ρ>0:是增广拉格朗日参数。

2.3.3 ADMM 的迭代步骤

  1. x x x-update:
    x k + 1 = arg ⁡ min ⁡ x f ( x ) + ρ 2 ∥ x − z k + u k ∥ 2 2 . x^{k+1} = \arg\min_x \; f(x) + \frac{\rho}{2}\|x - z^k + u^k\|_2^2. xk+1=argxminf(x)+2ρxzk+uk22.

目标函数为:
1 2 ∥ A x − b ∥ 2 2 + ρ 2 ∥ x − z k + u k ∥ 2 2 . \frac{1}{2}\|Ax - b\|_2^2 + \frac{\rho}{2}\|x - z^k + u^k\|_2^2. 21Axb22+2ρxzk+uk22.
这是一个标准的带正则化的最小二乘问题(Ridge Regression),其显式解为:
x k + 1 = ( A T A + ρ I ) − 1 ( A T b + ρ ( z k − u k ) ) , x^{k+1} = (A^T A + \rho I)^{-1}(A^T b + \rho(z^k - u^k)), xk+1=(ATA+ρI)1(ATb+ρ(zkuk)),

  • A T A + ρ I A^T A + \rho I ATA+ρI 总是可逆的( ρ > 0 \rho > 0 ρ>0)。

在实现时,可以通过对 A T A + ρ I A^T A + \rho I ATA+ρI 进行一次 Cholesky 分解 【见附录1】来加速后续迭代。当 m < n m<n m<n时,如果仍然去直接分解 ( A T A + ρ I ) ∈ R n × n (A^\mathsf{T} A + \rho I)\in \mathbb{R}^{n\times n} (ATA+ρI)Rn×n,其规模会较大(因为 n n n大于 m m m​),可能效率并不理想。此时更常见、更高效的做法是转而分解
( A A T + ρ I ) ∈ R m × m , (A A^\mathsf{T} + \rho I) \;\in\; \mathbb{R}^{m\times m}, (AAT+ρI)Rm×m,
这样做的原因是,当 m < n m<n m<n 时, ( A A T + ρ I ) (A A^\mathsf{T} + \rho I) (AAT+ρI) 的维度 m × m m \times m m×m更小,分解规模相应更小,计算会更高效。由 A T A + ρ I A^T A + \rho I ATA+ρI得到( A A T + ρ I A A^\mathsf{T} + \rho I AAT+ρI)可以借用著名的 Woodbury 恒等式(亦称 Sherman–Morrison–Woodbury 公式)【见附录3】:
( ρ I + A T A ) − 1 = 1 ρ I − 1 ρ A T ( I + 1 ρ A A T ) − 1 1 ρ A . (\rho I + A^\mathsf{T} A)^{-1} = \frac{1}{\rho} I - \frac{1}{\rho} \,A^\mathsf{T} \Bigl(I + \tfrac{1}{\rho}A\,A^\mathsf{T}\Bigr)^{-1} \tfrac{1}{\rho}\,A. (ρI+ATA)1=ρ1Iρ1AT(I+ρ1AAT)1ρ1A.
将它稍作整理,可以写成
( ρ I + A T A ) − 1 = 1 ρ I − 1 ρ 2 A T ( I + 1 ρ A A T ) − 1 A . (\rho I + A^\mathsf{T} A)^{-1} = \frac{1}{\rho}\,I - \frac{1}{\rho^2}\,A^\mathsf{T}\,\bigl(I + \frac{1}{\rho}A A^\mathsf{T}\bigr)^{-1}\,A. (ρI+ATA)1=ρ1Iρ21AT(I+ρ1AAT)1A.
因此,当我们要解
( A T A + ρ I ) x = q (A^\mathsf{T} A + \rho I)\,x \;=\; q (ATA+ρI)x=q
时( q = A T b + ρ ( z k − u k ) q=A^T b + \rho(z^k - u^k) q=ATb+ρ(zkuk)),可以直接乘上它的逆得到
x = ( A T A + ρ I ) − 1 q = [ 1 ρ I − 1 ρ 2 A T ( I + 1 ρ A A T ) − 1 A ] q . x = (A^\mathsf{T} A + \rho I)^{-1}\,q = \biggl[ \frac{1}{\rho} I \;-\; \frac{1}{\rho^2} A^\mathsf{T} \bigl(I + \frac{1}{\rho}A A^\mathsf{T}\bigr)^{-1} A \biggr] q. x=(ATA+ρI)1q=[ρ1Iρ21AT(I+ρ1AAT)1A]q.


  1. z z z-update:
    z k + 1 = arg ⁡ min ⁡ z g ( z ) + ρ 2 ∥ x k + 1 − z + u k ∥ 2 2 . z^{k+1} = \arg\min_z \; g(z) + \frac{\rho}{2}\|x^{k+1} - z + u^k\|_2^2. zk+1=argzming(z)+2ρxk+1z+uk22.

这是一个** ℓ 1 \ell_1 1​-范数最小化问题**,可以通过 软阈值算子(Soft-Thresholding Operator) 得到解析解:
z k + 1 = S λ / ρ ( x k + 1 + u k ) , z^{k+1} = S_{\lambda / \rho}(x^{k+1} + u^k), zk+1=Sλ/ρ(xk+1+uk),
其中:
S κ ( a ) = sign ( a ) ⋅ max ⁡ ( ∣ a ∣ − κ , 0 ) . S_\kappa(a) = \text{sign}(a) \cdot \max(|a| - \kappa, 0). Sκ(a)=sign(a)max(aκ,0).
软阈值操作会对小于 λ / ρ \lambda / \rho λ/ρ的系数进行稀疏化。


  1. u u u-update:
    u k + 1 = u k + x k + 1 − z k + 1 . u^{k+1} = u^k + x^{k+1} - z^{k+1}. uk+1=uk+xk+1zk+1.

2.3.4 Matlab程序和例子

ADMM_lasso函数

function [x, history] = ADMM_lasso(A, b, lambda, rho, alpha)
% ADMM_lasso   Solves the Lasso problem using ADMM
%
% This function solves the Lasso problem, which is defined as:
%   minimize (1/2)||Ax - b||_2^2 + lambda * ||x||_1,
%
% where:
%   - A: m x n data matrix
%   - b: m x 1 observation vector
%   - lambda: regularization parameter controlling sparsity
%
% The Lasso problem seeks to balance the data fitting term (||Ax - b||_2^2)
% with the sparsity-inducing regularization term (||x||_1).
%
% In ADMM form, the problem is reformulated as:
%   minimize f(x) + g(z),
%   subject to x - z = 0,
%
% where:
%   - f(x) = (1/2)||Ax - b||_2^2,
%   - g(z) = lambda * ||z||_1.
%
% The augmented Lagrangian is:
%   L(x, z, u) = f(x) + g(z) + (rho/2)||x - z + u||_2^2,
%
% ADMM proceeds with the following updates:
%   1. x-update: Solve a ridge regression problem:
%        x^{k+1} = argmin_x f(x) + (rho/2)||x - z^k + u^k||_2^2.
%      This step involves solving:
%        x^{k+1} = (A^T A + rho * I)^{-1}(A^T b + rho * (z^k - u^k)).
%
%   2. z-update: Apply the soft-thresholding operator:
%        z^{k+1} = S_{lambda/rho}(x^{k+1} + u^k).
%      Soft-thresholding is defined as:
%        S_kappa(a) = sign(a) * max(|a| - kappa, 0).
%
%   3. u-update: Update the scaled dual variable:
%        u^{k+1} = u^k + x^{k+1} - z^{k+1}.
%
% Input:
%   - A: m x n matrix of predictors
%   - b: m x 1 vector of responses
%   - lambda: regularization parameter
%   - rho: augmented Lagrangian parameter
%   - alpha: over-relaxation parameter (1.0 <= alpha <= 1.8 is typical)
%
% Output:
%   - z: solution vector (n x 1)
%   - history: structure containing convergence metrics:
%       * objval: objective value at each iteration
%       * r_norm: primal residual norm
%       * s_norm: dual residual norm
%       * eps_pri: primal feasibility tolerance
%       * eps_dual: dual feasibility tolerance%% Constants and initializationt_start = tic;               % Start timerMAX_ITER = 1000;             % Maximum number of iterationsABSTOL   = 1e-4;             % Absolute tolerance for convergenceRELTOL   = 1e-2;             % Relative tolerance for convergence[m, n] = size(A);            % Dimensions of the problem% Save a matrix-vector multiplyAtb = A' * b;z = zeros(n,1);              % Initialize auxiliary variable zu = zeros(n,1);              % Initialize scaled dual variable u% Cache the factorization[L, U] = factor(A, rho);% Print table header for iteration logsfprintf('%-5s %-12s %-12s %-12s %-12s %-12s\n',...'Iter', 'r_norm', 'eps_pri', 's_norm', 'eps_dual', 'Objective');for k = 1:MAX_ITER% x-update: Solve ridge regression problem% if m >= n, conduct Cholesky factorization directly;% if m < n, use the Sherman–Morrison–Woodbury equation:% (rho I + ATA)^-1 = 1/rho I - 1/rho^2 AT(I + 1/rho AAT)^-1Aq = Atb + rho*(z - u);    % Temporary valueif( m >= n )    % If skinnyx = U \ (L \ q);else            % If fatx = q/rho - (A'*(U \ ( L \ (A*q) )))/rho^2;end% z-update with relaxationzold = z;x_hat = alpha*x + (1 - alpha)*zold;z = shrinkage(x_hat + u, lambda/rho);% u-update: Update scaled dual variableu = u + (x_hat - z);% Diagnostics, reporting, termination checkshistory.objval(k)  = objective(A, b, lambda, x, z);history.r_norm(k)  = norm(x - z);history.s_norm(k)  = norm(-rho*(z - zold));history.eps_pri(k) = sqrt(n)*ABSTOL + RELTOL*max(norm(x), norm(-z));history.eps_dual(k)= sqrt(n)*ABSTOL + RELTOL*norm(rho*u);% Print iteration detailsfprintf('%-5d %-12.4f %-12.4f %-12.4f %-12.4f %-12.2f\n', k, ...history.r_norm(k), history.eps_pri(k), ...history.s_norm(k), history.eps_dual(k), history.objval(k));if (history.r_norm(k) < history.eps_pri(k) && ...history.s_norm(k) < history.eps_dual(k))break;endend% Print total computation timefprintf('Total time: %.2f seconds\n', toc(t_start));
endfunction p = objective(A, b, lambda, x, z)% Computes the objective value:%   p = (1/2)||Ax - b||_2^2 + lambda * ||z||_1p = ( 1/2*sum((A*x - b).^2) + lambda*norm(z,1) );
endfunction y = shrinkage(a, kappa)% Soft-thresholding operator:%   y = sign(a) .* max(abs(a) - kappa, 0)y = sign(a) .* max(abs(a) - kappa, 0);
endfunction [L, U] = factor(A, rho)
% FACTOR Precomputes Cholesky factorization for x-update in ADMM
% This function prepares a precomputed matrix factorization to speed up 
% the x-update step in the ADMM iterations. Depending on the size and shape 
% of A, it efficiently handles the matrix to solve the linear system.
% 
% INPUT:
%   A    - m x n matrix (data matrix in the optimization problem)
%   rho  - augmented Lagrangian parameter
% 
% OUTPUT:
%   L    - Lower triangular matrix from Cholesky decomposition
%   U    - Upper triangular matrix (transpose of L)
% 
% BACKGROUND:
% In the ADMM x-update step, we solve a linear system of the form:
%   (A^T A + rho I) x = q (if m >= n, "skinny" case), or
%   x = A^T y with (I + 1/rho A A^T) y = b (if m < n, "fat" case).
% This function computes the Cholesky factorization of the respective 
% matrices for efficient iterative solving.% Get dimensions of the input matrix A[m, n] = size(A);% Determine the matrix to factorize based on the shape of Aif (m >= n)  % "Skinny" case: More rows than columns% Factorize (A^T A + rho * I)% This is a (n x n) symmetric positive definite matrixL = chol(A' * A + rho * speye(n), 'lower');else  % "Fat" case: More columns than rows% Factorize (I + 1/rho * A A^T)% This is a (m x m) symmetric positive definite matrixL = chol(speye(m) + (1/rho) * (A * A'), 'lower');end% Convert the result to sparse format for memory efficiency and speed% This ensures MATLAB recognizes the triangular structureL = sparse(L);U = sparse(L');
end

调用示例

clear; close all; clc;% Example of ADMM for Lasso
rng(0);  % Set random seed for reproducibility%% ============ 1. 生成随机数据 ============
m = 500;           % 样本数(观测维度)
n = 1000;           % 特征数(变量维度)
k = 50;            % 稀疏度(真值 x_true 中非零元素个数)
A = randn(m, n);  % 随机生成设计矩阵% 生成稀疏真值 x_true
x_true = zeros(n, 1);
supp = randperm(n, k);        % 在 n 个位置中随机选 k 个作为非零
x_true(supp) = randn(k, 1)*3; % 放大一点非零量级% 生成观测 b (带一些噪声)
noise = 0.01*randn(m, 1);     % 噪声
b = A * x_true + noise;% 正则化系数(可调)
lambda = 0.1;[x, history] = ADMM_lasso(A, b, lambda, 1.0, 1.0);% Plot original vs. reconstructed signals
figure('Position', [100, 100, 800, 600]);
subplot(2, 1, 1);
stem(1:n, x_true, 'b', 'LineWidth', 1.5); hold on;
stem(1:n, x, 'r--', 'LineWidth', 1.5);
xlabel('Index', 'FontSize', 12, 'FontWeight', 'bold');
ylabel('Value', 'FontSize', 12, 'FontWeight', 'bold');
title('Original vs. Reconstructed Signal (First 100 Components)', 'FontSize', 14, 'FontWeight', 'bold');
legend({'Original Signal', 'Reconstructed Signal'}, 'FontSize', 12);
grid on;
set(gca, 'FontSize', 12, 'LineWidth', 1.2);% Plot convergence history
subplot(2, 1, 2);
semilogy(1:length(history.objval), history.objval, 'k-', 'LineWidth', 1.5); hold on;
semilogy(1:length(history.r_norm), history.r_norm, 'r-', 'LineWidth', 1.5);
semilogy(1:length(history.s_norm), history.s_norm, 'b-', 'LineWidth', 1.5);
xlabel('Iteration', 'FontSize', 12, 'FontWeight', 'bold');
ylabel('Log Scale', 'FontSize', 12, 'FontWeight', 'bold');
title('Convergence History', 'FontSize', 14, 'FontWeight', 'bold');
legend({'Objective Value', 'Primal Residual Norm', 'Dual Residual Norm'}, 'FontSize', 12);
grid on;
set(gca, 'FontSize', 12, 'LineWidth', 1.2);

结果

在这里插入图片描述

附录1. Cholesky 分解

Cholesky 分解是一种针对对称正定矩阵的分解方法;如果有一个对称正定矩阵 M M M​,我们可以把它分解为
M = R T R M = R^T R M=RTR
其中 R R R 是一个上三角矩阵(或有些实现中会取下三角矩阵)。在实际计算中,它常被用来快速解方程组提高数值稳定性以及节省运算量

比如在最小二乘问题中,如果我们要解
( A T A ) x = A T b , (A^T A)\,x = A^T b, (ATA)x=ATb,
一个直接的做法是先对 A T A A^T A ATA 做 Cholesky 分解 A T A = R T R A^T A = R^T R ATA=RTR,然后我们只需要两次三角回代就能快速得到 x x x​。这是因为解方程组
R T R x = A T b R^T R\,x = A^T b RTRx=ATb
可以分两步走:

  1. 先解 R T y = A T b R^T y = A^T b RTy=ATb 得到 y y y
  2. 再解 R x = y R x = y Rx=y 得到 x x x

这相对于一般的高斯消去法,能显著降低运算量并且更稳定。而且,当我们在迭代算法中要反复求解相似的线性方程组(例如 ADMM 的子问题),我们可以在最开始就对矩阵做 Cholesky 分解,然后重复使用这个分解,从而大幅加速后续的求解过程。

根据这个原理,我们先分解得到 R R R, 然后根据 R R R计算 x x x,即
x = R − 1 ( R T ) − 1 A T b x=R^{-1}(R^T)^{-1}A^Tb x=R1(RT)1ATb

附录2. 基追踪里 x x x更新

对于
x k + 1 : = arg ⁡ min ⁡ x ρ 2 ∥ x − z k + u k ∥ 2 2 subject to  A x = b . x^{k+1} := \arg \min_x \frac{\rho}{2} \|x - z^k + u^k\|_2^2 \quad \text{subject to } Ax = b. xk+1:=argxmin2ρxzk+uk22subject to Ax=b.
展开目标函数 ∥ x − z k + u k ∥ 2 2 \|x - z^k + u^k\|_2^2 xzk+uk22​:
∥ x − z k + u k ∥ 2 2 = ( x − z k + u k ) T ( x − z k + u k ) . \|x - z^k + u^k\|_2^2 = (x - z^k + u^k)^T (x - z^k + u^k). xzk+uk22=(xzk+uk)T(xzk+uk).
这可以写成:
x T x − 2 x T ( z k − u k ) + ( z k − u k ) T ( z k − u k ) . x^T x - 2x^T (z^k - u^k) + (z^k - u^k)^T (z^k - u^k). xTx2xT(zkuk)+(zkuk)T(zkuk).
因此目标函数变为:
ρ 2 ( x T x − 2 x T ( z k − u k ) + constant ) . \frac{\rho}{2} \left( x^T x - 2x^T (z^k - u^k) + \text{constant} \right). 2ρ(xTx2xT(zkuk)+constant).
其中“constant”项与 x x x 无关,可以忽略,优化问题化为:
min ⁡ x ρ 2 x T x − ρ x T ( z k − u k ) subject to  A x = b . \min_x \; \frac{\rho}{2} x^T x - \rho x^T (z^k - u^k) \quad \text{subject to } Ax = b. xmin2ρxTxρxT(zkuk)subject to Ax=b.
为引入约束 A x = b Ax = b Ax=b,使用拉格朗日乘子 λ \lambda λ​,构造拉格朗日函数:
L ( x , λ ) = ρ 2 x T x − ρ x T ( z k − u k ) + λ T ( A x − b ) . \mathcal{L}(x, \lambda) = \frac{\rho}{2} x^T x - \rho x^T (z^k - u^k) + \lambda^T (Ax - b). L(x,λ)=2ρxTxρxT(zkuk)+λT(Axb).
x x x λ \lambda λ 求偏导,设置导数为 0,得到以下方程组:

x x x​ 的导数:
∂ L ∂ x = ρ x − ρ ( z k − u k ) + A T λ = 0. \frac{\partial \mathcal{L}}{\partial x} = \rho x - \rho (z^k - u^k) + A^T \lambda = 0. xL=ρxρ(zkuk)+ATλ=0.
整理得到:
x = z k − u k − 1 ρ A T λ . x = z^k - u^k - \frac{1}{\rho} A^T \lambda. x=zkukρ1ATλ.
λ \lambda λ​ 的导数:
∂ L ∂ λ = A x − b = 0. \frac{\partial \mathcal{L}}{\partial \lambda} = Ax - b = 0. λL=Axb=0.
即:
A x = b . Ax = b. Ax=b.


联立求解
A ( z k − u k − 1 ρ A T λ ) = b . A\left(z^k - u^k - \frac{1}{\rho} A^T \lambda \right) = b. A(zkukρ1ATλ)=b.
展开整理:
A z k − A u k − 1 ρ A A T λ = b . A z^k - A u^k - \frac{1}{\rho} A A^T \lambda = b. AzkAukρ1AATλ=b.

A A T λ = ρ ( A z k − A u k − b ) . A A^T \lambda = \rho (A z^k - A u^k - b). AATλ=ρ(AzkAukb).

从而得到 λ \lambda λ​ 的解:
λ = ( A A T ) − 1 ρ ( A z k − A u k − b ) . \lambda = (A A^T)^{-1} \rho (A z^k - A u^k - b). λ=(AAT)1ρ(AzkAukb).
λ \lambda λ 的解代回
x = z k − u k − 1 ρ A T λ . x = z^k - u^k - \frac{1}{\rho} A^T \lambda. x=zkukρ1ATλ.
代入 λ = ( A A T ) − 1 ρ ( A z k − A u k − b ) \lambda = (A A^T)^{-1} \rho (A z^k - A u^k - b) λ=(AAT)1ρ(AzkAukb)​:
x = z k − u k − A T ( A A T ) − 1 ( A z k − A u k − b ) . x = z^k - u^k - A^T (A A^T)^{-1} (A z^k - A u^k - b). x=zkukAT(AAT)1(AzkAukb).
进一步整理为:
x k + 1 = ( I − A T ( A A T ) − 1 A ) ( z k − u k ) + A T ( A A T ) − 1 b . x^{k+1} = \left(I - A^T (A A^T)^{-1} A \right)(z^k - u^k) + A^T (A A^T)^{-1} b. xk+1=(IAT(AAT)1A)(zkuk)+AT(AAT)1b.

附录3. Woodbury 恒等式(Sherman–Morrison–Woodbury 公式)

**Woodbury 恒等式(Sherman–Morrison–Woodbury 公式)**是一条在数值分析和应用数学中非常著名、且常常被用来对矩阵进行「低秩修正」(low-rank update)求逆的公式。它能够将一个大规模矩阵的逆问题,转化为对一个更小规模矩阵做运算,从而显著节省计算开销。

给定可逆矩阵 B ∈ R n × n B \in \mathbb{R}^{n\times n} BRn×n,以及矩阵 U ∈ R n × k U \in \mathbb{R}^{n\times k} URn×k C ∈ R k × k C \in \mathbb{R}^{k\times k} CRk×k V ∈ R k × n V \in \mathbb{R}^{k\times n} VRk×n(其中 C C C​ 也要求可逆),那么 Woodbury 恒等式表述如下:
( B + U C V ) − 1 = B − 1 − B − 1 U ( C − 1 + V B − 1 U ) − 1 V B − 1 . \bigl( B \;+\; U\,C\,V \bigr)^{-1} \;=\; B^{-1} \;-\; B^{-1}\,U \Bigl( C^{-1} + V\,B^{-1}\,U \Bigr)^{-1} V\,B^{-1}. (B+UCV)1=B1B1U(C1+VB1U)1VB1.
U U U V V V 的列秩(或行秩)很小,且 C C C 维度小(例如 k ≪ n k \ll n kn),就可以用 Woodbury 公式来避开对一个 n × n n\times n n×n 大矩阵的求逆或分解,而改去操作一个 k × k k\times k k×k 的矩阵,大大降低了计算量和内存消耗。

对于 ( A T A + ρ I ) − 1 (A^\mathsf{T} A + \rho I)^{-1} (ATA+ρI)1,套用公式有 B = ρ I , U = A T , C = I , V = A B = \rho I, U = A^T, C = I, V= A B=ρI,U=AT,C=I,V=A
( A T A + ρ I ) − 1 = 1 ρ − 1 ρ A T ( I + 1 ρ A A T ) − 1 A 1 ρ (A^\mathsf{T} A + \rho I)^{-1} = \frac{1}{\rho}-\frac{1}{\rho}A^T(I+\frac{1}{\rho}AA^T)^{-1}A\frac{1}{\rho} (ATA+ρI)1=ρ1ρ1AT(I+ρ1AAT)1Aρ1

参考文献

Boyd S, Parikh N, Chu E, et al. Distributed optimization and statistical learning via the alternating direction method of multipliers[J]. Foundations and Trends® in Machine learning, 2011, 3(1): 1-122.

相关文章:

ADMM原理及应用

文章目录 1. ADMM原理1.1. 数学形式1.2. 传统“乘子法”和它的不足1.3. ADMM 的核心思想&#xff1a;分步做1.4. Scaled Form of ADMM1.5. 迭代过程中主要检查的两大残差1.6. 怎么设置停止准则(Stopping Criteria)&#xff1f;1.7. 自适应调整罚参数 ρ \rho ρ&#xff08;又…...

mysql之sql的优化方案(重点)

1、全字段匹配是最棒的 假如一个Staffs 这个表&#xff0c;将 name,age ,pos 组合成了一个联合索引&#xff0c;在where条件下&#xff0c;能够使用到的索引越多越好。 EXPLAIN SELECT * FROM staffs WHERE NAME July; EXPLAIN SELECT * FROM staffs WHERE NAME July AND age…...

【LeetCode】303. 区域和检索 - 数组不可变

目录 描述Python1. 前缀和 描述 给定一个整数数组nums&#xff0c;处理以下类型的多个查询&#xff1a;计算索引left和right&#xff08;包含left和right&#xff09;之间的nums元素的 和 &#xff0c;其中left < right 实现NumArray类&#xff1a; NumArray(int[] nums)&a…...

前端开发 vue 中如何实现 u-form 多个form表单同时校验

在 Vue 项目中使用 UView UI 的 u-form 组件时&#xff0c;多个表单同时校验的需求非常常见。例如&#xff0c;当我们有多个表单需要在同一个页面中进行校验并提交时&#xff0c;我们需要确保每个表单都能进行单独验证&#xff0c;同时可以在同一时刻进行批量验证。 接下来&am…...

【网络】什么是速率 (Rate)带宽 (Bandwidth)吞吐量 (Throughput)?

注意单位&#xff1a; 在 kbps、Mbps、Gbps 中&#xff0c;前面的 k、M、G 是 国际单位制(SI) 的前缀&#xff0c;表示不同的数量级&#xff1a; k&#xff08;千/kilo&#xff09;: (10^3 1,000) kbps&#xff08;kilobits per second&#xff09;: 每秒 1,000 位&#xff08…...

(leetcode算法题)769. 最多能完成排序的块

Q1. 是否能用贪心算法&#xff1f;为什么&#xff1f; 先预设一个策略&#xff0c;每当当前的nums[i]满足可以 "成块"&#xff0c;就直接让这个数成块&#xff0c;也就是说之后的遍历过程中不会将这个数在考虑到自己的块内&#xff0c; "成块" 是指只要只…...

高光谱相机的特点

光谱特性 高光谱分辨率&#xff1a;能将光谱范围分割成极窄的波段&#xff0c;光谱分辨率通常达到纳米级甚至亚纳米级&#xff0c;可精确捕捉到不同物质在细微光谱差异上的特征&#xff0c;比如可以区分不同种类的植被因叶绿素含量等差异而在光谱上的细微变化。 多波段探测&a…...

《Spring Framework实战》8:4.1.3.Bean 概述

欢迎观看《Spring Framework实战》视频教程 Spring IoC 容器管理一个或多个 bean。这些 bean 是使用 您提供给容器的配置元数据&#xff08;例如&#xff0c;以 XML <bean/>定义的形式&#xff09;。 在容器本身中&#xff0c;这些 bean 定义表示为BeanDefinition对象&a…...

BGP的local_preference本地优先级属性

一、BGP的local preference属性简介 1、local preference公认任意属性 当一条BGP路由器中存在多条去往同一目标网络的BGP路由时&#xff0c;BGP协议会对这些BGP路由属性进行比较&#xff0c;从而筛选出最佳到达目标网络的通达路径。本地优先属性&#xff0c;只在IBGP对等体之间…...

IP地址与端口号

ip地址与端口号 IP地址和端口号是网络通信中的两个重要概念&#xff0c;它们共同构成了网络通信的基础。 IP地址&#xff1a;网络世界的门牌号 定义&#xff1a;IP地址&#xff08;Internet Protocol Address&#xff09;是分配给网络设备的数字标签&#xff0c;用于在计算机网…...

Fastapi + vue3 自动化测试平台(2)--日志中间件

FastAPI Vue3 自动化测试平台&#xff08;2&#xff09;-- 日志中间件 前言 在开发和运行自动化测试平台时&#xff0c;日志功能是至关重要的一部分。日志不仅能帮助我们快速定位和解决问题&#xff0c;还能作为平台运行的记录依据&#xff0c;为后续分析和优化提供参考。 …...

iOS - AutoreleasePool

1. 基本数据结构 // AutoreleasePool 的基本结构 struct AutoreleasePoolPage {static pthread_key_t const key AUTORELEASE_POOL_KEY;magic_t const magic;id *next; // 指向下一个可存放对象的地址pthread_t const thread; // 所属线程AutoreleasePoolPage …...

1.CSS的复合选择器

1.1 什么是复合选择器 在CSS中&#xff0c;可以根据选择器的类型把选择器分为基础选择器和复合选择器&#xff0c;复合选择器是建立在基础选择器之上&#xff0c;对基础选择器进行组合形成的。 复合选择器可以更精准、更高效的选择目标元素&#xff08;标签&#xff09; 复…...

优质内容在个人IP运营中的重要性:以开源AI智能名片商城小程序为应用实例的深度探讨

摘要&#xff1a;在数字化时代&#xff0c;个人品牌&#xff08;IP&#xff09;的塑造与传播已成为各行各业提升影响力、吸引用户关注、促进商业转化的关键策略。优质内容作为连接个人IP与目标受众的桥梁&#xff0c;其在个人IP运营中的重要性不言而喻。本文旨在深入探讨优质内…...

Kafka性能测试

kafka是一个大数据消息队列&#xff08;可以看做为缓存软件&#xff09; 功能测试&#xff1a;能够读写数据 性能测试&#xff1a;1、测试生产者每秒往kafka写入的最大吞吐量 2、测试消费者每秒从kafka里获取消息最大吞吐量 硬件 3台物理机组成的kafka集群。 内存121G、24…...

解决Docker冲突问题

错误&#xff1a;docker-ce-cli conflicts with 2:docker-1.13.1-210.git7d71120.el7.centos.x86_64 错误&#xff1a;docker-ce conflicts with 2:docker-1.13.1-210.git7d71120.el7.centos.x86_64 您可以尝试添加 --skip-broken 选项来解决该问题 您可以尝试执行&#xff1a;…...

新手入门 React .tsx 项目:从零到实战

&#x1f680; 新手入门 React .tsx 项目&#xff1a;从零到实战 &#x1f4bb;✨ 如果你是 React 新手&#xff0c;刚接触 .tsx 文件&#xff0c;不要担心&#xff01;跟着这份指南&#xff0c;一步一步来&#xff0c;你很快就能上手了&#xff01;&#x1f447; &#x1f4d…...

基于可信数据空间的企业数据要素与流通体系建设(附ppt 下载)

近期&#xff0c;可信数据空间会议召开。大数据系统软件国家工程研究中心总工程师王晨发表了题为《基于可信数据空间的企业数据要素与流通体系建设》主旨演讲。 篇幅限制&#xff0c;部分内容如下&#xff1a;...

二维数组:求最大元素及其所在的行坐标及列坐标(PTA)C语言

求出NM整型数组的最大元素及其所在的行坐标及列坐标&#xff08;如果最大元素不唯一&#xff0c;选择位置在最前面的一个&#xff09;。 函数接口定义&#xff1a; int fun(int array[N][M]) ; 注意&#xff1a;函数只需靠return返回最大元素的值&#xff0c; 行、列坐标通过…...

WebRtc01: 课程导学、框架介绍

应用 难点 课程大纲 学习收获 涉及内容 概述 用途 学习收获...

day52 ResNet18 CBAM

在深度学习的旅程中&#xff0c;我们不断探索如何提升模型的性能。今天&#xff0c;我将分享我在 ResNet18 模型中插入 CBAM&#xff08;Convolutional Block Attention Module&#xff09;模块&#xff0c;并采用分阶段微调策略的实践过程。通过这个过程&#xff0c;我不仅提升…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器

——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的​​一体化测试平台​​&#xff0c;覆盖应用全生命周期测试需求&#xff0c;主要提供五大核心能力&#xff1a; ​​测试类型​​​​检测目标​​​​关键指标​​功能体验基…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

爬虫基础学习day2

# 爬虫设计领域 工商&#xff1a;企查查、天眼查短视频&#xff1a;抖音、快手、西瓜 ---> 飞瓜电商&#xff1a;京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空&#xff1a;抓取所有航空公司价格 ---> 去哪儿自媒体&#xff1a;采集自媒体数据进…...

[Java恶补day16] 238.除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂度…...

RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill

视觉语言模型&#xff08;Vision-Language Models, VLMs&#xff09;&#xff0c;为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展&#xff0c;机器人仍难以胜任复杂的长时程任务&#xff08;如家具装配&#xff09;&#xff0c;主要受限于人…...

jmeter聚合报告中参数详解

sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample&#xff08;样本数&#xff09; 表示测试中发送的请求数量&#xff0c;即测试执行了多少次请求。 单位&#xff0c;以个或者次数表示。 示例&#xff1a;…...

认识CMake并使用CMake构建自己的第一个项目

1.CMake的作用和优势 跨平台支持&#xff1a;CMake支持多种操作系统和编译器&#xff0c;使用同一份构建配置可以在不同的环境中使用 简化配置&#xff1a;通过CMakeLists.txt文件&#xff0c;用户可以定义项目结构、依赖项、编译选项等&#xff0c;无需手动编写复杂的构建脚本…...

API网关Kong的鉴权与限流:高并发场景下的核心实践

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 引言 在微服务架构中&#xff0c;API网关承担着流量调度、安全防护和协议转换的核心职责。作为云原生时代的代表性网关&#xff0c;Kong凭借其插件化架构…...

第八部分:阶段项目 6:构建 React 前端应用

现在&#xff0c;是时候将你学到的 React 基础知识付诸实践&#xff0c;构建一个简单的前端应用来模拟与后端 API 的交互了。在这个阶段&#xff0c;你可以先使用模拟数据&#xff0c;或者如果你的后端 API&#xff08;阶段项目 5&#xff09;已经搭建好&#xff0c;可以直接连…...