ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

DDPM扩散模型代码实战:前向加噪造数据、U-Net噪声预测与反向生成手写数字

DDPM扩散模型代码实战:前向加噪造数据、U-Net噪声预测与反向生成手写数字 目录一、任务设定为什么只生成数字 8二、前向过程200 步把一张图毁掉三、制造训练样本本集的核心四、两个关键认知五、U-Net扩散模型的大脑U-Net 不是必选项只是经典实现核心设计时间信号怎么进网络六、训练与反向生成七、路线选择什么时候从零写什么时候用现成库八、常见问题 FAQ结语摘要本文以「只生成数字 8」的极简设定完整走通 DDPM 扩散模型的最小闭环前向过程用 200 步把清晰图像逐步加噪成纯噪声制造训练样本时随机采样噪声与时间步、按闭式公式一步到位构造带噪图U-Net 作为噪声预测网络通过「CNN 时间图」注入步数信息训练目标是预测噪声与真实噪声的 MSE反向生成时从纯噪声出发按 DDPM 反推公式逐步去噪最终还原出手写风格的数字 8。全文覆盖任务设定、前向加噪、样本构造、U-Net 结构、训练与反向采样、路线选择及 12 个常见问题帮助读者从零理解扩散模型的完整链路。DDPM扩散模型代码实战前向加噪造数据、U-Net噪声预测与反向生成手写数字一句话概括扩散模型代码实战第一课只做一件事——不用任何条件引导让模型从纯噪声里无中生有画出 MNIST 风格的手写数字 8整条链路就三步前向加噪造训练样本、U-Net 学预测噪声、反向采样逐步去噪生成。DDPMDenoising Diffusion Probabilistic Model去噪扩散概率模型由两个过程构成前向过程对清晰图像逐步加入高斯噪声T200 步后图像退化为纯噪声反向过程训练一个 U-Net输入带噪图 x_t 和时间步 t预测当初加入的噪声 ε训练目标是预测噪声与真实噪声的 MSE。推理时从一张纯随机噪声出发反复预测噪声→按公式去噪200 步后还原出清晰图像。本文以只生成数字 8的极简设定走通完整闭环。扩散模型实战图解无中生有生成手写数字 8U-Net 噪声预测网络与反向生成图解一、任务设定为什么只生成数字 8为了把问题简化到能在 CPU 上跑通本集做了三个取舍只复原数字 8其他数字全部跳过、28×28 灰度图像素 0–255 归一化到 0–1、无条件生成不喂类别标签模型自己学会数字 8 长什么样。任务虽简单但前向加噪、样本构造、网络结构、反向采样四个环节一个不少——这是理解扩散模型全貌的最小闭环。二、前向过程200 步把一张图毁掉扩散模型的起点不是生成而是破坏。从清晰图 x₀ 出发每一步按比例保留原图像素、混入新噪声。关键符号辨析新手最容易混α_t单步保留率每一步保留上一步图像的比例。本集 CONFIG 设 α 从 0.99线性衰减到 0.9——前期少加噪保结构后期猛加噪彻底侵蚀ᾱ_t代码里的 alpha_M累积保留率从 α₁ 连乘到 α_t 的结果越乘越小代表 t 步后原图整体还占多少比例。任意一步的加噪公式DDPM 闭式解不必真做 200 步迭代xtαˉt⋅x01−αˉt⋅ε,ε∼N(0,I)xt​αˉt​​⋅x0​1−αˉt​​⋅ε,ε∼N(0,I)t0 时 ᾱ≈1x_t≈原图t200 时 ᾱ≈0x_t≈纯噪声。这就是训练样本可以一步到位现场构造的原因。讲师题外话这套线性 schedule 只是论文原始做法换成更好的加权 schedule如余弦 schedule并调优本身就是论文级创新点——这是新手切入扩散模型研究的现实缝隙。三、制造训练样本本集的核心数据流程取 Keras 自带 MNIST归一化到 0–1只保留标签为 8 的图每张图扩增 100 个训练样本全套数据约 6.4 GB每个样本独立从标准正态随机采噪声ε从 1–200 均匀随机采时刻t按公式加权求和得带噪图x_t训练输入 (x_t, t)一对目标 那个随机采出来的 ε损失 预测噪声与真实噪声的MSEL∥ε−ε^θ(xt,t)∥2L∥ε−ε^θ​(xt​,t)∥2。反直觉点就在这里模型要预测的目标是一个人工随机采出来的变量。但这恰恰是训练能收敛的原因——每张真实图都对应无数个它加了噪长什么样的样本数据被凭空放大上百倍。最终输出由电脑「手写」 的数字八四、两个关键认知认知一学的是还原当初加进去的噪声而噪声本身是随机的。扩散模型不直接学数字 8 长什么样它学的是任何时刻 x_t 里哪部分是噪声、该怎么扣掉。认知二模型干的其实是信息分离。x_t 里混着图像信号和噪声两份信息模型本质是把它们拆开——就像把两人合唱的录音分离成两条独立音轨。这也解释了为什么输出必须和输入同尺寸只有同尺寸才能逐元素减除噪声。五、U-Net扩散模型的大脑U-Net 不是必选项只是经典实现论文里只有数学公式占位符没规定网络结构。U-Net 最早为图像分割设计先卷积池化越压越小提语义再反卷积越放越大恢复分辨率天然满足输入加噪图、输出同尺寸噪声图。它的**跳跃连接skip connection**把编码器同层特征直接加到解码器对应层让去噪复用细节。想换结构完全可以。核心设计时间信号怎么进网络模型要从 x_t 恢复 x_{t-1}就必须知道现在是第几步 t。本集做法把时间 t 做成 embedding再变换成一张28×28 的时间图与加噪图逐像素相加——图像同时获得内容时间双重信息之后每卷积池化一次如缩到 14×14、32 通道时间图同步池化保持尺寸一致继续逐像素相加铁律逐像素相加的前提是尺寸和通道数对齐。一句话这个模型就是CNN 时间。六、训练与反向生成训练输入 (x_t, t)输出预测噪声 ε̂MSE 反向传播。GPU 约 1 小时训完纯 CPU 约五六个小时。生成把过程倒着放随机采一张纯噪声当作 x₂₀₀从 t200 走到 t1每步把 x_t 和 t 喂给 U-Net 得 ε̂按标准 DDPM 反推公式得到 x_{t-1}xt−11αt(xt−1−αt1−αˉtε^θ(xt,t))σtz,z∼N(0,I)xt−1​αt​​1​(xt​−1−αˉt​​1−αt​​ε^θ​(xt​,t))σt​z,z∼N(0,I)最后一步 t1→0 不加随机噪声 zσ_t 为由 schedule 决定的固定方差项。200 步走完雪花屏里逐渐浮现出手写风格的数字 8。整条链路落到代码上就三段造训练数据 → 搭 U-Net → 反向采样生成核心代码几十行。论文数学符号唬人实现本身不难。七、路线选择什么时候从零写什么时候用现成库场景建议学习原理、课程作业、复现最小闭环从零手写只生成8、T200、CPU可训要生成全部 10 类数字、清晰效果扩大数据集 加深加宽 U-Net 更多 epoch生产级海报级图像直接用Hugging Face diffusers加载预训练模型不要从零训想做研究发论文从换加噪 schedulelinear→cosine切入公认易出成果八、常见问题 FAQQ1为什么预测噪声而不是直接预测清晰图数学上可证明高斯加噪设定下预测该减去多少噪声比直接回归 x₀ 更容易学且每步都能用同一网络、同一 MSE 训练预测噪声是 DDPM 的核心训练目标。Q2α_t 和 ᾱ_t 有什么区别α_t 是单步保留率本集 0.99→0.9 线性衰减ᾱ_t 是 α₁ 到 α_t 的连乘累积保留率越乘越小。加噪公式里用的是 ᾱ_t——代码里最常见的下标写错点。Q3时间 t 为什么必须输入不传会怎样不同噪声浓度需要不同去噪量模型不知道步数就无法判断该去多少噪训练无法收敛。本集做法是把 t 变成 28×28 时间图逐像素相加。Q4U-Net 是必备结构吗不是。任何输入输出同尺寸、能逐像素预测的网络都可以U-Net 因先压缩再放大的结构和跳跃连接成为最常用实现。Q5为什么每张图扩增 100 个样本t 和 ε 都是随机采样的同一原图加不同噪声、在不同步数上构成无穷多样本扩增 100 倍让模型见到同一内容在各种噪声浓度下的样子。Q6反向生成公式是什么x_{t-1} (1/√α_t)(x_t − (1−α_t)/√(1−ᾱ_t)·ε̂) σ_t·z每步用 U-Net 预测噪声并扣掉除最后一步外加回小随机噪声 z 维持多样性。Q7为什么从纯噪声开始训练时见过最大 t 处 x_t≈纯噪声从 N(0,I) 采样正好落在训练分布边界上反向走一遍就是完整去噪路径。Q8没有 GPU 能跑吗能。本设定纯 CPU 约 5–6 小时生产级大模型才必须 GPU。Q9生成的数字模糊不像通常什么原因训练轮数不够、schedule 不合理、U-Net 容量太小或时间信号没正确注入先看训练损失曲线和中间去噪过程可视化定位。Q10扩散模型和 GAN 有什么区别GAN 一次出图、靠判别器博弈训练不稳定易模式崩塌扩散模型多步去噪、训练稳定、样本覆盖全代价是推理慢200 步串行。Q11为什么只生成数字 8教学简化单类别能把整条链路跑通而不必先解决多类别条件控制这个更复杂的问题。Q12换加噪 schedule 为什么能发论文加噪节奏决定训练信号分布和采样效率线性 schedule 只是众多方案之一更优 schedule 能在更少步数下得到更好效果是扩散研究的经典切入点。九、常见问题排查指南前面 FAQ 回答了原理层面的疑问这一节聚焦实战中最容易卡住的三类问题训练不收敛、生成图像模糊、显存不足。下面按「现象 → 原因 → 解决步骤」给出可操作的排查路径。问题一训练不收敛损失不下降或震荡典型现象训练多轮后 MSE 损失曲线几乎水平或上下剧烈震荡不下降反向生成时输出仍是纯噪声或大片灰块。可能原因与解决步骤学习率设置不当学习率过大导致震荡过小导致下降极慢。建议先用 1e-4 起步观察前 500 步损失变化再按 0.5 倍或 2 倍步长微调。时间信号未正确注入如果 t 没有变成时间图逐像素相加或尺寸通道没对齐模型无法区分噪声浓度。检查时间图是否与加噪图同尺寸、同通道数并确认相加发生在每次卷积池化之后。加噪 schedule 过激α 从 0.99 线性衰减到 0.9 是本文设定若衰减过快后期样本几乎全是噪声模型难以学习。可尝试把下限调到 0.95或改用余弦 schedule。数据归一化遗漏像素必须归一化到 0–1 再参与加噪公式若直接用 0–255 整数数值尺度不匹配会导致梯度异常。打印 x_t 的数值范围确认。损失函数写错确认是预测噪声 ε̂ 与真实噪声 ε 的 MSE而不是预测图像与真实图像的 MSE。两者训练目标不同写错会导致收敛到错误方向。问题二生成图像模糊、不像数字 8典型现象反向生成 200 步后输出能看出轮廓但边缘模糊或形状不像数字 8。可能原因与解决步骤训练轮数不足本文设定 GPU 约 1 小时、CPU 约 5–6 小时若提前中断模型还没学够。先看损失是否仍在下降是则继续训练。U-Net 容量偏小通道数太少或层数不够模型表达能力不足。可尝试把首层通道从 32 加到 64或增加一层下采样/上采样。时间信号注入不充分如果只在最外层加了一次时间图深层卷积后时间信息被稀释。确保每层池化后都同步池化时间图并逐像素相加。反向采样步数不足训练用 T200采样也应走满 200 步若只采样 50 步去噪不彻底会模糊。确认采样循环从 t200 走到 t1。最后一步处理错误t1→0 这一步不应加随机噪声 z若每步都加噪声最终图像会残留颗粒感。检查代码是否对最后一步做了特殊处理。问题三显存不足OOM典型现象训练或采样时报 CUDA out of memory或 batch size 稍大就崩溃。可能原因与解决步骤batch size 过大这是最常见原因。先把 batch size 减半如 128→64直到能跑通再逐步调大找到上限。图像尺寸或通道数过大28×28 灰度图本身很省显存若改用了更大分辨率或更多通道显存占用会平方级上升。排查阶段先保持 28×28、单通道。梯度累积导致显存峰值反向传播会缓存中间激活值。可开启梯度检查点gradient checkpointing以时间换显存或减少 U-Net 层数。采样时一次性生成太多图反向生成若一次生成多张图显存占用叠加。逐张生成或减小 batch 即可。其他进程占用显存用 nvidia-smi 查看是否有残留进程训练前清空显存必要时重启内核。通用排查顺序建议先看损失曲线判断收敛状态再可视化中间去噪过程定位模糊来源最后用 nvidia-smi 确认显存占用。三步走完绝大多数问题都能定位到具体环节。结语这两集只做了一件事把从噪声生成数字 8这条最小闭环走通——前向加噪是为了造数据U-Net 是为了学噪声反向采样是把训练好的能力倒放成生成。论文符号看着唬人落到代码上就是造数据、搭模型、生成三段。本文基于 2026 年 10 月课程内容整理超参T200、α0.99→0.9、每图扩增100份以原课程代码为准。参考延伸DDPM 原论文Denoising Diffusion Probabilistic ModelsHo et al., 2020Hugging Face Diffusers MNIST 教程浙大《计算摄影学》Lab6-UnetDDPM 讲义
返回列表