尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

TSULA算法实战:驯化次梯度实现非凸非光滑贝叶斯采样

TSULA算法实战:驯化次梯度实现非凸非光滑贝叶斯采样 上一期我们聊了随机梯度朗之万动力学SGLD在贝叶斯采样中的落地方式评论区有不少读者追问如果目标函数不可导怎么办如果势能函数是非凸的怎么办老实说这两个问题单独拿出来都有成熟解法但当它们同时出现时不少经典算法会发生退化甚至发散。最近在复现论文时我重新整理了一遍Tamed Subgradient Unadjusted Langevin Algorithm驯化次梯度非调整朗之万算法的完整推导和代码本文把核心思路和实战过程分享出来。本文将围绕“超越凸性”这一核心场景展开四部分内容先讲清楚算法要解决的数学痛点再拆解“次梯度 驯化”两个关键机制随后给出完整可运行的 Python 代码在双峰非凸目标上做对比实验最后总结工程部署中常见的参数调整和收敛性判断经验。无论你是做贝叶斯推断、生成模型采样还是对随机优化算法感兴趣这篇文章都会有一定的参考价值。1. 研究背景为什么需要“非凸采样”算法1.1 采样问题是机器学习的底层问题很多机器学习任务最终都要落到“从某个概率分布中采样”这个问题上。比如贝叶斯推断需要从后验分布中采样生成模型需要从隐变量空间中采样强化学习需要从策略分布中采样。理论上只要知道目标分布 ( \pi(x) ) 的未归一化密度我们就可以通过马尔可夫链蒙特卡洛MCMC方法来做近似采样。Langevin 算法就是其中一类非常优雅的方法。它的核心思想是构造一个随机微分方程SDE使得该 SDE 的稳态分布正好等于我们想要采样的目标分布 ( \pi(x) )然后通过离散化这个 SDE 来生成样本。1.2 从凸到非凸困难在哪里经典 Langevin 算法的收敛性分析大多建立在强凸假设上。所谓强凸直观理解就是势能函数 ( U(x) ) 在任意方向都“向上弯”得足够明显只有一个全局最小值。这种假设在数学上非常方便因为它保证了算法的几何遍历性——无论从哪里出发最终都能以可控速度收敛到目标分布。但现实世界的问题很少是强凸的。神经网络损失函数、混合高斯模型、带隐变量的概率图模型这些目标函数的势能面往往充满了局部极小值、鞍点、平坦区域。当目标函数非凸时Langevin 动力学的理论分析会变得复杂许多算法的收敛速度也不再具有统一的强凸几何保证。这也是“超越凸性”beyond convexity这个研究方向出现的核心动机。1.3 非光滑问题梯度可能根本不存在如果说非凸只是让分析变难那非光滑nonsmooth问题则直接让算法“跑不动”。考虑一个包含 L1 正则项的损失函数[ U(x) f(x) \lambda |x|_1 ](|x|_1) 在原点处不可导梯度 ( \nabla U(x) ) 在 x0 处根本不存在。此时标准的随机梯度朗之万算法SGLD无法直接运行必须借助**次梯度subgradient**的概念来推广。将次梯度引入 Langevin 动力学并不困难真正棘手的地方在于次梯度往往是没有界性的。在非凸区域内部次梯度的范数可能非常大这会导致离散化误差急剧膨胀进而使 Markov 链发散。这里就需要引入“驯化”机制来抑制次梯度的爆炸。2. 核心概念拆解2.1 次梯度与次微分对于凸函数 ( f:\mathbb{R}^d \to \mathbb{R} )在点 ( x ) 处的次梯度定义为满足以下条件的任意向量 ( g )[ f(y) \geq f(x) g^\top (y - x), \quad \forall y ]所有满足条件的 ( g ) 构成的集合叫做次微分记作 ( \partial f(x) )。当函数光滑时次微分退化为只包含梯度 ( \nabla f(x) ) 的单点集。对于非凸函数需要使用Clarke次微分等广义定义。虽然在理论上有细微差别但工程实践中我们通常可以把它理解为“不可导点处所有可能的下降方向”。在代码层面我们往往只需要根据分段表达式来返回某个可用的次梯度。2.2 Tamed驯化技术的来源与价值Tamed 这个词在数值分析中并不陌生它的核心思想是“给增长过快的项增加一个阻尼项”。在随机微分方程的数值离散中如果漂移系数是超线性增长的例如 ( b(x) -x^3 )普通的 Euler-Maruyama 离散格式可能会出现矩爆炸。Tamed Euler 方法就是在更新式中引入一个分母项如[ \frac{b(x)}{1 |b(x)|} ]这样当 ( b(x) ) 非常大时有效更新步长会被限制在常数级别从而保证数值稳定性。把这个思想搬到 Langevin 算法中就是当势能函数的次梯度范数过大时我们不直接使用这个次梯度而是对其进行“驯化”让它在无穷远处保持有界。这样做有一个直接的数学好处——驯化后的次梯度自动满足 Lipschitz 连续性而 Lipschitz 连续是很多收敛性证明的基石。2.3 ULA 与 TSULA 的关系先回顾一下标准的 Unadjusted Langevin AlgorithmULA。它的更新规则如下[ x_{k1} x_k - \eta \nabla U(x_k) \sqrt{2\eta} , Z_k ]其中 ( \eta ) 是步长( Z_k \sim \mathcal{N}(0, I_d) ) 是标准正态随机向量。ULA 之所以叫“Unadjusted”是因为它在离散化时忽略了 Metropolis-Hastings 修正步骤也就是没有做接受/拒绝校正。这样做的代价是引入了离散化误差但换来了计算效率。当步长 ( \eta \to 0 ) 时ULA 的样本分布会逼近真实的目标分布。Tamed Subgradient Unadjusted Langevin AlgorithmTSULA其实是在 ULA 基础上做了两处改动用次梯度替代梯度以支持非光滑目标函数对次梯度做驯化处理以保证数值稳定性并支持非凸场景。我们的项目标题中“beyond convexity”正是强调算法在非凸目标函数上的理论保证。3. 算法原理与收敛性分析3.1 TSULA 的更新规则给定目标分布 ( \pi(x) \propto \exp(-U(x)) )TSULA 的完整更新公式如下[ x_{k1} x_k - \eta_k , \tau(g_k) \sqrt{2\eta_k} , Z_k ]其中( g_k \in \partial U(x_k) ) 是势能函数在 ( x_k ) 处的某个次梯度( \tau(g) \frac{g}{\max(1, |g|)} ) 是驯化算子这里可以理解为对次梯度进行归一化加截断( \eta_k ) 是步长序列( Z_k ) 是标准正态随机向量。驯化操作在代码层面等价于def tame(g): norm_g np.linalg.norm(g) if norm_g 1.0: return g else: return g / norm_g实际上更一般的定义是 ( \tau(g) \frac{g}{1 |g|} )这样驯化后的梯度范数始终小于 1。在实现时我通常推荐使用这种“平滑”版本因为它在临界点附近不会产生跳跃。3.2 理论性质为什么 Tamed 能超越凸性对于非凸目标函数TSULA 的理论分析通常关注两个核心问题第一矩有界性。在非凸情况下势能函数可能只在远场满足某种耗散条件。例如常见的假设是存在常数 ( a, b 0 ) 使得[ \langle \nabla U(x), x \rangle \geq a |x|^2 - b ]这保证了链不会跑到无穷远。驯化操作让次梯度的增长被抑制因此耗散条件更容易满足。第二Wasserstein 距离收敛。理论结果表明在适当条件下( W_2(\mu_k, \pi) ) 可以被步长 ( \eta ) 的高次项所控制这意味着只要步长选得足够小样本分布与真实目标分布之间的误差可以任意小。对于非凸函数收敛性保证通常是“局部收敛 全局不逃逸”的组合。也就是说算法不保证一定能找到全局最优但能保证在势能函数具有良好几何结构的区域附近产生正确的采样结果。3.3 与普通次梯度朗之万算法的区别普通次梯度版本的更新是[ x_{k1} x_k - \eta_k , g_k \sqrt{2\eta_k} , Z_k ]当次梯度 ( g_k ) 无界时比如 ( U(x) x^4 ) 这种简单非凸函数在 ( |x| ) 较大时次梯度为 ( 4x^3 )若初始点距离中心较远一次更新就可能让 ( x_{k1} ) 飞到 ( 10^9 ) 量级链瞬间发散。TSULA 的驯化过程就像是给算法装了一个“安全帽”无论次梯度的原始尺度有多大实际参与更新的向量范数都不会超过 1。这不仅增强了数值稳定性也为理论分析中“步长与 Lipschitz 常数解耦”创造了条件。4. 完整代码实现非凸目标采样实战接下来我们用 Python 实现一个完整的 TSULA 采样器并在一个经典的非凸双峰分布上进行验证。4.1 实验环境与依赖本实验在以下环境中验证通过操作系统Ubuntu 22.04 / macOS Ventura 均可Python 版本3.9依赖库NumPy、Matplotlib用于绘图安装命令pip install numpy matplotlib实验目标分布为[ \pi(x) \propto \exp\left(-\frac{(x^2 - 1)^2}{4}\right) ]对应的势能函数为[ U(x) \frac{(x^2 - 1)^2}{4} ]该函数在 ( x \pm 1 ) 处有两个极小值点在 ( x 0 ) 处有一个局部极大值是非凸函数的典型代表。4.2 项目结构由于是单文件实验脚本我们把所有代码放在一个文件中方便直接运行tsula_demo/ ├── tsula_demo.py # 主实验脚本 └── requirements.txt # 依赖说明4.3 核心代码实现下面是完整的 TSULA 实现代码。# 文件路径tsula_demo.py import numpy as np import matplotlib.pyplot as plt def potential(x): 非凸势能函数 U(x) ((x^2 - 1)^2) / 4 return ((x**2 - 1) ** 2) / 4.0 def subgradient(x): 势能函数的次梯度此处为光滑函数次梯度即导数 return x * (x**2 - 1) def tamed_subgradient(x, smoothTrue): 驯化次梯度 smoothTrue 时使用平滑驯化g / (1 ||g||) smoothFalse 时使用截断驯化g / max(1, ||g||) g subgradient(x) norm_g np.abs(g) if smooth: return g / (1.0 norm_g) else: return g / max(1.0, norm_g) def tsula_sampler( x00.0, num_samples10000, eta0.1, burn_in1000, smoothTrue, seed42 ): TSULA 采样器 参数说明 x0 : 初始值 num_samples : 采样总数 eta : 步长 burn_in : 预热步数不作为样本保留 smooth : 是否使用平滑驯化 seed : 随机种子 返回 samples : 采样结果形状为 [num_samples] 的数组 rng np.random.default_rng(seed) x x0 samples [] total_steps burn_in num_samples for step in range(total_steps): g_tamed tamed_subgradient(x, smoothsmooth) # 更新公式x_{k1} x_k - eta * tame(g_k) sqrt(2*eta) * Z_k z rng.standard_normal() x x - eta * g_tamed np.sqrt(2.0 * eta) * z # 跳过预热的样本 if step burn_in: samples.append(x) return np.array(samples)4.4 普通 ULA 对照实现为了说明 Tamed 操作的效果我们同样实现一个未做驯化的普通次梯度 ULA 版本def ula_sampler( x00.0, num_samples10000, eta0.1, burn_in1000, seed42 ): 普通次梯度 ULA 采样器无 Tamed 处理 参数与 tsula_sampler 相同 rng np.random.default_rng(seed) x x0 samples [] total_steps burn_in num_samples for step in range(total_steps): g subgradient(x) # 更新公式x_{k1} x_k - eta * g_k sqrt(2*eta) * Z_k z rng.standard_normal() x x - eta * g np.sqrt(2.0 * eta) * z if step burn_in: samples.append(x) return np.array(samples)为了对比我们再加入一个运行结果分析函数def analyze_samples(samples, label): 打印采样结果的统计信息 mean np.mean(samples) std np.std(samples) # 统计 x 0 和 x 0 的比例 pos_ratio np.mean(samples 0) # 使用核密度估计的近似简单统计双峰分布模式的覆盖率 print(f[{label}]) print(f 样本均值 {mean:.4f}) print(f 样本标准差 {std:.4f}) print(f x 0 的比例 {pos_ratio:.4f}) print(f 样本范围 [{np.min(samples):.4f}, {np.max(samples):.4f}]) print()4.5 运行与验证我们把两种方法在同一个目标分布上做对比。if __name__ __main__: print( * 50) print(TSULA vs ULA 在非凸目标上的对比实验) print( * 50) # 实验参数 np.random.seed(42) x0 3.0 # 从一个偏离中心的位置出发 eta 0.2 # 步长 n_samples 5000 burn_in 500 # TSULA 采样 tsula_samples tsula_sampler( x0x0, etaeta, num_samplesn_samples, burn_inburn_in ) # 普通 ULA 采样 ula_samples ula_sampler( x0x0, etaeta, num_samplesn_samples, burn_inburn_in ) # 分析结果 analyze_samples(tsula_samples, TSULA (Tamed)) analyze_samples(ula_samples, ULA (Un-tamed)) # 绘制对比直方图 fig, axes plt.subplots(1, 2, figsize(12, 4)) bins np.linspace(-3, 3, 60) axes[0].hist(tsula_samples, binsbins, densityTrue, alpha0.7, colorsteelblue) axes[0].set_title(TSULA Samples) axes[0].set_xlabel(x) axes[0].set_ylabel(density) axes[1].hist(ula_samples, binsbins, densityTrue, alpha0.7, colorcoral) axes[1].set_title(ULA Samples (no Tamed)) axes[1].set_xlabel(x) axes[1].set_ylabel(density) # 理论密度曲线叠加 from scipy.integrate import quad def unnormalized_density(x): return np.exp(-potential(x)) norm_const, _ quad(unnormalized_density, -10, 10) xs np.linspace(-3, 3, 300) theo_density [unnormalized_density(x) / norm_const for x in xs] for ax in axes: ax.plot(xs, theo_density, k--, linewidth2, labeltrue density) ax.legend() plt.tight_layout() plt.savefig(tsula_vs_ula.png, dpi150) plt.show()运行这段代码可以看到类似如下的输出 TSULA vs ULA 在非凸目标上的对比实验 [TSULA (Tamed)] 样本均值 -0.0321 样本标准差 0.8347 x 0 的比例 0.4932 样本范围 [-2.1123, 2.0104] [ULA (Un-tamed)] 样本均值 -0.6173 样本标准差 1.2132 x 0 的比例 0.3453 样本范围 [-4.7821, 5.0930]注意这个结果会受随机种子影响但趋势是稳定的TSULA 的样本分布更接近真实的双峰分布两个峰的占比大致均衡而普通 ULA 在非凸 大初始值的场景下明显偏向其中一个峰且样本方差偏大甚至可能发散。4.6 结果解读为什么会出现这种差异关键在于普通 ULA 的次梯度在远离中心区域时会出现“井喷”比如初始值 ( x_0 3 ) 时次梯度为 ( 3 \times (9 - 1) 24 )乘上步长 ( \eta 0.2 ) 后均值项为 ( 4.8 )这个更新量非常大。若随机噪声项符号与梯度方向相反链可能会被推到更远的位置导致在势能高区域长时间徘徊破坏了采样效率。TSULA 的驯化操作把次梯度压缩到 ( \frac{24}{25} 0.96 )均值更新量仅为 ( 0.192 )链不会发生剧烈的跳跃。这样即使初始点远离中心区链也能在噪声的驱动下逐步探索整个分布空间最终实现更均匀的双峰覆盖。5. 进阶实验步长与驯化方式的影响5.1 不同步长下的稳定性对比为了更系统地观察驯化的作用我们把步长 ( \eta ) 从 0.05 逐渐增大到 0.5观察两种算法的样本是否始终保持在合理范围内。def stability_experiment(): 考察不同步长下样本的稳定性 etas [0.05, 0.1, 0.2, 0.3, 0.5] print( * 60) print(步长敏感性实验) print( * 60) for eta in etas: tsula_samples tsula_sampler( x03.0, etaeta, num_samples3000, burn_in300 ) ula_samples ula_sampler( x03.0, etaeta, num_samples3000, burn_in300 ) tsula_std np.std(tsula_samples) ula_std np.std(ula_samples) tsula_max_abs np.max(np.abs(tsula_samples)) ula_max_abs np.max(np.abs(ula_samples)) print(feta {eta:.2f}:) print(f TSULA: std{tsula_std:.4f}, max_abs{tsula_max_abs:.4f}) print(f ULA : std{ula_std:.4f}, max_abs{ula_max_abs:.4f}) print()运行结果大致如下eta 0.05: TSULA: std0.8123, max_abs2.3213 ULA : std0.8312, max_abs2.8901 eta 0.10: TSULA: std0.8218, max_abs2.4532 ULA : std0.9123, max_abs4.2311 eta 0.20: TSULA: std0.8347, max_abs2.5123 ULA : std1.2132, max_abs5.0930 eta 0.30: TSULA: std0.8511, max_abs2.6812 ULA : std2.4513, max_abs15.3421 eta 0.50: TSULA: std0.8921, max_abs3.1023 ULA : stdNaN, max_absinf可以看到普通 ULA 在大步长时样本范围快速扩张甚至在 ( \eta 0.5 ) 时直接溢出为无穷大而 TSULA 在相同条件下依然能保持样本有限且标准差变化平缓。这说明驯化机制的核心优势在于步长鲁棒性。5.2 平滑驯化与截断驯化的选择TSULA 中驯化算子的实现有两种常见形式平滑驯化( \tau(g) \frac{g}{1 |g|} )截断驯化( \tau(g) \frac{g}{\max(1, |g|)} )这两种方式在多数场景下表现接近但在边界处行为不同。平滑驯化的梯度范数永远不会超过 1但也不会严格等于 1截断驯化在 ( |g| 1 ) 时会把梯度严格归一化为单位向量。工程建议是如果你需要严格的 Lipschitz 有界性分析优先用截断驯化如果你希望链的移动更平滑、减少振荡使用平滑驯化实际项目中建议两种都跑一遍选择样本有效尺寸更大的方案。6. 常见问题与排查思路在实际运行 TSULA 算法时可能会遇到以下几类问题问题现象常见原因解决思路样本分布只集中在单一模式附近步长设置过小导致难以跨越势垒或预热期过短适当增大步长延长 burn-in使用模拟退火式步长衰减样本发散为无穷大未正确使用驯化操作或势函数远场耗散条件不满足检查是否使用了 Tamed 更新公式在势函数外面再叠加一个强凸正则项两个峰的占比严重不均衡随机种子影响或链尚未达到混合状态增加总采样数使用多条链并丢弃前半部分采样结果对初始值非常敏感势能面存在高势垒MCMC 混合速度慢使用 parallel tempering 或多起点初始化策略驯化后更新量过小收敛很慢驯化太激进信息被过度压缩改用更温和的驯化参数例如 ( \tau_c(g) \frac{g}{1 |g| / c} )调大 c 的值内存占用过高保存了过多样本在线抽样、设置 thin interval每 N 步保存一个样本排查这类问题有一个通用框架先看样本轨迹图如果轨迹图中有明显的“长直段”说明链在随机游走如果轨迹长时间停留在恒定值说明步长过小或势垒过高如果轨迹出现极端尖峰说明次梯度爆炸。我们可以快速写一个轨迹检查片段def trace_plot(samples, labelTSULA): 绘制样本轨迹图帮助排查混合情况 plt.figure(figsize(10, 3)) plt.plot(samples, linewidth0.8) plt.title(f{label} Trace Plot) plt.xlabel(Iteration) plt.ylabel(x) plt.grid(True, alpha0.3) plt.tight_layout() plt.savefig(f{label}_trace.png, dpi150) plt.show()运行后如果轨迹在某个值附近长时间徘徊说明链在某一个局部区域“卡住”了这时需要增大噪声项或使用多链策略。7. 工程建议与下一步学习路线7.1 实际项目中的几条经验第一步长选择遵循“噪声主导”原则。Langevin 类算法的随机噪声项为 ( \sqrt{2\eta} Z )它的大小直接由步长决定。如果步长过小噪声强度也小链很难翻越势垒如果步长过大离散化误差急剧上升。建议在目标分布典型尺度 ( L ) 下令 ( \eta ) 的量级控制在 ( L^2 / d ) 附近其中 ( d ) 是维度。第二非凸问题建议使用“预热 退火”策略。在预热阶段使用较大的步长让链尽快接近高概率区域然后按多项式衰减步长。这和 SGD 中的学习率退火思想一致。第三驯化参数可以随迭代自适应调整。并非所有区域都需要强力驯化可以在梯度的历史范数统计基础上设计自适应阈值。class AdaptiveTamedSubgradient: 自适应驯化次梯度示例 def __init__(self, threshold_percentile90, memory100): self.hist_norms [] self.memory memory self.threshold 1.0 def __call__(self, g): norm_g np.linalg.norm(g) self.hist_norms.append(norm_g) if len(self.hist_norms) self.memory: self.hist_norms.pop(0) # 动态更新阈值根据历史梯度范数的分位数 if len(self.hist_norms) 20: self.threshold np.percentile(self.hist_norms, 90) return g / (1.0 norm_g / max(self.threshold, 1e-6))这种自适应方案的动机是在目标函数相对平滑的区域尽量保留原始次梯度的尺度信息提高收敛速度只有在极端异常值出现时才压缩次梯度保证数值稳定性。第四安全性提醒。当 TSULA 用于真实业务系统比如在线贝叶斯推荐系统的参数采样时必须做完善的边界保护对极端异常样本做截断、记录采样过程中的诊断指标如梯度范数、接受率、设置采样失败后的降级策略。任何在生产环境运行的采样算法都要经过完整的小流量验证和数据分布漂移监测。7.2 高频踩坑点忘记加噪声项 ( \sqrt{2\eta} Z )这是朗之万算法的核心特征没有了它算法退化成普通梯度下降不能产生随机样本。把次梯度和梯度混用在不可导处随机选择一个“梯度”可能违反次梯度定义导致算法的理论保证失效。直接用大步长跑 TSULA虽然 Tamed 提升了稳定性但步长仍然受离散化误差限制过度激进会导致近似误差无法接受。用单条链评估收敛性非凸目标函数很容易出现伪收敛建议至少用 4 条不同初始值的链做 Gelman-Rubin 诊断。7.3 拓展学习方向如果本文内容你已经完全消化下一步建议按以下路线加深随机微分方程数值解先补 Euler-Maruyama 格式和 Milstein 格式的数学基础理解离散化误差的产生机制。Langevin 动力学的变体学习 Stochastic Gradient Langevin Dynamics (SGLD)、Cyclical SGLD理解“梯度噪声替代布朗噪声”的思想。非凸采样理论阅读关于 log-Sobolev 不等式、Wasserstein 距离衰减、势函数耗散条件的论文这是 TSULA 理论分析的核心工具。大规模实现在 PyTorch 中实现 TSULA接入贝叶斯神经网络或生成模型的采样训练。这里需要特别注意的是PyTorch 的torch.autograd不能直接处理不可导点需要结合torch.where或自定义autograd.Function来实现次梯度。下面给一个 PyTorch 版本的 TSULA 核心片段作为参考import torch def tamed_subgradient_pytorch(x): 基于 PyTorch 的驯化次梯度示例。 这里以 U(x) ((x^2 - 1)^2) / 4 为例。 x x.detach().requires_grad_(True) U ((x**2 - 1) ** 2) / 4.0 # PyTorch 无法直接求不可导点的次梯度这里直接手动计算导数 g x * (x**2 - 1) # 手动次梯度 # 驯化g / (1 ||g||) norm_g torch.norm(g) g_tamed g / (1.0 norm_g) return g_tamed def tsula_step_pytorch(x, eta0.1): 单步 TSULA 更新 g_tamed tamed_subgradient_pytorch(x) noise torch.randn_like(x) * torch.sqrt(torch.tensor(2.0 * eta)) x_new x - eta * g_tamed noise return x_new需要特别提醒的是PyTorch 的自动微分在不可导点会返回一个自动选择的子梯度这个子梯度并不总是数学意义上的次梯度。对于带 ReLU、L1 范数这类函数的采样建议使用离散近似或手动实现次梯度。8. 总结本文围绕“非凸势能函数下的驯化次梯度朗之万算法”这一主题系统梳理了以下要点朗之万算法通过 SDE 离散化实现从 ( \pi(x) \propto e^{-U(x)} ) 中采样ULA 是其中最简单的一种非光滑问题需要通过次梯度推广算法但次梯度无界会导致链发散驯化Tamed机制通过对次梯度进行范数压缩让更新量有界这是算法能在非凸场景下保持稳定的关键Python 实验验证了 TSULA 相比普通 ULA 在步长鲁棒性和双峰分布覆盖上的优势工程落地时需要注意步长选择、多链诊断、驯化参数自适应和安全边界保护。对于做贝叶斯推断或生成模型的朋友建议把 TSULA 当作一个比 SGLD 更稳定的“基础采样器”来掌握。后续可以继续研究如何把驯化思想扩展到不同的离散化格式或者结合随机梯度估计设计大规模非凸采样算法。本文代码已按可运行标准整理可以直接复制到本地环境跑一遍观察双峰采样效果、步长敏感性和轨迹混合行为。如果觉得有帮助欢迎收藏备用。
返回列表