ARTICLE DETAIL

资讯详情

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

PyMC贝叶斯变分自编码器完整指南:用pm.fit三步搭出MNIST生成模型

PyMC贝叶斯变分自编码器完整指南:用pm.fit三步搭出MNIST生成模型 PyMC贝叶斯变分自编码器完整指南用pm.fit三步搭出MNIST生成模型【免费下载链接】pymcBayesian Modeling and Probabilistic Programming in Python项目地址: https://gitcode.com/GitHub_Trending/py/pymcPyMC 是 Python 里做贝叶斯建模的概率编程库。本文用它的变分推断功能pm.fit搭一个贝叶斯 VAE变分自编码器大约 30 行代码跑通 MNIST 的生成、重构与隐空间插值。一、为什么不用 MCMC 而用变分推断pm.sample要跑一万步 MCMC参数维度一大就得熬半天——有没有更快拿到够用结果的路维度MCMCpm.sample变分推断pm.fit得到什么后验样本集参数可能取值分布的抽样一个参数化的近似分布 q高斯精度保证渐近精确有 R-hat 等诊断只保证最大化数据对数似然的下界ELBO代价每步算一次似然大模型慢梯度优化一组变分参数接近神经网络训练速度典型定位交付级精度探索、大模型、需要快速后验的场景MCMC 慢在走一步、算一次似然几千个参数就是几千次求值。变分推断换了问法不采样而是直接拿一个参数化的分布去逼近后验用梯度下降把它推到最像。代价是引入近似误差——ADVI自动微分变分推断用的是高斯族真正的多峰后验它描述不了好处是全程由 PyTensor 编译执行可挂backendnumba或jax提速。分工很清楚先用pm.fit拿可用后验需要严格精度校验时再换回pm.sample。二、VAE 的三个角色编码器、隐变量、解码器VAE 不是三个网络而是三个角色每个角色在 PyMC 里都能一行写出编码器把数据映射到隐变量上的分布。本文不手写编码器ADVI 为 z 学到的后验q(z|x)直接充当这个角色隐变量把整批图像信息压缩成的一小组连续变量 z例子里是 20 维、标准正态先验解码器把 z 通过带先验的贝叶斯权重算出 784 维概率再经 Bernoulli 似然与图像对比。训练目标是最大化 ELBO证据下界数据对数似然的可算下界$$\mathrm{ELBO}\mathbb{E}_{q(z)}\big[\log p(x\mid z)\big]-\mathrm{KL}\big(q(z),\Vert,p(z)\big)$$第一项是重构项z 重构出的图像与原图有多一致即代码里的 Bernoulli 似然$p(z)$ 是先验默认标准正态是隐空间的出厂设置KL 项是正则把 q 拉回先验防止 z 任意漂移。对应到源码pymc/variational/operators.py里的KL算子按log q − log p加数据对数似然计算approx.hist记录的就是这个 loss负 ELBO。三、三步跑通 MNIST下面一个例子贯穿三步可直接当最小 PyMC VAE 教程照抄。第 1 步数据准备把像素归一化到 [0,1]Bernoulli 概率语义才对得上import numpy as np import pymc as pm import pytensor.tensor as pt from sklearn.datasets import fetch_openml # mnist_784 共 70000 张取前 10000 张足够本例 X fetch_openml(mnist_784, version1, as_frameFalse).data[:10000] X X / 255.0 # 灰度归一化到 [0, 1] print(X.shape) # (10000, 784)第 2 步pm.Model 定义生成过程 pm.fit 训练三个角色一个pm.Model写完权重是带先验的随机变量z 是隐变量Bernoulli 是似然。然后一行pm.fit交给 ADVI 优化latent_dim 20 # 隐空间维度 with pm.Model() as vae: w_dec pm.Normal(w_dec, 0, 0.5, shape(latent_dim, 784)) # 贝叶斯解码权重 b_dec pm.Normal(b_dec, 0, 0.5, shape784) # 偏置 z pm.Normal(z, 0, 1, shapelatent_dim) # 共享隐变量 p_recon pt.sigmoid(pt.dot(z, w_dec) b_dec) # 解码 obs pm.Bernoulli(obs, pp_recon, observedX) # 似然 approx pm.fit(n10000, methodadvi, random_seed42) # ADVI 训练训练完approx就是拟合好的变分后验均值、协方差、ELBO 历史都能从它读。第 3 步采样近似后验、生成重构图approx.sample从 q 里抽样本再喂给解码器得到重构import matplotlib.pyplot as plt idata approx.sample(draws200, random_seed0) # 从近似后验抽 200 个样本 z_s idata.posterior[z].values # (200, 20) w_s idata.posterior[w_dec].values # (200, 20, 784) b_s idata.posterior[b_dec].values # (200, 784) # 每个样本各自过解码器后取平均得到模型重构的平均脸 recon 1 / (1 np.exp(-(z_s[:, :, None] w_s b_s[None]))) recon recon.mean(0).reshape(28, 28) fig, ax plt.subplots(1, 2, figsize(8, 4)) ax[0].imshow(X[0].reshape(28, 28), cmapgray) ax[1].imshow(recon, cmapgray) plt.show()一点坦白z 是全批共享的所以这里重构的是整批数据的平均脸不是逐张图像的重构逐张重构需要把编码器做成逐样本网络见第六节。四、怎么判断模型练好了能跑通不等于练好了三个指标各有一条合格线ELBO 收敛曲线画plt.plot(approx.hist)。合格线最后 1000 步的 loss 基本走平、线性拟合斜率接近 0还在明显下降就加大n或用approx.refine(5000)续训。重构对比重构平均脸应能认出数字笔画而不是一团模糊灰斑。模糊先查数据是否归一化、latent_dim是否过小。隐空间插值取两个后验 z线性插值再解码中间点应连续过渡、无跳变z1, z2 z_s[0], z_s[100] path z1 np.linspace(0, 1, 6)[:, None] * (z2 - z1) # (6, 20)逐点过解码器展示近似后验本身也可以用森林图形式可视化检查各参数的可信区间五、选择与踩坑MeanField、FullRank 与 pm.fit 常见报错踩坑基本集中在三个选择上问题选项判断依据近似族methodadviMeanField各参数独立高斯默认最快探索期、后验看不出明显参数间相关时近似族methodfullrank_adviFullRank允许完整协方差参数量 O(d²)捕捉参数相关均值场系统性低估不确定性、参数强相关时隐维度怎么定5~50 起试太小重构糊太大隐变量退化、只有少数维有效FloatingPointError: NaN occurred in optimization学习率过猛或梯度爆炸给pm.fit传total_grad_norm_constraint限幅KeyError: method should be one of ...方法名写错只有advi/fullrank_advi/svgd/asvgd四个合法值训练太慢backendnumba或jax大模型编译提速不改任何模型代码六、再进一步贝叶斯权重本例权重本来就是带先验的随机变量ADVI 直接给出每个权重的后验用不同权重样本重构的离散程度就能量化平均脸预测的不确定性。半监督给 z 加有监督约束如数字分类头标签只观测一部分数据共享同一套权重先验未标注数据只约束似然比全标注学得更省。流模型PyMC 标准 VI 的高斯族表达能力有上限可换methodsvgd用粒子近似后验或引入外部 normalizing flow 构造更自由的 q代价是工程量更大。七、小结与下一步变分推断的本质是拿近似误差换速度pm.fit优化 ELBOVAE 三个角色在 PyMC 里各一行。判断比训练更重要ELBO 走平、重构可辨认、隐空间插值连续三条合格线都过了才算练好。下期方向把平均脸 VAE 升级成逐图像的摊销式编码器-解码器并延伸到高斯过程的生成建模。延伸阅读docs/source/api/vi.rstpm.fit、ADVI、FullRank 的 API 参考、源码目录 pymc/variational/。【免费下载链接】pymcBayesian Modeling and Probabilistic Programming in Python项目地址: https://gitcode.com/GitHub_Trending/py/pymc创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表