十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Langevin采样与Moreau-Yosida平滑:从非光滑目标到Active-Trace复杂度分析

Langevin采样与Moreau-Yosida平滑:从非光滑目标到Active-Trace复杂度分析 这是一篇理论向采样算法的解读文章不涉及图像生成、不涉及一键部署但非常值得做贝叶斯采样、随机优化、MCMC 算法分析的读者收藏。核心对象是 Langevin 采样并且带上了 Moreau--Yosida 平滑、Active-Trace 复杂度上界这两个关键词。如果说 ComfyUI 或 WebUI 类项目节省的是“调参成本”那么这类理论结果节省的是“推导成本”它告诉你对一个带非光滑正则项的后验分布做无调整 Langevin 采样时到底需要多少步才能把误差压到给定范围而且这个步数上界能不能不随全维度 d 线性增长而是只随问题真正“活跃”的方向数增长。先给一个直接判断如果你关心的是“L1 正则先验下的高维贝叶斯回归怎么采样收敛更快”“约束优化和目标分布采样能不能共用同一套近端算法”那这个方向比换采样器参数更值得先搞清楚。本文不贴具体实验数据因为这类论文的结果不像图像模型那样可以直接跑一个 WebUI 复现但它背后有一套非常清晰的数值验证逻辑我会把这套逻辑和实现模板完整拆开。1. 理论成果速览很多读者看到 “Complexity Bounds” 会先退一步担心全文都是定理。这里先给一张速查表把整个研究对象的骨架列出来。维度说明研究对象对非光滑、非强凸目标分布进行近似的 Unadjusted Langevin SamplingULA采样算法方法核心用 Moreau--Yosida 正则化构造光滑近似目标再走 Langevin 离散更新关键概念Active-Trace 复杂度把迭代步数上界和轨迹上的有效协方差迹联系起来解决痛点直接在非光滑分布上做次梯度 Langevin 更新理论上难以给出干净的收敛上界理论输出给出了 2-Wasserstein 距离或 KL 散度意义下的迭代复杂度边界适用问题贝叶斯后验采样、强凸或凸光滑损失加 L1 约束、带约束参数空间采样典型目标形式(p(\theta)\propto \exp(-f(\theta)-\phi(\theta)))其中 f 光滑φ 不可导但结构简单验证方式构造已知后验的合成问题运行近端 Langevin 更新用距离指标观察误差衰减硬件要求实际验证阶段不需要大显存1000 维以下的合成问题普通 CPU 就能跑读者类型关注 MCMC、贝叶斯推断、采样算法复杂度分析的算法工程师与研究型开发者先记住一个结论这篇工作不是来告诉你“哪个采样器出图更快”而是告诉你“在高维参数空间里非光滑项不该成为你放弃使用 ULA 的原因”。2. 背景问题为什么 Langevin 采样需要处理非光滑目标先回顾随机微分方程形式。连续时间 Langevin 动力系统的稳态分布就是目标分布 π其形式是[ dX_t \nabla \log \pi(X_t) dt \sqrt{2} dW_t. ]令 (U(\theta)-\log \pi(\theta))并称为势能函数那么上面的方程可以写成[ dX_t -\nabla U(X_t) dt \sqrt{2} dW_t. ]实际执行时不可能真的模拟连续随机微分方程通常会做 Euler-Maruyama 离散化得到[ \theta_{k1} \theta_k - h\nabla U(\theta_k)\sqrt{2h}Z_k, ]其中 (Z_k\sim N(0,I_d))。这个离散迭代就是 ULA。Unadjusted 表示采样过程中不做 Metropolis-Hastings 校正步骤因此每一步计算都很便宜非常适合高维参数空间。但这里马上会碰到一个矛盾。贝叶斯推断里非常常见的先验项比如 L1 稀疏先验、Box 约束、区间约束都会让 U 出现不可导点。L1 正则对应的势能是 (U(\theta)\alpha|\theta|_1)这个函数在某个坐标恰好为 0 时不可导。约束类问题更麻烦(U(\theta)\delta_C(\theta)) 这种指示函数几乎处处不可解释为普通梯度。若直接采用次梯度版本[ \theta_{k1}\theta_k-hg_k\sqrt{2h}Z_k,\quad g_k\in\partial U(\theta_k), ]那么理论上就很难再用常规的强凸光滑假设去推收敛速度。次梯度在不可导点可能有强烈振荡步长稍大就容易让轨迹偏离目标分布的高概率区域。这就是整个研究方向产生的动机能不能先把非光滑目标“磨平”再套用 ULA 的成熟理论框架。Moreau--Yosida 正则化就是用来做“磨平”的标准数学工具而且它和近端算子之间有非常直接的解析关系。3. 从 ULA 到 Moreau--Yosida 平滑化Moreau--Yosida 正则化的定义对任何一个闭凸函数 (U) 都成立。对参数 (\lambda0)定义[ U_\lambda(y)\min_z\left{U(z)\frac{1}{2\lambda}|z-y|^2\right}. ]这个函数 (U_\lambda) 有两个非常重要的性质第一(U_\lambda) 是凸且光滑的。对闭凸函数来说Moreau 包络的梯度是 Lipschitz 连续的Lipschitz 常数不超过 (1/\lambda)。这让它天然适合放进 ULA 更新中使用梯度。第二(U_\lambda) 的梯度可以用近端算子直接表示。对上述问题做一阶最优性条件可以得到[ \nabla U_\lambda(y)\frac{1}{\lambda}\left(y-\operatorname{prox}_{\lambda U}(y)\right), ]其中[ \operatorname{prox}_{\lambda U}(y)\arg\min_z\left{U(z)\frac{1}{2\lambda}|z-y|^2\right}. ]这个形式理论价值很大。它说明只要能够高效计算目标势能的近端算子就能得到光滑化后目标的梯度剩下的更新就是一次带噪声的梯度下降[ \theta_{k1}\theta_k-h\nabla U_\lambda(\theta_k)\sqrt{2h}Z_k. ]对很多常见非光滑函数来说近端算子是非常容易计算的闭式解。以 L1 范数 (\phi(\theta)\alpha|\theta|_1) 为例其近端算子就是软阈值算子[ \operatorname{prox}_{\lambda\phi}(y)_i\operatorname{sign}(y_i)\max(|y_i|-\lambda\alpha,0). ]如果约束是 (C[a,b]^d) 的 Box 约束目标函数里加入指示函数后近端算子就是简单截断[ \operatorname{prox}_{\lambda\delta_C}(y)_i\min(\max(y_i,a),b). ]这意味着即便原问题整体复杂只要非光滑部分都落在这些有闭式近端的函数组合里实现 MY-ULA 就只需要写近端求解函数不需要手动处理任何次梯度。工程上唯一要注意的是实际计算时通常不会直接去求解整个复合函数 (Uf\phi) 的 Moreau 包络因为如果 f 不是简单的二次函数内层最小化可能没有解析解。更常见的处理方式是把它理解为一种算子分裂光滑部分 f 直接计算梯度非光滑部分 φ 在每次迭代后执行一次近端映射。也就是说实际更新往往写成[ \theta_{k1}\operatorname{prox}_{h\phi}\left(\theta_k-h\nabla f(\theta_k)\sqrt{2h}Z_k\right). ]这个式子也可以看作对 MY-ULA 在步长足够小时的近似实现。理论分析时假设每一步都能求解出精确的 Moreau 包络梯度实现时则用近端映射近似。合成问题验证阶段通常优先选择 φ 有解析近端的设定这样才能保证迭代行为更贴近理论模型。4. Active-Trace 复杂度到底在衡量什么先看光滑强凸情况下 ULA 的经典复杂度结论。当目标分布满足强凸和光滑条件时离散化步长会带来两个误差来源一个是梯度离散化误差另一个是每一步注入的 Gaussian 噪声的累积协方差。在很粗糙的描述下固定步长 h 的 ULA 最终无法让采样分布完全收敛到目标分布而只能收敛到目标分布附近的一个正则化分布二者之间的偏差大约是 (O(h))。如果想要达到 2-Wasserstein 距离不超过 ε最优步长和迭代步数之间会形成一个权衡最终复杂度往往表现为[ O\left(\frac{d}{\varepsilon}\right) ]这一类形式或者是在更细的分析里出现 (O(\sqrt{d}/\varepsilon))(O(d/\varepsilon)) 这样的分子。这里的 d 为什么会出现并不完全是因为高维计算代价高而是因为每一步注入的噪声在统计上会混合所有 d 个方向。如果目标分布在很多方向上信息量很少这 d 个方向仍然会全部进入更新的随机波动中最终把步数和精度之间的权衡拖慢。问题在于真实高维后验经常不是每个维度都同等重要。以高维稀疏线性回归为例真实系数可能只有 k 个非零分量但参数向量本身有 d 个坐标d 可能是数千甚至百万。经典复杂度界的缺陷就在这里它默认所有维度的困难度一样于是系数里必然出现 d。即使大多数坐标根本不和观测数据发生强耦合也会被无差别地计入复杂度。Active-Trace 的思想是把复杂度中这个维数因素替换成一个更精细的量。直观上可以把离散化过程看成在每一步扰动上加权了一个协方差结构而这个结构中某些方向贡献很小。那么影响最终误差的就不是全部维度 d而是一个沿着算法轨迹估计出来的有效迹。这个有效迹在特定结构下可以远小于 d从而得到更紧的复杂度边界。这类界通常会出现在与轨迹协方差矩阵相关的量中比如沿着迭代点计算梯度协方差或噪声在 Hessian 度量下的迹。如果目标分布在很多方向上非常集中那么协方差在这些方向的乘积项会很小活性迹也就相应变小。于是复杂度从依赖全维度 d 变成依赖某种有效维度或有效迹。它并不代表只需要对少于 d 个方向做计算而是代表误差传播结构本身具有低有效维数理论分析可以把这个结构识别出来。这个改进和随机优化领域里常见的“有效维度”概念有关联但在采样算法里更难证明因为 Langevin 迭代带有随机噪声噪声在每次迭代中都是全维度的不能简单裁剪掉不活跃的方向。真正有价值的理论工作就是证明即便迭代本身仍然是在 d 维空间中进行最终复杂度上界依然可以被 Active-Trace 控制。对读者来说理解它的工程含义就够了如果问题天然稀疏或天然低秩那么不需要在理论上被迫接受一个和全维度线性相关的迭代步数只要能量函数在多数方向上提供了足够的约束算法收敛是有可能比最坏情况快得多的。5. 从理论到代码实现一个近端 Langevin 验证程序理论上说完现在讨论怎样在合成问题上做数值验证。验证一类采样复杂度界不需要完整复现论文里的每一个引理但至少要复现算法更新格式并观察两个指标误差随迭代次数的衰减速度以及衰减速度随问题有效维数的变化。先选择一个最简单的验证场景带 L1 先验的贝叶斯线性回归。令响应变量为[ yX\theta^*\epsilon, ]其中 (\theta^*\in\mathbb R^d) 只有 k 个非零坐标(X\in\mathbb R^{n\times d}) 是设计矩阵噪声 (\epsilon\sim N(0,\sigma^2 I_n))。使用 L1 先验 (p(\theta)\propto \exp(-\rho|\theta|_1))此时后验可以写成[ p(\theta\mid X,y)\propto \exp\left(-\frac{1}{2\sigma^2}|y-X\theta|_2^2-\rho|\theta|_1\right). ]这是一个标准的非光滑对数凹后验。它的非光滑部分只有 L1 范数近端算子就是软阈值。于是实现近端 Langevin 采样只需要写几行 Python 代码。这里给出完整模板import numpy as np rng np.random.default_rng(0) d 100 k 8 n 300 sigma2 1.0 rho 0.5 # 构造稀疏真实参数 theta_star np.zeros(d) support rng.choice(d, sizek, replaceFalse) theta_star[support] rng.normal(sizek) # 生成设计矩阵和观测 X rng.normal(size(n, d)) y X theta_star rng.normal(sizen) * np.sqrt(sigma2) def soft_threshold(x, threshold): return np.sign(x) * np.maximum(np.abs(x) - threshold, 0.0) def log_posterior(theta): return -0.5 * np.sum((y - X theta) ** 2) / sigma2 - rho * np.sum(np.abs(theta)) def run_proximal_ula(X, y, rho, sigma2, init, step_size, num_iters): d X.shape[1] samples np.zeros((num_iters 1, d)) theta init.copy() samples[0] theta for it in range(num_iters): grad (X.T (X theta - y)) / sigma2 noise rng.normal(sized) * np.sqrt(2 * step_size) proposal theta - step_size * grad noise theta soft_threshold(proposal, step_size * rho) samples[it 1] theta return samples init np.zeros(d) step_size 1e-3 num_iters 20000 samples run_proximal_ula( X, y, rho, sigma2, init, step_sizestep_size, num_itersnum_iters, ) # 丢弃 burn-in 后统计 burn_in 5000 chain samples[burn_in:] sample_mean np.mean(chain, axis0) sample_cov np.cov(chain, rowvarFalse) print(estimated support:, np.where(np.abs(sample_mean) 0.1)[0]) print(true support:, support)这段代码不会直接在终端打印一个漂亮数字它只是验证框架。判断程序是否在正确工作的关键点有三个。第一近端映射是否在每一步都正确执行。如果忘了 soft threshold而是直接对原始梯度做更新那么采样链会在 L1 不可导区域附近出现明显振荡。判断方法很简单在没有任何稀疏化约束时样本均值向量往往没有一个分量严格接近 0而正确执行软阈值后绝大多数非支撑点都会稳定在 0 附近。第二样本协方差是否保持稳定。运行到后半段时如果步长过大链会持续发散或跳跃到很大值。可以在代码里增加一个中断条件比如定期计算当前样本的二阶矩。如果二阶矩在持续增长且没有收敛迹象说明步长 h 超出稳定范围。第三真实支撑向量与估计支撑向量是否一致。这个指标在无法直接拿采样分布和理论分布做精确比较时是最直观的代理指标。上面代码只是近端 Langevin 的一个基本版本。若要验证的是带有理论性质的 MY-ULA通常会把迭代中的一步 near-end prox 替换成更接近 Moreau 包络梯度的形式。可以这样简单理解理论文章中的更新更依赖 Moreau 包络的解析结构而代码验证中只需要确保每次更新在步长较小时和 Moreau 包络方向一致。6. 实验设计如何验证 Active-Trace 相关的复杂度行为采样器本身能跑并不等于能够验证复杂度界。复杂度界回答的是这样一个问题给定允许误差 (\varepsilon)最小需要多少步Active-Trace 类结果的更细微差别在于这个步骤数是否与全量维度 d 关系不大而更像与真正活跃的结构有关。在合成实验里可以设置一组可控对照固定 d200、n200真实 (\theta^*) 的非零分量数量 k 分别取 5、10、20每次实验使用相同的初始值、相同步长、相同随机种子只改变 k观察算法达到同样精度所需的迭代步数变化。如果复杂度只依赖全维度 d那么 k 从 5 增长到 20 时达到目标精度所需的步数不会发生可预期的改变因为 d 没有变。如果 Active-Trace 相关复杂度成立那么在其他条件相同时活跃维数越少采样轨迹在每个有效方向上的混合速度越快达到同精度所需步数应该更短或至少不应变长。这里有一个容易混淆的点进行这个对照实验时并不是直接数“第几千步后进入高概率区域”而是要用一个距离指标来测误差。常见的选择是 2-Wasserstein 距离或最大均值差异。完全在非高斯后验上精确计算 2-Wasserstein 不容易但在线性回归加 L1 先验这种较为规范的问题里可以用一阶矩和二阶矩的误差作为替代。此时核心指标是样本均值向量与真实 (\theta^*) 之间的 L2 距离以及样本协方差与某种参考协方差之间的差异。代码可以参考下面这个精简评估版本def evaluate_chain(samples, burn_in, theta_star): chain samples[burn_in:] chain_mean np.mean(chain, axis0) chain_cov np.cov(chain, rowvarFalse) mean_err np.linalg.norm(chain_mean - theta_star) trace_cov np.trace(chain_cov) return mean_err, trace_cov需要明确的是单次实验的 chain_cov 会受到初始化状态、随机噪声等因素影响因此更稳定的判断方式是执行多组随机种子并记录误差的对数与迭代步数之间的下降曲线。如果画出的误差衰减曲线在 k 较小的时候斜率更陡而在 k 较大时变得平缓那么这个现象与 Active-Trace 复杂度所描述的方向是一致的问题每增加一个真正活跃的方向就会增加一部分需要被采样的有效信息。需要注意的是这里并不建议直接下结论说“实验证明了定理”。数值实验无法证明理论界但能够帮助你在复现论文结果时快速发现实现错误。比如如果理论作者声称复杂度是随有效迹变化但你的实验发现支撑集大小 k 的变化对收敛速度毫无影响那你就应该回到实现中检查是否有 bug。这种验证流程是理论型博客中最实用的工作流。7. 批量运行与参数扫描验证复杂度界通常不会只跑一次。更规范的做法是批量扫描参数并把指标写入 CSV 文件。这里给一个通用模板import pandas as pd configs [] for d in [100, 200, 400]: for k in [10, 20, 40]: for seed in [1, 2, 3]: configs.append({d: d, k: k, seed: seed}) results [] for cfg in configs: X, y, theta_star generate_data(cfg[d], cfg[k], cfg[seed]) init np.zeros(cfg[d]) samples run_proximal_ula( X, y, rho, sigma2, init, step_sizestep_size, num_iters20000, ) mean_err, trace_cov evaluate_chain(samples, burn_in5000, theta_startheta_star) results.append({ d: cfg[d], k: cfg[k], seed: cfg[seed], mean_err: mean_err, trace_cov: trace_cov, }) df pd.DataFrame(results) df.to_csv(active_trace_scan.csv, indexFalse)用 CSV 保存结果的好处是最后可以按 d 和 k 分组绘制误差曲线而不需要重新执行昂贵的采样过程。参数矩阵扫描在 CPU 上就能完成只有当维度上升到万级才需要 GPU 或用批处理梯度来加速矩阵乘积。因为这属于采样算法验证而不是深度学习训练显存不是主要瓶颈真正的瓶颈往往是迭代次数和链长。实际运行中建议先设置一个较短链长做冒烟测试比如先跑 2000 步确认没有显式报错、近端函数没有产生 NaN再正式运行完整参数扫描。很多实验失败并不是因为理论有问题而是因为初始步长太大链在一两千步内就发散到数值溢出。8. 显存、CPU、GPU 与性能观察虽然这里没有像图像生成一样直接给出固定显存占用但还是值得说明性能观察方法。近端 Langevin 采样每个迭代的主要计算开销来自梯度计算。在贝叶斯线性回归中这一步是 (X^T(X\theta-y))其成本是 (O(nd))。如果 d 是 10000n 是 1000那么单次迭代大约需要计算千万级浮点运算纯 Python 的逐维循环会非常慢正确实现要用向量化 NumPy 操作。对于维度低于 2000 的问题CPU 单线程足够完成所有测试。达到上万维时可以用 GPU 加速矩阵乘法但要注意随机数生成在高维循环里也可能成为瓶颈。此时可以把整批正态噪声一次性生成避免每次迭代都调用 rng.normal 产生重复开销。显存占用方面如果使用 PyTorch 实现并把 (X)、(\theta) 和噪声张量全部放在 GPU 上(n1000,d10000) 的矩阵乘法只需要几十 MB 显存真正变大的是采样链的存储。如果一次把所有中间链都保留在 GPU 显存中比如保存 100000 次迭代的 d 维样本就是 (100000\times10000\times8) 字节约 8GB。避免显存爆掉的常规做法是只保存 burn-in 之后的低频样本或者定期把 GPU 上的链拷贝回 CPU。性能观察的核心指标有三个每次迭代耗时有效样本量误差随迭代次数的下降曲线。如果 Active-Trace 相关复杂度结论成立且问题稀疏那么比较不同 k 值下的有效样本量时应该看到活跃维数 k 低时同样的链长能带来更高的有效样本量。这不是一个偶然现象而是低有效维数带来更好的混合速度的直接反映。9. 常见问题与排查方法理论型代码与图像模型代码不同它不会输出可视化的漂亮图片所以调试时更需要结构化排查。这里把最容易踩的坑列成清单。问题现象可能原因排查方式解决方案链快速发散到极大值步长 h 过大打印前 100 步参数范数将 h 缩小到原来的 0.1 倍再测试所有样本都变成 0软阈值收缩过大检查 rho 和步长的乘积降低 rho 或步长样本均值和真实参数差距大burn-in 太短画出链后 5000 步的轨迹增加 burn-in 或增大迭代轮数误差下降曲线非常慢目标条件数过大步长受到约束检查设计矩阵 X 的条件数对特征做标准化或使用预条件矩阵同一配置不同随机种子结果差异很大单条链方差大按 seed 重复多次实验使用多条链取平均或提高链长CPU 上跑得太慢每次迭代只生成少量随机数用 profile 查看热点批量生成噪声减少 Python 循环近端映射导致 Step NaNsoft threshold 前数值溢出检查 proposal 是否已发散先缩短步长再考虑梯度裁剪看上去收敛但理论复杂度曲线对不上误差指标测量不准确检查是否加入了 burn-in 前的样本在误差计算中严格去掉 burn-in在调试这类代码时最重要的一条规则是先用小维度做可观测实验。比如 d10真值 (\theta^*) 中只有 2 个非零这时你可以手动计算目标后验的大致位置也可以通过更强的先验让后验接近高斯从而用解析协方差验证采样器是否正确。只有当小规模实验的输出符合理论预期再扩大到百维甚至千维才有意义。另一个容易踩坑的地方是步长选择。多数复杂度理论结果都会给出一个保守步长范围但实际合成实验中步长可以比理论保守值大一些。盲目使用过小步长会得到收敛但需要非常多迭代步步长过大会让链越过约束边界或离开 L1 非光滑区域时来回振荡。更稳妥的方法是先以 0.1 倍理论步长做测试再逐步放大直到误差不再明显下降为止。10. 如何正确解读一个复杂度和理论结论这一节稍微展开理论态度的部分。对于大多数做工程落地的算法工程师接触这类理论文章最容易出现的误解是认为“证明了一个更好复杂度上界就代表算法实际运行更快”。实际并非如此。复杂度上界描述的是最坏情况下要达到一定精度需要多少步的比较关系。Active-Trace 类型界经常能给出比 d 相关更紧的上界但也是“上界”而不是“真实收敛速度”。在实验中观察到的现象可能比上界好也可能比上界差。上界真正的价值是定位瓶颈如果理论界说复杂度应该随有效迹缩放但实际代码在增加无关维度 d 时严重变慢那么实现中很可能存在额外问题。第二个常见误解是把“不调整”当成可有可无的细节。ULA 与 MALA 的区别就是少了 Metropolis 校正步骤。少了校正就失去了精确不变性每次离散化都会造成 (O(h)) 的稳态误差。因此使用固定步长的 ULA 或 MY-ULA 时最终采样链并不严格来自目标分布而是来自一个被平滑过的近似目标。在验证代码时不能把链直接当成精确后验样本使用比较误差时也要预留由 h 造成的偏置。第三个误解与 Moreau--Yosida 有关。有人会认为平滑化只是为了让梯度存在实际和直接做次梯度差别不大。但两者的理论性质明显不同。Moreau 包络是凸且光滑的这意味着可以复用 ULA 在光滑凸目标上的整套分析工具比如强凸、光滑、LSI 常数等次梯度则很难放进这些标准框架中。因此Moreau--Yosida 不是一个工程取巧技巧而是让理论从非光滑情形回到成熟框架的关键工具。理论上阅读这类文章时应关注四个问题目标函数需要满足什么正则性条件是否需要强凸凸但不强凸时如何加正则项复杂度依赖的是 d、还是某个可以实际计算的迹量步长 h 的上界依赖哪些与问题相关的常数当你能准确回答这四个问题把这篇论文迁移到自己的贝叶斯模型就不再是只有阅读没有产出。11. 实战建议从阅读论文到可复现实验的最小闭环这里给出一套完整的最小闭环建议适合想验证此类理论结果或进行扩展研究的开发者。第一步实现最简采样器。选择 L1 先验线性回归把维数控制在 100活跃维数控制在 5。这样可以在 1 分钟内在 CPU 上跑完数千次迭代且任何明显 bug 都会立刻暴露。第二步校验梯度与近端算子。如果自己实现了非标准正则项不要只凭直觉调用 soft threshold。对平滑部分 f 做一次数值梯度检查def numerical_grad(f, x, eps1e-6): grad np.zeros_like(x) for i in range(len(x)): xp x.copy() xm x.copy() xp[i] eps xm[i] - eps grad[i] (f(xp) - f(xm)) / (2 * eps) return grad把数值梯度和解析梯度对比确保平滑部分没有实现错误。非光滑近端算子的正确性可以用如下恒等式验证[ \operatorname{prox}_{\lambda\phi}(x)\arg\min_z\left{\phi(z)\frac{1}{2\lambda}|z-x|^2\right}. ]第三步做步长扫描。对一组 log 等间距步长记录链的均方误差和接受率或轨迹范数。这个实验可以直接得到该目标下步长 h 的可工作上限。第四步观察有效迹的变化。如果 Active-Trace 类复杂度是关注重点那么需要设计一个包含稀疏结构的合成目标。一个比较经典的模型是稀疏线性回归另一个是带有强先验的随机效应模型。在这类目标中真实后验协方差矩阵的某些方向方差极小这会让 Active-Trace 远小于 d。第五步在报告中保留完整实验配置。写清目标形式、样本生成方式、初始化、步长、迭代数、burn-in、随机种子。理论类实验最怕结果不可复现而采样算法又偏偏对随机种子极其敏感所以每一次实验都应当把种子、参数和输出完整记录。从更功利的角度说验证完这套近端 Langevin 流程之后你其实已经掌握了一类可以直接迁移到工程问题的工具。很多真实场景中的目标分布都包含“光滑损失 简单非光滑正则”这种复合结构比如带 L1 惩罚的逻辑回归、带 Box 约束的推荐系统参数推断、带稀疏先验的时序模型。只要能写出后验的势能形式并把非光滑部分的近端算子给出来下面的采样与复杂度观察流程就基本一致。12. 总结与下一步方向这篇文章没有给你一个能直接安装的库也没有一键启动界面。它的价值在于把 Moreau--Yosida、ULA、Active-Trace 复杂度这三件事连成一条可以实际操作的链路先用 Moreau--Yosida 正则化解决非光滑问题再用 ULA 做低成本的未校正采样最后用 Active-Trace 来判断高维目标的有效复杂度和收敛行为。建议先跑通上面那个 L1 贝叶斯线性回归的最小代码确认软阈值近端和梯度下降能稳定工作。然后试着把代码里的 L1 替换成 L2 约束甚至 Box 约束观察近端映射改变后收敛曲线的变化。这个替换动作本身并不复杂但能帮助你直观理解非光滑项对收敛的影响并不会因为加了噪声而消失。如果只想记住一个实验结论那应当是不能假设高维问题一定需要 d 量级的采样步数。当后验具有显著的稀疏结构或低秩结构时近端型 Langevin 采样在适当步长下有可能表现出明显优于最坏情况的收敛行为。主动去度量这个结构正是 Active-Trace 复杂度界想要做的事情。下一步可以做两件事一是把合成实验中的“稀疏结构”拓展为“块稀疏结构”或“低秩结构”观察 Active-Trace 是否依然有效二是把近端 Langevin 与 MALA 或 HMC 做对比看无调整的步数优势在多大维度下能弥补偏置代价。这类实验跑完你对采样算法的理解会比单纯调包深刻很多。
返回列表