写在前面
最近pua老师一直让我不停给毕设做实验,无奈去给他打工。实话来说毕设工作并不开心,其实自己是有许多想法,但是被他打击后并不想在这篇工作里继续深挖,只想着早日毕业,自己在工作之外多多读文献,练练编程~最近武大的师兄建了个pytorch学习群,让我们几个即将入学的研0同学互相学习交流,这篇博客写的目的也是记录一下论文复现过程。
正文开始
初看论文,发现是一个改良的unet网络架构,其中包括一些上采样、projection操作。

网络结构搭建
可以从图中看到主要就是一些卷积下采样和上采样的过程,尾部采用多个尺度projection融合,得到最终的预测。
下采样
class down_conv2d_bn(nn.Module):
'''
Encoder的下采样包括1个Conv 3x3, ReLU + Conv 3x3, BN, ReLU
decoder的下采样包括2个Conv 3x3, ReLU
'''
def __init__(self,in_channels,out_channels,kernel_size=3,strides=1,padding=1, with_bn = True):
super(down_conv2d_bn,self).__init__()
self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=kernel_size, stride=strides, padding=padding, bias=True)
self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size = kernel_size, stride = strides, padding=padding, bias=True)
self.with_bn = with_bn
self.bn2 = nn.BatchNorm2d(out_channels)
def forward(self,x):
out = F.relu(self.conv1(x))
if self.with_bn:
out = F.relu(self.bn2(self.conv2(out)))
else:
out = F.relu(self.conv2(out))
return out
其中with_bn参数是为了分辨图中有的卷积不带bn,只有卷积后接relu操作。标准的卷积块是conv+bn+relu。
上采样
class up_conv2d_bn(nn.Module):
'''
Decoder上采样采用转置卷积,尺寸计算公式为 output = (input-1)*stride + outputpadding - 2*padding + kernelsize
'''
def __init__(self,in_channels,out_channels,kernel_size=2,strides=2):
super(up_conv2d_bn,self).__init__()
self.conv1 = nn.ConvTranspose2d(in_channels, out_channels, kernel_size = kernel_size, stride = strides,bias=True)
def forward(self,x):
out = F.relu(self.conv1(x))
return out
上采样的操作包括反池化、PixelShuffle、最近邻插值、双线性插值、转置卷积。以下依次介绍这些操作。
反池化
反池化操作有两种,一种是反最大池化,另一种是反平均池化。反池化是池化的逆操作,是无法通过池化的结果还原出全部的原始数据。因为池化的过程就只保留了主要信息,舍去部分信息。
反最大池化

主要原理就是在Maxpooling的时候保留最大值的位置信息,之后在UnPooling阶段使用该信息扩充Feature Map,除最大值位置以外,其余补0。
反平均池化

反平均池化的操作其实与反最大值池化操作类似,如反最大值池化上图只不过是除了索引位置,其他对应位置也用均值来代替。
PixelShuffle
PixelShuffle原理
主要原理就是将r*r个通道的特征图转换成新的w*r,h*r的上采样结果(比如原来特征图大小为4*128*128,现在调整成大小1*256*256)。具体来说,就是按照一定规则将每个像素点的r*r个通道依次转换为对应的r*r的图像块。

感觉这张原理图挺难理解的,不过代码应用起来还是很好理解。
# 上采样操作之亚像素卷积,
ps = nn.PixelShuffle(3) #3为放大倍数,即h与w方向上均扩大3倍
input = autograd.Variable(torch.Tensor(1, 9, 4, 4))
output = ps(input)
print(output.size())
torch.Size([1, 1, 12, 12])
最近邻插值
torch.nn.UpsamplingNearest2d(size=None, scale_factor=None)对输入信号做2D最近邻上采样。


import torch
import torch.nn as nn
input = torch.arange(1, 5, dtype=torch.float32).view(1, 1, 2, 2)
tensor([[[[1., 2.],
[3., 4.]]]])
upnear = nn.UpsamplingNearest2d(scale_factor=2)
out = upnear(input
深度学习:UNet网络结构详解及上采样操作

本文介绍了UNet网络结构,包括下采样和上采样的实现方式,如卷积、反池化、PixelShuffle、最近邻插值和转置卷积。此外,还展示了网络的整体搭建过程,以及数据集构建的基本方法。
最低0.47元/天 解锁文章
1872





