手撕Diffusion系列 - 第六期 - Unet网络

手撕Diffusion系列 - 第六期 - Unet网络

DDPM 原理图

​ DDPM包括两个过程:前向过程(forward process)反向过程(reverse process),其中前向过程又称为扩散过程(diffusion process),如下图所示。无论是前向过程还是反向过程都是一个参数化的马尔可夫链(Markov chain),其中反向过程可以用来生成图片。

在这里插入图片描述

DDPM 整体大概流程

​ 图中,由高斯随机噪声 x T x_T xT 生成原始图片 x 0 x_0 x0 为反向过程,反之为前向过程(噪音扩散)。

Unet网络结构图

  • Unet的网络架构如下图所示:

在这里插入图片描述

Unet 网络结构图
  • 通过上述的图像,我们可以发现对于Unet来说,其编码器包含5个卷积,4个最大池化层,解码器包含4个上采样,4个反卷积层。我们分别对每个卷积层池化层上采样层反卷积层进行分析。

    • Part1 卷积层:对于一个卷积层来说,我们的操作是先进行第一个二维卷积扩大卷积通道数(如下图从1通道到64通道),然后Relu激活函数,然后再第二次卷积,通道数不变。(注意1. 图像可能图像的大小也进行了变化,但是我们这里不进行变化2. 为了融入时间t元素,我们会在第一次卷积之后在图像上面添加对应的时间t的embdding编码)

    • 在这里插入图片描述

    • 卷积层的构造示例图
    • Part2 下采样层:下采样层采用的是最大池化,也就是在一个池化核大小的图像元素内,取其最大值。我们这里的下采样都是对其图像进行边长减小二分之一,比如 (512,512) -> (256,256) ,所以我们的核的大小取(2,2),步长取2,不padding。通道数不变。

    • 在这里插入图片描述

    • max下采样示例图
    • Part3 上采样层:对于上采样,我们和下采样反着来,下采样图像边长变小一半,上采样图像边长就放大一倍数。同时,由于解码器过程中,有残差操作,并且这个操作是直接对通道进行合并,因此通道数会比编码时候多一倍,为了达成平衡,解码器的上采样同时改变通道数,把通道数减小(如下图:(看这里就把通道减小了一半,从1024->512))。

    • 在这里插入图片描述

    • 上采样示例图
    • Part4 反采样层:对于反卷积层,也没啥特别的,和卷积层反着来就行,通道增加,只不过由于有残差,导致和卷积层的通道减小有延迟,不是完全对称的(如图中所示,这里左边的卷积是把64->128,而右边的反卷积层确是把256->128,所以说非完全对称)。

    • 在这里插入图片描述

    • 反卷积层示例图

Uet 网络代码

Part1 首先在conv_block.py设置一个卷积的类(用于正反卷积)

第一部分:引入相关库函数

# 该模块主要是为了实现Unet里面的横向卷积过程,每个上下采样后,都需要进行两次卷积,主要是改变图像通道数,和容易batch_t_emding信息

'''
# Part1 引入相关的库函数
'''
import torch
from dataset import *
from torch import nn

第二部分:设置卷积类

'''
# Part2 将卷积设置为一个类函数 
'''


class Conv_Block(nn.Module):
    def __init__(self, in_channel, out_channel, time_emding_size):
        super().__init__(
### 扩散模型中的UNet架构 在扩散模型中,UNet架构扮演着至关重要的角色。作为一种编码器-解码器结构,UNet能够有效地捕捉图像的空间特征并进行逐步细化处理[^1]。 #### 编码部分(Encoder) 编码部分由多个卷积层组成,每一层负责提取输入数据的不同层次特征表示。随着网络深度增加,感受野逐渐扩大,使得深层可以获取全局上下文信息。为了减少参数量以及防止过拟合,在每次下采样操作之后通常会应用批量归一化(batch normalization) 和激活函数(ReLU)。 ```python import torch.nn as nn class EncoderBlock(nn.Module): def __init__(self, in_channels, out_channels): super().__init__() self.conv = nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=2, padding=1) self.bn = nn.BatchNorm2d(out_channels) self.relu = nn.ReLU() def forward(self, x): return self.relu(self.bn(self.conv(x))) ``` #### 解码部分(Decoder) 解码过程则是通过一系列反向的上采样操作来恢复原始分辨率。每一步都会融合来自相应编码阶段的信息,这有助于保留更多细节并且提高重建质量。跳跃连接(skip connection) 是实现这一目标的关键机制之一,它允许低级特征直接传递给高级特征图谱。 ```python class DecoderBlock(nn.Module): def __init__(self, in_channels, skip_channels, out_channels): super().__init__() self.upconv = nn.ConvTranspose2d(in_channels, out_channels, kernel_size=4, stride=2, padding=1) self.conv = nn.Conv2d(out_channels + skip_channels, out_channels, kernel_size=3, padding=1) self.bn = nn.BatchNorm2d(out_channels) self.relu = nn.ReLU() def forward(self, x, concat_with): x = self.upconv(x) x = torch.cat([x, concat_with], dim=1) return self.relu(self.bn(self.conv(x))) ``` #### 中间瓶颈层(Bottleneck Layer) 位于整个网络最底部的是中间瓶颈层,这里集中了最高级别的抽象特征表达。该层不仅起到了压缩维度的作用,还为后续解码提供了强有力的支持。一般情况下,此位置也会加入注意力机制或其他增强模块以提升表现力。 ```python class BottleneckLayer(nn.Module): def __init__(self, channels): super().__init__() self.residual_block = ResidualBlock(channels) def forward(self, x): return self.residual_block(x) ``` 整体来看,UNet 架构凭借其独特的设计思路,在保持良好泛化能力的同时实现了高效的特征映射转换,成为众多计算机视觉任务的理想选择,尤其是在生成对抗网络(GANs)和扩散模型等领域展现出了卓越的效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值