Unet的一些概念

Unet 的初衷:

是为了解决生物医学图像方面的问题,最初也是在细胞数据集上使用的,由于效果确实很好后来也被广泛的应用在语义分割的各个方向,比如卫星图像分割,工业瑕疵检测等。

Unet 的优势:

1,可以在小数据集上达到较好的效果。以往的网络模型依赖于大量的数据集进行训练,但是在医学图像的分割中,往往能够训练的数据相对较小而检测目标又会比较大,在unet网络中使用了数据增强;

2,可以对每个像素点进行分割,获得更高的分割准确率;

3,在训练过程中使用高梯度下降,这使得训练模型的学习率处在一个自我调节的过程中;

4,权重划分。权重划分公式为:

是用于平衡类别频率的权重图代表到最近细胞的边界的距离,​代表到第二近的细胞的边界的距离。基于经验我们设定=10,σ≈5像素

5,引入图像镜像操作,能够更好的对数据进行训练。

Unet的网络结构

基本概念:

U-Net的结构是用编码和解码,它左边和右边很类似(完全对称),U形的左侧是一个编码的过程,右侧是一个解码的过程。

1,网络是一个全卷积网络(即网络中没有全连接操作)

2,网络的输入是一张572*572的边缘经过镜像操作的图片

3,通过两次卷积之后得到特征图像,然后经过池化进行收缩

4,重复步骤3,总共进行4次

5,通过复制和裁剪,融合之后再经过两次卷积,然后反卷积进行解码

6,重复步骤5,总共进行4次

7,经过两次卷积和一次1*1卷积得到最终的结果。

代码解释:

conv1*1:

1)对于单通道图像,其作用仅仅是进行线性运算;

2)对于多通道图像,会遍历图像所在的位置,将每个位置处所有通道的值作为其输入,与1*1卷积核中对应通道的值进行线性运算。本质上可以视为一个全连接神经网络。

(conv1*1一般只改变输出的通道数,而不改变输出的宽度和高度;而Pooling操作一般只改变输出的宽和高,而不改变通道数)

模型代码:

关于两层conv3*3:

import torch.nn as nnclass DoubleConv(nn.Module):"""(convolution => [BN] => ReLU) * 2"""def __init__(self, in_channels, out_channels):super().__init__()self.double_conv = nn.Sequential(#torch.nn.Sequential是一个时序容器,modules会以它们传人的顺序被添加到容器中nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=0),nn.BatchNorm2d(out_channels), #归一化处理,为了避免在进行relu之前因为数据过大而导致网络性能不稳定nn.ReLU(inplace=True),nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=0),nn.BatchNorm2d(out_channels),nn.ReLU(inplace=True))def forward(self, x):return self.double_conv(x)

关于max pool 2*2:

import torch.nn as nnclass Down(nn.Module):"downscaling and maxpool 2*2 then coupleconv”def __int__(self, in_channenls, out_channels):super().__init__()self.maxpool_conv = nn.Sequential(nn.MaxPool2d(2),Douleconv(in_channenls,out_channels))def forward(self, x):return self.maxpool_conv(x)

关于copy  and crop 以及 up conv:

class Up(nn.Module):"""Upscaling then double conv"""def __init__(self, in_channels, out_channels, bilinear=True):super().__init__()# if bilinear, use the normal convolutions to reduce the number of channelsif bilinear:self.up = nn.Upsample(scale_factor=2, mode='bilinear', align_corners=True)self.conv = DoubleConv(in_channels, out_channels, in_channels // 2)else:self.up = nn.ConvTranspose2d(in_channels, in_channels // 2, kernel_size=2, stride=2)self.conv = DoubleConv(in_channels, out_channels)def forward(self, x1, x2):x1 = self.up(x1)# input is CHWdiffY = x2.size()[2] - x1.size()[2]diffX = x2.size()[3] - x1.size()[3]x1 = F.pad(x1, [diffX // 2, diffX - diffX // 2,diffY // 2, diffY - diffY // 2])# if you have padding issues, see# https://github.com/HaiyongJiang/U-Net-Pytorch-Unstructured-Buggy/commit/0e854509c2cea854e247a9c615f175f76fbb2e3a# https://github.com/xiaopeng-liao/Pytorch-UNet/commit/8ebac70e633bac59fc22bb5195e513d5832fb3bdx = torch.cat([x2, x1], dim=1)return self.conv(x)

关于conv1*1:

class OutConv(nn.Module):def __init__(self, in_channels, out_channels):super(OutConv, self).__init__()self.conv = nn.Conv2d(in_channels, out_channels, kernel_size=1)def forward(self, x):return self.conv(x)

应用

1,主要用于医学分割;

2,姿态估计;

3,Gan网络。

联系:VGG——resnet——FCN——Unet

问题

1,图像分割为什么要采用先编码后解码的形式?

1)下采样是为了图像识别,可以降低显存和计算量;增大感受野,使卷积获得更全局性的特征提取;多级语义融合可以使得分类更加准确;

2)上采样是为了便于分割处理,输出得到分割结果mask。当然,上采样不能够恢复成为原始图像,这个过程中已经丢失了许多特征,因此unet中使用了copy and crop来做补充。

2,上采样过程中使用skip-connection保留细节,那这个过程中像素点增加,不会导致下采样过程中降低的显存和计算量增加回来吗,为什么这样能得到一个好的效果?

1)个人认为unet图像分割的下采样可能更主要的是为了增大感受野,同时在增大感受野的过程中计算量的显存得到降低;

2)而在上采样的过程中,是为了提升其精度,但是大量的padding确实造成了巨大的冗余,这也是unet网络慢的一个原因。

有个说法,cnn网络分类精度和定位精度难以共存,那unet下采样增大感受野skip-connection增加精度的方式是否对这个说法有一定的冲击?

训练部分

相关参数:

learning_rate:学习率决定了权值的更新速度,设置得太大会使结果超过最优值,太小会使下降速度过慢。在训练模型时,通常会遇到:我们训练模型时已经平衡了模型的训练速度和loss去选择相对合适的学习率,但是训练集的loss降低到一定程度之后就不再下降了,而是在一个区间来回,这种情况可以通过适当降低学习率来实现,但是学习率的降低又会延长训练时间。

一般的解决办法是——学习率衰弱(learning rate decay)基本思想是:学习率随着训练的进行逐渐衰弱。

val_percent:验证集的划分比例,这里采用了整个数据集的90%做训练集,10%做验证集;

weight_decay: 的作用是用当前可学习参数p的值修改偏导数。weight_decay的作用是正则化,和RMSProp并无直接关系,但是可以一定程度上缓解过拟合。

save_checkpoint:checkpoint检查点,不仅保存模型的参数,优化器参数,还有loss,epoch等(相当于一个保存模型的文件夹)。

amp:自动混合精度。

monmenrum:动量来源于牛顿定律,基本思想是为了找到最优,SGD通常来说下降速度比较快,但却容易造成另一个问题,就是更新过程不稳定,容易出现震荡。加入“惯性”的影响,就是在更新下降方向的时候不仅要考虑到当前的方向,也要考虑到上一次的更新方向,两者加权,某些情况下可以避免震荡,摆脱局部凹域的束缚,进入全局凹域。动量,就是上一次更新方向所占的权值。当误差曲面中存在平坦区域,SGD可以更快的学习,是梯度下降法中一种常用的加速技术。
对于一般的SGD,其表达式为:
w := w - lr * dw
即沿负梯度方向下降。而添加momentum的SGD形式如下:
v := mu * v - lr * dw
w := w + v
其中mu为momentum系数,即如果上一次的momentum(v)与这一次的负梯度方向是相同的,则这次下降的幅度就会很大,就起到加速迭代收敛的作用。当刚开始训练的时候,把动量设小,或者直接就置为0,然后慢慢增大动量,有时候效果比较好。

gradient_clipping:梯度裁剪。

优化器:

传统梯度优化:

BGD:批量梯度下降算法,在训练的时候选用所有的训练集进行计算;

SGD:随机梯度下降算法,在训练的时候只选用一个数据进行训练;

MBGD:小批量梯度下降算法,在训练的时候只选用小部分数据进行训练;

虽然这三种算法在选择数据集量的时候不同,但是他们在进行参数优化的时候是相同的;一般采用小批量梯度下降算法,即选择部分数据进行训练,因为它们更新参数的时候采用相同的参数,因此它们统称为“传统梯度更新算法”,基本思想是:先设定一个学习率,参数沿梯度的反方向移动,假设需要更新的参数为,梯度为g,则其更新策略可表示为:

传统算法的优化算法:

针对传统梯度优化过于依赖学习率的选取的缺点问题,许多优化算法从梯度方向和学习率两方面入手。有些从梯度方向入手,如动量更新策略;有些从学习率入手,这涉及到调参的问题;还有的从两方面同时入手,如自适应更新策略;

AdaGrad算法:

适合处理稀疏数据,通过参数来调整合适的学习率,对稀疏参数进行大幅更新和对频繁参数进行小幅更新。可能是因为其累计梯度平方导致学习率过早或过量的减少所致,它在某些深度学习模型上有着不错的效果,但仍不够优秀。

RMSProp算法:

RMSProp算法通过修改AdaGrad得来,其目的是在非凸背景下效果更好。针对梯度平方和累计越来越大的问题,RMSProp指数加权的移动平均代替梯度平方和。RMSProp为了使用移动平均,还引入了一个新的超参数,用来控制移动平均的长度范围。它在深度学习中被广泛用于深度神经网络优化。

Unet——pytorch相关推荐

  1. unet脑肿瘤分割_[论文代码]UNET++pytorch实现+环境安装+代码解释+brats2018脑肿瘤二维分割,UNetpytorch,Brats2018,2D...

    原始的代码: 链接 我修改后的代码: 链接 1.env 环境的安装 windows10 64 bits.nvidia驱动.CUDA8.0.cudnn.anaconda 打开命令窗口, 分别输入以下指令 ...

  2. U-Net Pytorch实现

    import torch.nn as nn import torch from torch import autograd#把常用的2个卷积操作简单封装下 class DoubleConv(nn.Mo ...

  3. UNet Introducing Symmetry in Segmentation

    UNet Introducing Symmetry in Segmentation 转载自:https://towardsdatascience.com/u-net-b229b32b4a71 Intr ...

  4. 基于Python Unet的医学影像分割系统源码,含皮肤病的数据及皮肤病分割的模型,用户输入图像,模型可以自动分割去皮肤病的区域

    手把手教你用Unet做医学图像分割 我们用Unet来做医学图像分割.我们将会以皮肤病的数据作为示范,训练一个皮肤病分割的模型出来,用户输入图像,模型可以自动分割去皮肤病的区域和正常的区域.废话不多说, ...

  5. 三分钟教你快速选择机器视觉传感器

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转自|新机器视觉 六招教您合理选择机器视觉传感器 传感器是一种 ...

  6. pytorch | 深度学习分割网络U-net的pytorch模型实现

    原文:https://blog.csdn.net/u014722627/article/details/60883185 pytorch | 深度学习分割网络U-net的pytorch模型实现 这个是 ...

  7. 【小白学习PyTorch教程】十九、 基于torch实现UNet 图像分割模型

    @Author:Runsen 在图像领域,除了分类,CNN 今天还用于更高级的问题,如图像分割.对象检测等.图像分割是计算机视觉中的一个过程,其中图像被分割成代表图像中每个不同类别的不同段. 上面图片 ...

  8. 基于U-net的肝脏肿瘤分割实战(Pytorch实现)

    这是我去年本科毕业设计的一部分,去年使用tensorflow去实现的,这几天就随手用Pytorch做了一下实现.肝脏肿瘤的分割是医学影像分割里面比较重要的一部分,实现从人的CT或MRI影像中将肝脏区域 ...

  9. pytorch 测试每一类_2D UNet++ VGGBlock脑胶质瘤分割BraTs + Pytorch实现

    UNet++讲解 玖零猴:UNet++解读 + 它是如何对UNet改进 + 作者的研究态度和方式​zhuanlan.zhihu.com BraTs数据准备 数据来源 本文用的训练集和验证集均来自Bra ...

最新文章

  1. MACE(2)-----模型编译
  2. 用imageNamed加载图片产生的问题
  3. ubuntu16搭建z-blog博客
  4. 面向对象基础回顾(二)
  5. 牛客题霸 [用两个栈实现队列] C++题解/答案
  6. Java –缺少字体–崩溃的应用程序!
  7. jpa和hibernate_从JPA到Hibernate的旧版和增强型标识符生成器
  8. 【洛谷P1966】火柴排队
  9. Html控件和Web控件(转)
  10. SQLyog备份与还原数据库
  11. iOS学习——Socket
  12. nginx之lua_shared_dict命令
  13. 小红书种草达人类型有哪些?如何评判达人质量
  14. Java获取今天是星期几
  15. 68个Python内置函数详解,进阶必备
  16. 【工具】一键制作纯净ROM去除推广APP,支持线刷包卡刷包
  17. 国外整理的一套在线渗透测试资源合集[转载]
  18. 端智能助力西瓜视频业务实践
  19. mysql 复合索引(联合索引) a b c的使用
  20. uniapp图片无法显示

热门文章

  1. 软件测试基础篇1--探索式软件测试中用到的一些方法
  2. win7计算机服务项,新萝卜家园win7旗舰版服务项的详解
  3. Windows Server 2008 R2中关闭“IE增强的安全配置”
  4. 普及篇:什么是瀑布模型?
  5. 单片机项目:8个发光二极管从上至下间隔一秒流动,其中每个管亮500ms,500ms,亮时蜂鸣器响,灭时蜂鸣器关闭,一直重复下去
  6. 【MySql 数据库综合练习01 】
  7. Terracotta Server集群
  8. import nose ImportError: No module named 'nose'
  9. VC中三种常见中文内码的转换方法(GB2312/GBK/BIG5)
  10. 软考中级-嵌入式系统设计师(三)