ADMM原理及应用
文章目录
- 1. ADMM原理
- 1.1. 数学形式
- 1.2. 传统“乘子法”和它的不足
- 1.3. ADMM 的核心思想:分步做
- 1.4. Scaled Form of ADMM
- 1.5. 迭代过程中主要检查的两大残差
- 1.6. 怎么设置停止准则(Stopping Criteria)?
- 1.7. 自适应调整罚参数 ρ \rho ρ(又称“变步长”技巧)
- 1.8. Over-relaxation (过松弛)
- 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. x∈Rn,z∈Rmminf(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+Bz−c)+2ρ∥Ax+Bz−c∥22,
其中 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+1−c).
这样做当然可以,但如果 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”的交替方式。它的三步更新如下:
-
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 zk、yk 不变,这一步就是在一个比较“简化了”的函数里找最优 x x x。 -
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). -
对偶变量 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+1−c).
这样一来,每一步都只是对一个变量做最小化,问题规模往往更小,如果 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+Bz−c.
同时,定义“缩放后的对偶变量”(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ρ∥r∥2可以用 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+u∥22−校正 (ρ/2)∥u∥22.
这个结论的得来类似于高中学到的凑平方项。
“用 u = 1 ρ y u = \tfrac{1}{\rho}y u=ρ1y 替换后,线性和二次项可以组合到一个“ ρ 2 ∥ r + u ∥ 2 \frac{\rho}{2}\|r + u\|^2 2ρ∥r+u∥2”形式里,看起来更整洁。”
在这个新的记号下,ADMM 的迭代过程可以写成(省去常数项):
-
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+Bzk−c+uk 22). -
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+Bz−c+uk 22). -
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+1−c).
你会发现,现在对偶更新变得很简单,直接是对旧的 u u u 加上“残差” r = A x + B z − c r = Ax + Bz - c r=Ax+Bz−c。而在 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):
-
主(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+1−c.
这是用来度量“原约束 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,说明越接近可行。 -
对偶(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+1−zk).
这是用来度量对偶可行性。若 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}}, ∥rk∥2≤εpriand∥sk∥2≤ε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{∥Axk∥2,∥Bzk∥2,∥c∥2},εdual=nεabs+εrel∥ATyk∥2,
- ε 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=10−3或 1 0 − 4 10^{-4} 10−4 之类,视需求和数值规模而定。
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+Bzk−c 的惩罚力度:
- ρ \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,如果 ∥rk∥2>μ∥sk∥2,如果 ∥sk∥2>μ∥rk∥2,否则.
这里:
- μ > 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+1 。Over-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)(Bzk−c),
其中 α 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, ∥Ax−b∥22,
即最小二乘(Least Squares)。但有时候数据中会有较大的“离群点”(outliers),这时最小二乘可能会被几个特别极端的数据“拉偏”,并不能很好地反映整体趋势。最小绝对偏差(Least Absolute Deviations) 的想法,是用
∥ A x − b ∥ 1 \|Ax - b\|_1 ∥Ax−b∥1
来衡量误差。因为 L 1 L_1 L1-范数对极端值的敏感程度不如二范数大,从而得到更鲁棒的(robust)结果。
2.1.2. 将问题转换成ADMM形式
引入变量 z z z,令
z = A x − b z = Ax - b z=Ax−b
于是原问题就可以写成
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,zmin∥z∥1,subject toAx−z=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 ∥z∥1 里);
- g ( z ) = ∥ z ∥ 1 g(z) = \|z\|_1 g(z)=∥z∥1,这是要最小化的部分;
- 约束 A x − z = b Ax - z = b Ax−z=b 则成为 ADMM 中要处理的那条等式。
2.1.3. ADMM迭代步骤
- 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ρ∥Ax−b−zk+uk∥22=argxmin0+2ρ∥Ax−b−zk+uk∥22=argxmin∥Ax−b−zk+uk∥22.
这基本上就是一个最小二乘问题:
min x ∥ A x − ( b + z k − u k ) ∥ 2 2 . \min_x \;\; \|Ax - (b + z^k - u^k)\|_2^2. xmin∥Ax−(b+zk−uk)∥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+zk−uk).
这一步也可以用因式分解(比如对 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=R−1(RT)−1AT(b+zk−uk).
- 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=argzmin∥z∥1+2ρ∥Axk+1−b−z+uk∥22.
这个子问题的解可以用**软阈值(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+1−b+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))。关于软阈值算子的详细介绍,可以参考我这篇文章。
- 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+1−b−zk+1).
这一步是标准的拉格朗日乘子更新,会在迭代中不断逼近约束 A x − z = b Ax - z = b Ax−z=b。
注意:
在ADMM介绍中,我们也提到,在 ADMM 的 z z z-update 和 u u u-update 里,常常会出现表达式 A x k + 1 A x^{k+1} Axk+1。Over-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)(Bzk−c),
其中 α 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)(Bzk−c),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^−b−zk+1).
2.1.4. 停止准则
首先计算两个残差:
- 主残差
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+1−c=Axk+1−zk+1−b.
- 对偶残差
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+1−zk)=−ρAT(zk+1−zk).
然后根据停止准则的典型设置,有
ε 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{∥Axk∥2,∥Bzk∥2,∥c∥2},εdual=nεabs+εrel∥ATyk∥2,
那么当
∥ 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}}, ∥rk∥2≤εpriand∥sk∥2≤ε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, xmin∥x∥1subject to Ax=b,
其中:
- x ∈ R n x \in \mathbf{R}^n x∈Rn 是优化变量;
- A ∈ R m × n , b ∈ R m A \in \mathbf{R}^{m \times n}, b \in \mathbf{R}^m A∈Rm×n,b∈Rm;
- 通常情况下, m < n m < n m<n,即这是一个欠定问题(未知数多于方程数)。
2.2.2 将问题转换为 ADMM 形式
为了用 ADMM 求解,需要将原问题拆分成两个部分:
- 第一部分处理 ℓ 1 \ell_1 ℓ1 范数最小化;
- 第二部分处理等式约束 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} xmin∥z∥1,subject to x−z=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)+∥z∥1subject to x−z=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)=∥z∥1+2ρ∥x−z+u∥22,
其中 u u u 是拉格朗日乘子, ρ > 0 \rho > 0 ρ>0 是增广拉格朗日参数。
2.2.3 ADMM迭代步骤
- 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ρ∥x−zk+uk∥22.
由于 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ρ∥x−zk+uk∥22subject 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=Π{x∣Ax=b}(zk−uk),
其中 Π { x ∣ A x = b } \Pi_{\{x | Ax = b\}} Π{x∣Ax=b} 表示投影到约束集 { x ∣ A x = b } \{x | Ax = b\} {x∣Ax=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=(I−AT(AAT)−1A)(zk−uk)+AT(AAT)−1b,
- 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:=argzmin∥z∥1+2ρ∥xk+1−z+uk∥22.
这一步是一个标准的 ℓ 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).
- 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+1−zk+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, xmin21∥Ax−b∥22+λ∥x∥1,
其中:
- x ∈ R n x \in \mathbf{R}^n x∈Rn;
- A ∈ R m × n , b ∈ R m A \in \mathbf{R}^{m \times n}, b \in \mathbf{R}^m A∈Rm×n,b∈Rm:数据矩阵和观测向量;
- λ > 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 x−z=0,
其中:
- f ( x ) = 1 2 ∥ A x − b ∥ 2 2 f(x) = \frac{1}{2}\|Ax - b\|_2^2 f(x)=21∥Ax−b∥22:用于拟合数据;
- g ( z ) = λ ∥ z ∥ 1 g(z) = \lambda \|z\|_1 g(z)=λ∥z∥1:用于实现稀疏性约束。
增广拉格朗日函数为:
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ρ∥x−z+u∥22,
其中:
- u u u:是缩放的拉格朗日乘子;
- ρ > 0 \rho > 0 ρ>0:是增广拉格朗日参数。
2.3.3 ADMM 的迭代步骤
- 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ρ∥x−zk+uk∥22.
目标函数为:
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. 21∥Ax−b∥22+2ρ∥x−zk+uk∥22.
这是一个标准的带正则化的最小二乘问题(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+ρ(zk−uk)),
- 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+ρ(zk−uk)),可以直接乘上它的逆得到
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.
- 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+1−z+uk∥22.
这是一个** ℓ 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 λ/ρ的系数进行稀疏化。
- 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+1−zk+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
可以分两步走:
- 先解 R T y = A T b R^T y = A^T b RTy=ATb 得到 y y y;
- 再解 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=R−1(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ρ∥x−zk+uk∥22subject to Ax=b.
展开目标函数 ∥ x − z k + u k ∥ 2 2 \|x - z^k + u^k\|_2^2 ∥x−zk+uk∥22:
∥ 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). ∥x−zk+uk∥22=(x−zk+uk)T(x−zk+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). xTx−2xT(zk−uk)+(zk−uk)T(zk−uk).
因此目标函数变为:
ρ 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ρ(xTx−2xT(zk−uk)+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(zk−uk)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(zk−uk)+λT(Ax−b).
对 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. ∂x∂L=ρx−ρ(zk−uk)+ATλ=0.
整理得到:
x = z k − u k − 1 ρ A T λ . x = z^k - u^k - \frac{1}{\rho} A^T \lambda. x=zk−uk−ρ1ATλ.
对 λ \lambda λ 的导数:
∂ L ∂ λ = A x − b = 0. \frac{\partial \mathcal{L}}{\partial \lambda} = Ax - b = 0. ∂λ∂L=Ax−b=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(zk−uk−ρ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. Azk−Auk−ρ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λ=ρ(Azk−Auk−b).
从而得到 λ \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ρ(Azk−Auk−b).
将 λ \lambda λ 的解代回
x = z k − u k − 1 ρ A T λ . x = z^k - u^k - \frac{1}{\rho} A^T \lambda. x=zk−uk−ρ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ρ(Azk−Auk−b):
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=zk−uk−AT(AAT)−1(Azk−Auk−b).
进一步整理为:
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=(I−AT(AAT)−1A)(zk−uk)+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} B∈Rn×n,以及矩阵 U ∈ R n × k U \in \mathbb{R}^{n\times k} U∈Rn×k、 C ∈ R k × k C \in \mathbb{R}^{k\times k} C∈Rk×k、 V ∈ R k × n V \in \mathbb{R}^{k\times n} V∈Rk×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=B−1−B−1U(C−1+VB−1U)−1VB−1.
当 U U U 和 V V V 的列秩(或行秩)很小,且 C C C 维度小(例如 k ≪ n k \ll n k≪n),就可以用 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 的核心思想:分步做1.4. Scaled Form of ADMM1.5. 迭代过程中主要检查的两大残差1.6. 怎么设置停止准则(Stopping Criteria)?1.7. 自适应调整罚参数 ρ \rho ρ(又…...
mysql之sql的优化方案(重点)
1、全字段匹配是最棒的 假如一个Staffs 这个表,将 name,age ,pos 组合成了一个联合索引,在where条件下,能够使用到的索引越多越好。 EXPLAIN SELECT * FROM staffs WHERE NAME July; EXPLAIN SELECT * FROM staffs WHERE NAME July AND age…...
【LeetCode】303. 区域和检索 - 数组不可变
目录 描述Python1. 前缀和 描述 给定一个整数数组nums,处理以下类型的多个查询:计算索引left和right(包含left和right)之间的nums元素的 和 ,其中left < right 实现NumArray类: NumArray(int[] nums)&a…...
前端开发 vue 中如何实现 u-form 多个form表单同时校验
在 Vue 项目中使用 UView UI 的 u-form 组件时,多个表单同时校验的需求非常常见。例如,当我们有多个表单需要在同一个页面中进行校验并提交时,我们需要确保每个表单都能进行单独验证,同时可以在同一时刻进行批量验证。 接下来&am…...
【网络】什么是速率 (Rate)带宽 (Bandwidth)吞吐量 (Throughput)?
注意单位: 在 kbps、Mbps、Gbps 中,前面的 k、M、G 是 国际单位制(SI) 的前缀,表示不同的数量级: k(千/kilo): (10^3 1,000) kbps(kilobits per second): 每秒 1,000 位(…...
(leetcode算法题)769. 最多能完成排序的块
Q1. 是否能用贪心算法?为什么? 先预设一个策略,每当当前的nums[i]满足可以 "成块",就直接让这个数成块,也就是说之后的遍历过程中不会将这个数在考虑到自己的块内, "成块" 是指只要只…...
高光谱相机的特点
光谱特性 高光谱分辨率:能将光谱范围分割成极窄的波段,光谱分辨率通常达到纳米级甚至亚纳米级,可精确捕捉到不同物质在细微光谱差异上的特征,比如可以区分不同种类的植被因叶绿素含量等差异而在光谱上的细微变化。 多波段探测&a…...
《Spring Framework实战》8:4.1.3.Bean 概述
欢迎观看《Spring Framework实战》视频教程 Spring IoC 容器管理一个或多个 bean。这些 bean 是使用 您提供给容器的配置元数据(例如,以 XML <bean/>定义的形式)。 在容器本身中,这些 bean 定义表示为BeanDefinition对象&a…...
BGP的local_preference本地优先级属性
一、BGP的local preference属性简介 1、local preference公认任意属性 当一条BGP路由器中存在多条去往同一目标网络的BGP路由时,BGP协议会对这些BGP路由属性进行比较,从而筛选出最佳到达目标网络的通达路径。本地优先属性,只在IBGP对等体之间…...
IP地址与端口号
ip地址与端口号 IP地址和端口号是网络通信中的两个重要概念,它们共同构成了网络通信的基础。 IP地址:网络世界的门牌号 定义:IP地址(Internet Protocol Address)是分配给网络设备的数字标签,用于在计算机网…...
Fastapi + vue3 自动化测试平台(2)--日志中间件
FastAPI Vue3 自动化测试平台(2)-- 日志中间件 前言 在开发和运行自动化测试平台时,日志功能是至关重要的一部分。日志不仅能帮助我们快速定位和解决问题,还能作为平台运行的记录依据,为后续分析和优化提供参考。 …...
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中,可以根据选择器的类型把选择器分为基础选择器和复合选择器,复合选择器是建立在基础选择器之上,对基础选择器进行组合形成的。 复合选择器可以更精准、更高效的选择目标元素(标签) 复…...
优质内容在个人IP运营中的重要性:以开源AI智能名片商城小程序为应用实例的深度探讨
摘要:在数字化时代,个人品牌(IP)的塑造与传播已成为各行各业提升影响力、吸引用户关注、促进商业转化的关键策略。优质内容作为连接个人IP与目标受众的桥梁,其在个人IP运营中的重要性不言而喻。本文旨在深入探讨优质内…...
Kafka性能测试
kafka是一个大数据消息队列(可以看做为缓存软件) 功能测试:能够读写数据 性能测试:1、测试生产者每秒往kafka写入的最大吞吐量 2、测试消费者每秒从kafka里获取消息最大吞吐量 硬件 3台物理机组成的kafka集群。 内存121G、24…...
解决Docker冲突问题
错误:docker-ce-cli conflicts with 2:docker-1.13.1-210.git7d71120.el7.centos.x86_64 错误:docker-ce conflicts with 2:docker-1.13.1-210.git7d71120.el7.centos.x86_64 您可以尝试添加 --skip-broken 选项来解决该问题 您可以尝试执行:…...
新手入门 React .tsx 项目:从零到实战
🚀 新手入门 React .tsx 项目:从零到实战 💻✨ 如果你是 React 新手,刚接触 .tsx 文件,不要担心!跟着这份指南,一步一步来,你很快就能上手了!👇 Ὅ…...
基于可信数据空间的企业数据要素与流通体系建设(附ppt 下载)
近期,可信数据空间会议召开。大数据系统软件国家工程研究中心总工程师王晨发表了题为《基于可信数据空间的企业数据要素与流通体系建设》主旨演讲。 篇幅限制,部分内容如下:...
二维数组:求最大元素及其所在的行坐标及列坐标(PTA)C语言
求出NM整型数组的最大元素及其所在的行坐标及列坐标(如果最大元素不唯一,选择位置在最前面的一个)。 函数接口定义: int fun(int array[N][M]) ; 注意:函数只需靠return返回最大元素的值, 行、列坐标通过…...
WebRtc01: 课程导学、框架介绍
应用 难点 课程大纲 学习收获 涉及内容 概述 用途 学习收获...
为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...
Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错
出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上,所以报错,到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本,cu、torch、cp 的版本一定要对…...
WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成
厌倦手动写WordPress文章?AI自动生成,效率提升10倍! 支持多语言、自动配图、定时发布,让内容创作更轻松! AI内容生成 → 不想每天写文章?AI一键生成高质量内容!多语言支持 → 跨境电商必备&am…...
12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...
JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...
3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...
用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...
Docker 本地安装 mysql 数据库
Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker ;并安装。 基础操作不再赘述。 打开 macOS 终端,开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...
Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
