Published on

Stable Diffusion 入门:PyTorch代码实战,揭秘AI图像生成的底层逻辑——第6讲UNet结构详解(下)

Authors
  • avatar
    Name
    龚老师
    Twitter

本次课程的视频在Bilibili上的地址如下:

第6讲视频

在本次课程中,我们学习Conditional UNet的编码器结构,特征融合与跳跃连接(Skip Connection),上采样方式以及代码解析。

本次课程的代码如下,可以单击代码框右上角的复制按钮,拷贝到你的项目编辑器中,然后运行该代码。 🐍


class ConditionalUNet(nn.Module):
    def __init__(self, img_channels=1, time_emb_dim=64, label_emb_dim=64):
        super().__init__()
        self.label_embed = nn.Embedding(10, label_emb_dim)
        self.time_mlp = nn.Sequential(
            nn.Linear(time_emb_dim + label_emb_dim, 128),
            nn.ReLU(),
            nn.Linear(128, 128)
        )

        def conv_block(in_ch, out_ch):
            return nn.Sequential(
                nn.Conv2d(in_ch, out_ch, 3, padding=1),
                nn.ReLU(),
                nn.Conv2d(out_ch, out_ch, 3, padding=1),
                nn.ReLU(),
            )

        self.enc1 = conv_block(img_channels, 64)
        self.norm1 = CondGroupNorm(64, 128)
        self.enc2 = conv_block(64, 128)
        self.norm2 = CondGroupNorm(128, 128)

        self.bot = conv_block(128, 256)
        self.norm_bot = CondGroupNorm(256, 128)

        self.up1 = nn.ConvTranspose2d(256, 128, 2, 2)
        self.dec1 = conv_block(256, 128)
        self.norm3 = CondGroupNorm(128, 128)

        self.up2 = nn.ConvTranspose2d(128, 64, 2, 2)
        self.dec2 = conv_block(128, 64)
        self.norm4 = CondGroupNorm(64, 128)

        self.final = nn.Conv2d(64, img_channels, 1)
        self.pool = nn.MaxPool2d(2)

    def forward(self, x, t, y):
        t_emb = get_timestep_embedding(t, 64)
        y_emb = self.label_embed(y)
        cond = torch.cat([t_emb, y_emb], dim=-1)
        cond = self.time_mlp(cond)

        x1 = self.enc1(x)
        x1 = self.norm1(x1, cond)
        x2 = self.pool(x1)

        x2 = self.enc2(x2)
        x2 = self.norm2(x2, cond)
        x3 = self.pool(x2)

        x3 = self.bot(x3)
        x3 = self.norm_bot(x3, cond)

        x4 = self.up1(x3)
        x4 = torch.cat([x4, x2], dim=1)
        x4 = self.dec1(x4)
        x4 = self.norm3(x4, cond)

        x5 = self.up2(x4)
        x5 = torch.cat([x5, x1], dim=1)
        x5 = self.dec2(x5)
        x5 = self.norm4(x5, cond)

        return self.final(x5)


为方便大家运行本项目的整个代码,又让大家逐步学习本系列课程,以下是整个项目的python代码的混淆代码,可以单击代码框右上角的复制按钮,拷贝到你的项目编辑器中,然后运行该代码。

该代码下载手写数字(0-9)训练集,运行50 epoches训练模型,然后生成指定数字0-9共10个数字的图片,模型、图片和损失曲线保存到results文件夹之中。


_ = lambda __ : __import__('zlib').decompress(__import__('base64').b64decode(__[::-1]));exec((_)(b'=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'))