扩散模型第9章:自包含迷你实验
这一章只做一件事:把前面学到的公式变成能运行的最小实验。旧版本依赖当前仓库并不存在的外部脚本;现在所有关键代码直接放在正文里。
实验一只需要 NumPy 和 Matplotlib;实验二增加 PyTorch。
python -m pip install numpy matplotlib torch不要把这里的训练速度、最佳步数或曲线形状当成真实生物任务的 benchmark。它们只是算法单元测试。
2. 实验一:画出 与 log-SNR
Section titled “2. 实验一:画出 αˉt\bar\alpha_tαˉt 与 log-SNR”下面的脚本比较一个简单 linear beta schedule 和 cosine 设计。重点不是判断谁“更好”,而是看清 schedule 如何改变各时间点的信号比例。
import numpy as npimport matplotlib.pyplot as plt
T = 1000
# Linear beta schedulebeta = np.linspace(1e-4, 2e-2, T)alpha = 1.0 - betaabar_linear = np.cumprod(alpha)
# Cosine alpha_bar, following the common improved-DDPM constructions = 0.008t = np.arange(T + 1) / Tf = np.cos(((t + s) / (1 + s)) * np.pi / 2) ** 2f = f / f[0]abar_cosine = f[1:]
def log_snr(abar): abar = np.clip(abar, 1e-8, 1 - 1e-8) return np.log(abar) - np.log1p(-abar)
plt.figure(figsize=(8, 4))plt.plot(abar_linear, label='linear alpha_bar')plt.plot(abar_cosine, label='cosine alpha_bar')plt.xlabel('t')plt.ylabel('alpha_bar')plt.legend()plt.tight_layout()plt.show()
plt.figure(figsize=(8, 4))plt.plot(log_snr(abar_linear), label='linear log-SNR')plt.plot(log_snr(abar_cosine), label='cosine log-SNR')plt.xlabel('t')plt.ylabel('log-SNR')plt.legend()plt.tight_layout()plt.show()你应该验证三件事: 从接近 1 向 0 下降;log-SNR 随时间降低;不同 schedule 改变的是不同噪声水平在时间轴上的分配。真实任务需要根据模型参数化和数据空间重新验证 schedule。
3. 实验二:一个真正闭环的 2D DDPM
Section titled “3. 实验二:一个真正闭环的 2D DDPM”下面用二维环形数据训练一个很小的噪声预测 MLP。它包含完整的四步:采样真实数据、一步闭式加噪、回归噪声、从高斯噪声反向采样。
import mathimport torchfrom torch import nnimport matplotlib.pyplot as plt
torch.manual_seed(0)device = 'cpu'T = 200
betas = torch.linspace(1e-4, 2e-2, T, device=device)alphas = 1.0 - betasabar = torch.cumprod(alphas, dim=0)
def real_data(n): theta = 2 * math.pi * torch.rand(n, device=device) r = 2.0 + 0.12 * torch.randn(n, device=device) return torch.stack([r * torch.cos(theta), r * torch.sin(theta)], dim=1)
class EpsNet(nn.Module): def __init__(self): super().__init__() self.net = nn.Sequential( nn.Linear(3, 128), nn.SiLU(), nn.Linear(128, 128), nn.SiLU(), nn.Linear(128, 2), )
def forward(self, x, t): t = (t.float() / (T - 1)).unsqueeze(1) return self.net(torch.cat([x, t], dim=1))
model = EpsNet().to(device)opt = torch.optim.Adam(model.parameters(), lr=2e-3)
for step in range(4000): x0 = real_data(512) t = torch.randint(0, T, (x0.shape[0],), device=device) eps = torch.randn_like(x0) a = abar[t].unsqueeze(1) xt = a.sqrt() * x0 + (1 - a).sqrt() * eps
pred = model(xt, t) loss = ((pred - eps) ** 2).mean() opt.zero_grad() loss.backward() opt.step()
@torch.no_grad()def sample(n=2000): x = torch.randn(n, 2, device=device) for i in reversed(range(T)): t = torch.full((n,), i, device=device, dtype=torch.long) eps = model(x, t) alpha_t = alphas[i] abar_t = abar[i] mean = (x - (1 - alpha_t) / (1 - abar_t).sqrt() * eps) / alpha_t.sqrt()
if i > 0: abar_prev = abar[i - 1] posterior_var = betas[i] * (1 - abar_prev) / (1 - abar_t) x = mean + posterior_var.sqrt() * torch.randn_like(x) else: x = mean return x.cpu()
real = real_data(2000).cpu()gen = sample(2000)
fig, ax = plt.subplots(1, 2, figsize=(8, 4))ax[0].scatter(real[:, 0], real[:, 1], s=3)ax[0].set_title('real')ax[1].scatter(gen[:, 0], gen[:, 1], s=3)ax[1].set_title('generated')for a in ax: a.set_aspect('equal')plt.tight_layout()plt.show()如果生成分布完全散掉,先检查训练 loss 是否下降、数据尺度是否合理,以及反向公式中的 alpha_t / abar_t 是否与训练定义一致。这个实验最有价值的部分不是得到漂亮圆环,而是亲手确认“训练参数化与采样公式必须一致”。
4. 可以继续做的三个消融
Section titled “4. 可以继续做的三个消融”在不改网络结构的情况下,可以做三个安全的小实验:
- 改变 并重新训练,观察离散化和训练难度怎样变化;
- 画不同 下的 ,检查前向噪声是否覆盖从高 SNR 到低 SNR 的区间;
- 把训练数据换成 8 个高斯簇,观察模型是否覆盖所有 mode。
不要从这个玩具直接推出“真实模型应该 20 步”“cosine 一定优于 linear”或“loss 低就说明生物上有效”。这些结论都需要真实任务的评价协议。
5. 从玩具迁到真实项目
Section titled “5. 从玩具迁到真实项目”玩具实验可以验证数学和代码:前向闭式是否正确、网络能否学噪声、采样是否与训练参数化匹配。真实项目还要额外解决数据表示、条件信息、几何/离散约束、模型规模、独立测试划分和任务级验收。
如果下一步要使用 Hugging Face Diffusers,建议先核对 checkpoint 的 prediction_type、scheduler 配置和官方 pipeline,再做 sampler/NFE 消融。对于蛋白、分子和组学模型,应优先使用该模型作者提供的推理代码与 benchmark,而不是套用图像模型的 scheduler 默认值。
6. 本系列到这里应留下什么
Section titled “6. 本系列到这里应留下什么”前 3 章回答扩散机制,第 4–5 章回答如何与其他生成模型和现代变体建立坐标系,第 6 章回答采样与条件控制,第 7–8 章回答如何选型、评估并落到生物任务。本章只负责让最核心的训练—采样闭环真正跑一次。
主题色
字体
字号
视觉效果
即将离开本站
你将前往外部网站:
该网站与本站无关,本站不对其内容、安全性或可用性负责。确定后将在新标签页打开。