Unet网络详解

Unet

  • 参考文献:U-Net: Convolutional Networks for Biomedical
    Image Segmentation
  • 作者:Olaf Ronneberger, Philipp Fischer, and Thomas Brox

什么是Unet模型

Unet是一个优秀的语义分割模型,其主要执行过程与其它语义分割模型类似。与CNN不同的之处在于CNN是图像级的分类,而unet是像素级的分类,其输出的是每个像素点的类别。

Unet损失函数

主要部分:softmax激活函数 + 带权重的交叉熵损失函数 + 权重计算函数

softmax激活函数

softmax激活函数将每个像素点的输入特征与权重做非线性叠加。每个像素点经过softmax的处理后产生的输出值个数等于标签里的类别数。softmax将每个像素点的输出值变换成值为正且和为1的概率分布,从而得到每个像素点中每个类的置信度。

交叉熵损失函数

交叉熵损失函数:用来衡量两个概率分布差异的测量函数

在这里插入图片描述

在上式中,yc表示样本的真实分布,其值要么为0,要么为1,Pc表示样本的预测分布。

本论文使用的是带边界权重的交叉熵损失函数

p是经softmax处理后的输出值;

l :Ω → {1, . . . , K},是每个像素的真实标签;

pl(x)(x):点x在对应的label给出的那个类别的输出的激活值。

w : Ω → R 是在训练过程中添加给每个像素的权重 。

权重计算函数

w(x)这个公式主要参考正态分布的式子。
wc(x)是预先计算每个地面真值分割,用来补偿训练数据集中每个类别的像素的不同频率;
d1是距离最近细胞边界的距离
d2是距离第二近细胞边界的距离

当d1、d2都等于0时,后面部分有最大值,且d1、d2越小,后面部分越大,即整个权重越大。当d1、d2越小,意味着越靠近细胞边界,细胞边界所占的权重越大,可以迫使网络学习。

权重的作用:权重可以调整图像中某个区域的重要程度,在计算损失的过程中,给两个细胞重合的边缘部分增加了损失的权重,以此让网络更加注重这类重合的边缘信息。

总结:首先使用softmax操作得到每个类的置信度,然后使用交叉熵来衡量预测和标号之间的差距。

Unet主要结构

在这里插入图片描述

Unet可以分为三个部分,如上图所示:

第一部分是主干特征提取部分,我们可以利用主干部分获得一个又一个的特征层,Unet的主干特征提取部分与VGG相似,为卷积和最大池化的堆叠。利用主干特征提取部分我们可以获得五个初步有效特征层,在第二步中,我们会利用这五个有效特征层可以进行特征融合。

第二部分是加强特征提取部分,我们可以利用主干部分获取到的五个初步有效特征层进行上采样,并且进行特征融合,获得一个最终的,融合了所有特征的有效特征层。

第三部分是预测部分,我们会利用最终获得的最后一个有效特征层对每一个特征点进行分类,相当于对每一个像素点进行分类。

主干特征提取网络

Unet的主干特征提取部分由卷积层+最大池化层组成,整体结构与VGG类似。

在这里插入图片描述当输入的图像大小为512x512x3的时候,具体执行方式如下:
1、conv1:进行两次[3,3]的64通道的卷积,获得一个[512,512,64]的初步有效特征层,再进行2X2最大池化,获得一个[256,256,64]的特征层。
2、conv2:进行两次[3,3]的128通道的卷积,获得一个[256,256,128]的初步有效特征层,再进行2X2最大池化,获得一个[128,128,128]的特征层。
3、conv3:进行三次[3,3]的256通道的卷积,获得一个[128,128,256]的初步有效特征层,再进行2X2最大池化,获得一个[64,64,256]的特征层。
4、conv4:进行三次[3,3]的512通道的卷积,获得一个[64,64,512]的初步有效特征层,再进行2X2最大池化,获得一个[32,32,512]的特征层。
5、conv5:进行三次[3,3]的512通道的卷积,获得一个[32,32,512]的初步有效特征层。
在这里插入图片描述

 
为什么论文中说输入图片的尺寸是512x512,而论文中的模型示意图却显示输入图片的尺寸是572x572呢?
在这里插入图片描述

镜像扩充示意图

镜像扩充示意图
 
因为图像边界的图像块没有周围像素,卷积会使图像边缘处的信息丢失,因此要对周围像素采用镜像扩充。
通俗的说就是我们原本打算输入512x512尺寸的图片,但是由于图片边缘的像素点没有周围像素(即每个方向都有相邻的像素),当用模型处理这些边缘像素点时就会产生较大的误差,为了消除这种误差,在向模型中输入图片时,输入的尺寸就会比我们实际想要输入的尺寸要大一些,我们将这种处理方法称之为镜像扩充。

加强特征提取结构

利用第一步我们可以获得五个初步的有效特征层,在加强特征提取网络这里,我们会利用这五个初步的有效特征层进行特征融合特征融合的方式就是对特征层进行上采样并且进行堆叠

为了方便网络的构建与更好的通用性,我们的Unet和上图的Unet结构有些许不同,在上采样时直接进行两倍上采样再进行特征融合,最终获得的特征层和输入图片的高宽相同。

在这里插入图片描述

利用特征获得预测结果

利用特征获得预测结果的过程为:
利用一个1x1卷积核进行通道调整,将最终特征层的通道数调整成num_classes。

在这里插入图片描述

代码复现

数据集:ISBI

模型训练:

在这里插入图片描述

测试集:
在这里插入图片描述
在这里插入图片描述

  • 20
    点赞
  • 247
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
UNet是一种用于图像分割的卷积神经网络,其结构类似于自编码器。在这个网络中,输入图像被编码成一个较小的向量,然后被解码为分割图像。UNet的特点是具有对称的编解码结构,同时也具备跳跃连接,这使得网络能够更好地捕捉到不同层次的特征信息。 下面是一个基于PyTorch实现的UNet模型的代码详解: 首先,我们需要导入所需的库: ```python import torch import torch.nn as nn import torch.nn.functional as F ``` 接下来,我们定义UNet的编码器和解码器部分: ```python class EncoderBlock(nn.Module): def __init__(self, in_channels, out_channels): super(EncoderBlock, self).__init__() self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1) self.bn1 = nn.BatchNorm2d(out_channels) self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1) self.bn2 = nn.BatchNorm2d(out_channels) self.pool = nn.MaxPool2d(kernel_size=2, stride=2) def forward(self, x): x = F.relu(self.bn1(self.conv1(x))) x = F.relu(self.bn2(self.conv2(x))) out = self.pool(x) return out, x class DecoderBlock(nn.Module): def __init__(self, in_channels, out_channels): super(DecoderBlock, self).__init__() self.upconv = nn.ConvTranspose2d(in_channels, out_channels, kernel_size=2, stride=2) self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1) self.bn1 = nn.BatchNorm2d(out_channels) self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1) self.bn2 = nn.BatchNorm2d(out_channels) def forward(self, x, encoder_output): x = self.upconv(x) x = torch.cat([x, encoder_output], dim=1) x = F.relu(self.bn1(self.conv1(x))) out = F.relu(self.bn2(self.conv2(x))) return out ``` EncoderBlock和DecoderBlock都是基本的卷积块,其中EncoderBlock用于向下采样图像,DecoderBlock用于向上采样图像。在EncoderBlock中,我们使用2个卷积层和1个最大池化层来减小图像的大小。在DecoderBlock中,我们使用一个转置卷积层和2个卷积层来增加图像的大小。在解码器中,我们还使用了跳跃连接,将编码器输出的特征图与解码器的输入特征图连接起来。 接下来,我们定义完整的UNet模型: ```python class UNet(nn.Module): def __init__(self, num_classes=1): super(UNet, self).__init__() self.enc1 = EncoderBlock(3, 64) self.enc2 = EncoderBlock(64, 128) self.enc3 = EncoderBlock(128, 256) self.enc4 = EncoderBlock(256, 512) self.center = nn.Conv2d(512, 1024, kernel_size=3, padding=1) self.bn = nn.BatchNorm2d(1024) self.dec4 = DecoderBlock(1024, 512) self.dec3 = DecoderBlock(512, 256) self.dec2 = DecoderBlock(256, 128) self.dec1 = DecoderBlock(128, 64) self.final = nn.Conv2d(64, num_classes, kernel_size=1) def forward(self, x): enc1, out1 = self.enc1(x) enc2, out2 = self.enc2(enc1) enc3, out3 = self.enc3(enc2) enc4, out4 = self.enc4(enc3) center = self.center(enc4) center = self.bn(center) dec4 = self.dec4(center, out4) dec3 = self.dec3(dec4, out3) dec2 = self.dec2(dec3, out2) dec1 = self.dec1(dec2, out1) final = self.final(dec1) return final ``` 其中,我们将4个EncoderBlock和4个DecoderBlock连接起来,中间加入了一个卷积层和BatchNormalization层。 最后,我们可以使用该模型进行图像分割: ```python model = UNet(num_classes=2) inputs = torch.randn((1, 3, 256, 256)) outputs = model(inputs) print(outputs.shape) ``` 这里我们使用了一个大小为256x256的RGB图像进行测试,并输出了模型的输出形状。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

这篇博客保熟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值