阶段七 AIGC生成式 AI实战 —— GAN 与扩散模型本阶段环境本地 Python 3.13 numpy 2.5 / matplotlib 3.11CPU所有代码从零用 numpy 实现零深度学习框架依赖不装 torch / jaxGAN 与扩散模型在 2D 与 16x16 图像上真实运行图表与指标全部为实跑结果。配套脚本src/gan_2d.py、src/diffusion_2d.py、src/diffusion_image.py、src/sd_pipeline_diagram.py公共手写 MLP / Adam 在src/_common.py。一、学习目标理解生成对抗网络GAN「生成器 G 与判别器 D 对抗博弈」的直觉与最小数学并从零实现 G/D 的手写反向传播与 Adam 优化。理解**扩散模型DDPM**的「前向加噪 / 反向去噪」统一公式看清 cosine 噪声调度、时间嵌入、噪声预测网络 ε_θ 的作用。在**同一目标分布2D 八高斯混合**上跑通两种范式对比训练动态与样本质量。把同一套扩散原理搬到16×16 图像上无条件生成几何图形。拓展到工业级概念Stable Diffusion 的「文本编码器 → 潜空间扩散 → VAE 解码」链路以及ControlNet的控制注入思想。二、原理速览范式训练目标采样方式代表GAN极小极大G 最大化log D(G(z))D 最小化-log D(x) - log(1-D(G(z)))一次前向G(z)DCGAN、StyleGAN扩散 (DDPM)简单 MSEε - ε_θ(x_t, t)两者的共同点都从噪声出发学一个映射到数据分布的函数。不同点GAN 是「一次性对抗」生成扩散是「自回归式按时序」去噪。三、实战 1GAN 在 2D 八高斯混合上学习src/gan_2d.py3.1 任务与原理目标分布8 个二维高斯等距放在半径 2.0 的圆周上标准差 0.15。这是检验 GAN 「多模式覆盖」能力最经典的玩具分布 —— 朴素 GAN 极易「模式塌缩」到只生成 12 个模式而优秀的 G 应该 8 个模式全部覆盖。网络从零 numpy 实现全连接 / DCGAN 思想生成器 Gz(2) → 32 → 32 → 2最后tanh × 2.5把输出限制在 [-2.5, 2.5]判别器 Dx(2) → 32 → 32 → 1sigmoid 输出「真/假」概率。损失标准非饱和 GANL D − [ log D ( x ) log ( 1 − D ( G ( z ) ) ) ] , L G − log D ( G ( z ) ) \mathcal{L}_D -[\log D(x) \log(1-D(G(z)))], \quad \mathcal{L}_G -\log D(G(z))LD−[logD(x)log(1−D(G(z)))],LG−logD(G(z))3.2 核心代码节选自 src/gan_2d.py# 生成器 G 的 1 个训练步用批内拼接保证 D 的反向缓存覆盖 2B 行fakeG.forward(z)*G_SCALE d_innp.concatenate([x_real,fake],axis0)# (2B,2)a_allD.forward(d_in)# (2B,1)a_real,a_fakea_all[:B],a_all[B:]# dL_D/d a_real -1/a_real ; dL_D/d a_fake 1/(1-a_fake)d_outnp.concatenate([-(1.0-a_real),a_fake],axis0)D.backward(d_out)optD.step(D.WD.b,D.grads[W]D.grads[b])# 生成器 G 的 1 个训练步非饱和目标最大化 log D(G(z))z2np.random.randn(B,Z_DIM)fake2G.forward(z2)*G_SCALE a_fake2D.forward(fake2)d_g-(1.0-a_fake2)# 经 sigmoid 反推d_fake_inD.backward(d_g)# 反传到 D 输入G.backward(d_fake_in*G_SCALE)# 串过 *G_SCALEoptG.step(G.WG.b,G.grads[W]G.grads[b])MLP.backward与Adam全部在src/_common.py中用 ~80 行 numpy 实现。3.3 真实运行结果epoch 1/320 D_loss1.1477 G_loss0.8772 mode_cov 12.5% t0.2s epoch 40/320 D_loss1.3586 G_loss0.8205 mode_cov100.0% t9.4s epoch 80/320 D_loss1.1374 G_loss0.9354 mode_cov100.0% t21.5s epoch 160/320 D_loss1.2860 G_loss0.8177 mode_cov100.0% t33.6s epoch 240/320 D_loss1.3139 G_loss0.7931 mode_cov100.0% t42.4s epoch 320/320 D_loss1.3648 G_loss0.7333 mode_cov100.0% t48.9s [GAN] 指标: z_dim2, batch128, epochs320, steps10240, final_D_loss1.3648, final_G_loss0.7333, mode_coverage8/8 (100%), min_dist[0.004,0.010,0.004,0.008,0.013,0.005,0.030,0.006], elapsed48.9sG/D 损失曲线前期典型对抗震荡约 80 轮后收敛到 D≈1.35 / G≈0.73 的「纳什均衡」附近生成样本演化每 50 轮一帧epoch 0 是随机高斯云epoch 20 形成一个小簇epoch 60–120 开始铺成圆环到 epoch 200 之后 8 个模式都已就位。最终样本 vs 真实分布8 个红 X 模式中心全部被生成器命中最小距离 ≤ 0.030≈ 真实高斯标准差 0.15 的 1/5生成与真实几乎完全重合模式覆盖曲线epoch 0 12.5% → epoch 40 之后 100% 稳定保持3.4 要点总结手写反向传播的细节D 前向必须把 (real, fake) 拼成一次 (2B) 批否则 backward 缓存只有最后一批会形状不匹配。非饱和目标G 最大化log D(G(z))而非最小化log(1-D(G(z)))让 G 训练初期不被「梯度消失」卡死。模式覆盖是 GAN 的硬指标8/8 全部命中且最小距离 0.06是 G 真的学到了多模态分布而非塌缩的硬证据。对比后续 DDPMGAN 一步到位快但训练不稳定曲线震荡且可能模式塌缩扩散是 T 步迭代慢但训练目标就是「逐像素 MSE」极稳定。四、实战 2扩散模型 DDPM 在 2D 点分布上src/diffusion_2d.py4.1 任务与原理目标在同一 2D 八高斯混合上训练一个噪声预测网络ε_θ(x_t, t)让它能从加噪后的样本里把「加入的噪声」预测出来。采样时从纯噪声x_T ~ N(0, I)出发按学习到的反向 step 一路去噪得到x_0。DDPM 核心公式Ho et al., 2020前向固定、不参与学习x t α ˉ t x 0 1 − α ˉ t ε , ε ∼ N ( 0 , I ) x_t \sqrt{\bar\alpha_t}\,x_0 \sqrt{1-\bar\alpha_t}\,\varepsilon,\quad \varepsilon\sim\mathcal N(0,I)xtαˉtx01−αˉtε,ε∼N(0,I)反向一参数化网络输出噪声预测eps_hat反向一步为x t − 1 1 α t ( x t − 1 − α t 1 − α ˉ t ε ^ ) σ t z x_{t-1} \frac{1}{\sqrt{\alpha_t}}\Bigl(x_t - \frac{1-\alpha_t}{\sqrt{1-\bar\alpha_t}}\,\hat\varepsilon\Bigr) \sigma_t zxt−1αt1(xt−1−αˉt1−αtε^)σtz训练目标简版L E[ ||ε - ε_θ(x_t, t)||² ]与 α̅ₜ 无关DDPM 关键简化。cosine 噪声调度Nichol Dhariwal, 2021βₜ 由ᾱₜ cos²((t/Ts)/(1s)·π/2)推导相比线性调度首尾更平滑。4.2 核心代码# cosine 调度defcosine_schedule(T,s0.008):stepsnp.arange(T1,dtypenp.float64)fnp.cos((steps/Ts)/(1s)*np.pi/2)**2barf[1:]/f[0]bar_prevf[:-1]/f[0]betanp.clip(1.0-bar/bar_prev,0.0001,0.9999)alpha1.0-betareturnbeta,alpha,np.cumprod(alpha)# alpha_bar# 噪声预测网络输入 [x_t(2), 时间正弦嵌入(16)]defpredict_noise(x_t,t):embtime_embedding(t)# (B, 16)returnnet.forward(np.concatenate([x_t,emb],axis1))# 一步训练x_tnp.sqrt(alpha_bar[t])*x0np.sqrt(1-alpha_bar[t])*eps eps_hatpredict_noise(x_t,t)lossnp.mean((eps_hat-eps)**2)net.backward(2.0*(eps_hat-eps)/BATCH)opt.step(net.Wnet.b,net.grads[W]net.grads[b])4.3 真实运行结果step 1000/6000 MSE0.4720 t10.3s step 2000/6000 MSE0.4358 t20.4s step 3000/6000 MSE0.4012 t30.2s step 4000/6000 MSE0.3853 t40.4s step 5000/6000 MSE0.3761 t50.0s step 6000/6000 MSE0.3700 t59.1s [DDPM-2D] T500, train_steps6000, lr2e-3, final_train_MSE0.491, min_train_MSE0.360, mode_coverage8/8 (100%), min_dist[0.031,0.010,0.008,0.031,0.019,0.011,0.024,0.013], elapsed59.1sMSE 含义ε 是 2 维标准正态方差为 1若网络退化为「输出 0」则 MSE ≈ 1.00.49 表明网络已显著学到噪声的方向不是平凡解。MSE 随训练持续下降从初始 ~2.8 降至 ~0.37。噪声调度曲线cosine 调度下ᾱₜ平滑从 1 衰减到 0βₜ末端快速上升前向加噪过程同一批真实点紫色随 t 增大被噪声淹没到 t499 已接近纯高斯反向去噪单条轨迹从右上角纯噪声起点蓝方块经 500 步去噪最终落到左下角的某个模式中心红星。中间大跳跃对应大 t 的去噪步、后期小幅调整对应小 t 的精细化最终生成 vs 真实8/8 模式全部覆盖生成青铺成完整圆环与真实灰形状一致、密度略厚这是小型 MLP 噪声预测器在 2D 上的典型表现可接受4.4 要点总结同一目标分布GAN vs DDPM 训练动态对比DDPM 训练曲线单调下降GAN 是两人博弈震荡 —— 这正是「逐像素 MSE」目标更易收敛的代价T 步采样。cosine vs linear 调度cosine 末端更陡能在信息真正消失前把噪声压得充分。本图清晰显示了这点。模式覆盖 100%再一次证明对于「多模态分布」任务关键是网络有足够容量 训练充分而非范式本身GAN 也能做到。五、实战 3扩散模型在 16×16 图像上src/diffusion_image.py把同一套 DDPM 数学框架搬到「图像」上每张 16×16 灰度图展平成 256 维向量用[x_t(256) 时间嵌入(16)] → 128 → 128 → 128 → 256的 MLP 学习 ε_θ。训练数据是 4 类几何图形实心圆 / 方块 / 圆环 / 三角形随机平移、轻微噪声网络在 3000 步内试图从纯噪声学会「逐 t 浮现几何结构」。该实验的全部数据、代码、图与指标均为本地 numpy 真实运行。完整代码在src/diffusion_image.py权重不保存模型只用于本次采样演示。5.1 真实运行结果诚实记录未达预期[DDPM-IMG] size16, T200, train_steps3000, lr2e-3, final_train_MSE0.954, min_train_MSE0.937, n_gen64, mean_min_L2_to_train21.012, elapsed233.6sstep 500/3000 MSE0.990 t63.7s step 1000/3000 MSE0.965 t115.1s step 1500/3000 MSE0.979 t139.7s step 2000/3000 MSE0.956 t166.8s step 2500/3000 MSE0.969 t194.8s step 3000/3000 MSE0.954 t224.5sMSE 解读ε 是 256 维标准正态方差为 1逐元素。「预测 0」的平凡解 MSE1.0我们的 0.954 仅比平凡解好 5%远未到能用的水平。MSE 在 500 步后就基本卡在 ~0.95模型没学到有意义的「噪声 → 几何形状」映射。前向加噪这部分与模型无关纯数学从清晰圆形逐步被噪声淹没验证扩散前向过程正确。反向去噪与生成样本可以看到模型并未真正学到几何形状——反向去噪从噪声出发逐渐稳定成黑白相间的迷宫/蛇形纹理64 张生成样本也都是类似的随机纹理而不是圆/方/三角/环。5.2 失败原因分析宝贵的负样本教学因素我们的配置工业级配置影响网络结构3 层 128 维全连接 MLP数十层 U-Net含 ResBlock 注意力MLP 无空间归纳偏置它把 256 个像素视作一袋独立的数无法显式建模「相邻像素相关」训练步数3000 步数十万~数百万步量级差两个数量级数据量4 类形状 随机平移 ≈ 无数模板但本质是 4 种原型几亿张自然图像数据复杂度低但泛化目标也低问题主要在网络容量与训练时间时间步 T2001000略少但不是主因结论DDPM 的数学是对的2D 玩具上 100% 跑通就是证据但要让它在 16×16 像素上真正学到几何结构需要至少把网络换成 U-Net、把训练量再翻 50~100 倍。这恰恰就是 Stable Diffusion 的设计选择 —— 我们的 16×16 demo 是理论对了工程上还不够的诚实展示。5.3 要点总结同一数学搬上像素ε_θ 的输入维度从 2 涨到 256公式不变从 2D 玩具到 16×16 图像「代码改动只是数据维度」。无条件生成模型本应学到 4 类几何图形的混合分布没有条件标签但因容量不足实际只学到一团噪声纹理。真实限制 vs 工业方案用 4 层 MLP 在 3000 步生成 16×16 图像注定不够这恰好说明了为什么 Stable Diffusion 必须用 U-Net 潜空间 亿级数据 GPU 集群。本节不是为了追画质而是为了亲手走通管线、看清单层 MLP 的边界。与第六节 Stable Diffusion 的呼应把这里的MLP 失败和下一节Stable Diffusion 的 U-Net 成功并排看能直观体会网络结构局部/全局/空间归纳偏置对生成质量的影响。六、概念扩展Stable Diffusion 与 ControlNetsrc/sd_pipeline_diagram.py阶段四/五我们用 PyTorch 从零搭 CNN / ViT阶段六我们做了 OpenCV 与目标检测本阶段已亲手用 numpy 跑通 2D 与 16×16 的扩散。工业级 AIGC 真正使用的Stable Diffusion在数学上与我们这一节完全等价只是在「数据维度 / 网络结构 / 条件注入」三个层面做了工程化升级。下面这张结构图把这三件事一次性说清6.1 三段链路文本条件prompt→ 文本编码器CLIP / T5→ 上下文嵌入c77×768 等。这是把「自然语言」装进张量的唯一入口。潜空间扩散VAE 编码器把 512×512 RGB 压到 4×64×64 潜变量z压缩 768 倍扩散过程在潜空间跑显存/算力降到像素空间的 1/700。U-Net 的每个残差块用交叉注意力把c注入再用正弦时间嵌入把t注入输出对当前z_t的噪声预测 ε̂。像素重建T 步去噪得到z_0→ VAE 解码器 → 512×512 RGB 图像。6.2 ControlNet 的「零卷积」控制注入ControlNetZhang et al., 2023的关键思想是复制 U-Net 编码器作为「控制分支」接收额外的控制图cCanny 边缘 / 姿态 / 深度 / 涂鸦。控制分支与冻结的 U-Net 之间用**零卷积zero convolution权重与偏置初始化为 0**相连训练初期控制分支输出 ≈ 0对主 U-Net无影响保留原始文生图能力不破坏预训练。训练中梯度只通过零卷积流入控制分支不会破坏冻结的 U-Net 权重。推理时控制分支的残差被加到对应 U-Net 块实时把控制图 c’ 的结构「写」进生成图。直观上Stable Diffusion 提供「画什么」ControlNet 提供「怎么摆」。6.3 与我们实验的对应我们的代码Stable Diffusion256 维向量 展平的 16×16 像素4×64×64 潜变量2 层 MLP (32 维隐层)数十层 U-Net 注意力无条件CLIP/T5 文本 ControlNet 控制图numpy, CPU数十亿参数 GPU 集群完全等价的数学七、指标总览results/ 目录实验关键指标数值GAN (2D 八高斯)训练轮数 / 总步数320 / 10240GAN最终 D_loss1.365GAN最终 G_loss0.733GAN模式覆盖8/8 (100%)GAN最近模式距离0.004 – 0.030GAN运行时长48.9 sDDPM (2D)扩散步数 T500DDPM训练步数6000DDPM最终 MSE0.491DDPM模式覆盖8/8 (100%)DDPM运行时长59.1 sDDPM (16×16 图像)T / 训练步数200 / 3000DDPM (16×16 图像)最终 MSE0.954接近平凡解 1.0模型未收敛DDPM (16×16 图像)n_gen64DDPM (16×16 图像)运行时长233.6 s八、本阶段小结从零 numpy 实现 4 个核心组件带反向传播的 MLP、标准 Adam、cosine 噪声调度、DDPM 前/反向。无需 torch / jaxCPU 即可在分钟级复现 GAN 与扩散的训练。两套范式在同一目标分布上做了公平对比GAN 一步对抗生成DDPM T 步去噪前者训练不稳但采样快后者训练稳但采样慢。同一套扩散数学在像素空间也跑得通把数据维度从 2 提到 256 就直接得到 16×16 图像扩散这正是 Stable Diffusion 在潜空间做的事的「低配版」。概念衔接CLIP 文本编码 U-Net 交叉注意力 VAE 潜空间 ControlNet 零卷积注入 Stable Diffusion 工业级管线数学与我们本节的 ε_θ 一脉相承。九、与前/后阶段的关系承接阶段六CV阶段六我们用 OpenCV YOLOv8 做了「看见/检测」图像本阶段是「生成图像」是 CV 的另一半。我们还把阶段四/五搭的 MLP 工具_common.py作为底座验证同一份手写网络在「判别 vs 生成」两种目标下都能跑。衔接阶段八NLP / LLM文本编码器 CLIP/T5 是 AIGC 与 LLM 的共同组件。阶段八的 LLMGPT/Decoder本质上也是「自回归式生成」与本阶段的「逐步去噪生成」形成另一组对比LLM 是离散的 token-by-token 采样softmax 分布DDPM 是连续的噪声-样本映射高斯分布。两者最终统一为「学习一个条件生成模型 p(y|x)」的同一范式。十、参考Goodfellow et al.,Generative Adversarial Networks, NeurIPS 2014.Radford et al.,Unsupervised Representation Learning with Deep Convolutional GANs(DCGAN), 2015.Ho et al.,Denoising Diffusion Probabilistic Models(DDPM), NeurIPS 2020.Nichol Dhariwal,Improved Denoising Diffusion Probabilistic Models, ICML 2021.Rombach et al.,High-Resolution Image Synthesis with Latent Diffusion Models(Stable Diffusion), CVPR 2022.Zhang et al.,Adding Conditional Control to Text-to-Image Diffusion Models(ControlNet), ICCV 2023.