当前位置: 首页 > news >正文

Pytorch之经典神经网络语义分割(3.1) —— 空洞卷积 Dilated conv/Atrous Conv (膨胀卷积/扩张卷积)(扩张率dilation rate)

2016年提出的

空洞卷积广泛应用于语义分割与目标检测等任务中

空洞卷积(膨胀卷积/扩张卷积) Dilated/Atrous Convolution

空洞卷积是一种不增加参数量(运算量)同时增加输出单元感受野的一种方法。Atrous 卷积,就是带洞的卷积,卷积核是稀疏的

此外,空洞卷积还可以捕获多尺度上下文信息。通过设置不同的dilation rate,感受野就会不一样,也即获取了多尺度信息。多尺度信息在视觉任务中相当重要。

空洞卷积的概念是从语义分割任务中发展出来的,是为了解决基于FCN思想的语义分割中,输出图像的size要求和输入图像的size一致而需要upsample,但由于FCN中使用pooling操作来增大感受野同时降低分辨率,导致upsample无法还原由于pooling导致的一些细节信息的损失的问题而提出的。为了减小这种损失,自然需要移除pooling层,因此空洞卷积应运而生。

原先的 CNN architecture 是用一个“实心”的 kernal 去扫描 input data,然后使用 pooling 方法直接暴力的删掉其余 75% 的信息量,只留下 25% 的原汁原味,这样的做法在还没有精确到 pixel-wise 的情况时还是可以行的通的,一旦要归类到小至 pixel 等级的尺度时,pooling 对原 data 的破坏力足以让事情搞砸,试想一个原始数据被经过 Convolution 剥离出了其区域特征后,接着下一个环节被大刀阔斧般的砍去内部信息,并且永久无法复原,小物体信息无法重建 (假设有四个pooling layer 则任何小于 2^4 = 16 pixel 的物体信息在理论上将无法重建和分割)。这是在微小的 pixel 世界中无法接受的做法。

如果说 pooling 这种简单删减 data 让单位 output 中 Receptive Field 增大的方法不可行,就需要一个新的在不删减原始数据的情况下,直接让 Receptive Field 提升的办法:Dilated Convolution。简单的说,就是把原本“实心”的 kernal 元素之间按照一定规律插入 0 元素作为空格

空洞卷积向卷积层引入了一个称为 “扩张率(dilation rate)”的新参数,该参数定义了卷积核处理数据时各值的间距。

看下图可以对膨胀率有一个比较直观的理解

假设原始特征为feat0

首先使用扩张率为1的空洞卷积生成feat1,feat1上一点相对feat0感受野为3*3(如图a);

然后使用扩张率为2的空洞卷积处理feat1生成feat2(如图b),使第一次空洞卷积的卷积核大小等于第二次空洞卷积的一个像素点的感受野,图b即feat1上一个点综合了图a即feat0上3*3区域的信息,则生成的feat2感受野为7*7,即整个图b深色区域;

第三次处理同上,第二次空洞卷积的整个卷积核大小等于第三次空洞卷积的一个像素点的感受野,图c即feat2上每个点综合了feat0上7*7的信息(感受野),则采用扩张率为3的空洞卷积,生成的feat3每一个点感受野为15*15。

普通卷积的结果的size是

经过空洞卷积后的结果的size是

r是dilation

例子:7*7的feature map,kernel size = 3, padding = 0,stride = 1, dilation =2
标准卷积后大小F为(7-3+0)/1+1 = 5,Dilated卷积后大小F为[7-(3+2*1)+0]/1+1=3

空洞卷积存在的问题

潜在问题 1:The Gridding Effect

假设我们仅仅多次叠加 dilation rate 2 的 3 x 3 kernel 的话,则会出现这个问题:

我们发现我们的 kernel 并不连续,也就是并不是所有的 pixel 都用来计算了,因此这里将信息看做 checker-board 的方式会损失信息的连续性。这对 pixel-level dense prediction 的任务来说是致命的。

由于空洞卷积的计算方式类似于棋盘格式,某一层得到的卷积结果,来自上一层的独立的集合,没有相互依赖,因此该层的卷积结果之间没有相关性,即局部信息丢失

潜在问题 2:Long-ranged information might be not relevant.

我们从 dilated convolution 的设计背景来看就能推测出这样的设计是用来获取 long-ranged information。然而光采用大 dilation rate 的信息或许只对一些大物体分割有效果,而对小物体来说可能则有弊无利了。如何同时处理不同大小的物体的关系,则是设计好 dilated convolution 网络的关键。

由于空洞卷积稀疏的采样输入信号,使得远距离卷积得到的信息之间没有相关性,影响分类结果。

解决方法: Hybrid Dilated Convolution (HDC)

 总结-空洞卷积(Dilated/Atrous Convolution) - 知乎

代码实现

dilation convolution的操作内置在nn.Conv2d里面了

正常的紧密的kernel,dialation=1(默认)

dialation=2的情况,就不是紧凑的了

手动实现

import torch
from torch import nn
import torch.nn.functional as F
import math
 
def my_conv(input, kernel, stride=1, padding=0, bias=0, dilation=1):
    if padding > 0:
        input = F.pad(input, (padding,padding,padding,padding))
    batch_size, in_channel, input_h, input_w= input.shape
    out_channel, _, kernel_h, kernel_w = kernel.shape
    
    #本来紧凑的输入,现在相邻点之间要插入dialation-1个空洞,共插入kernel_h-1次
    kernel_h = (kernel_h-1)*(dilation-1)+kernel_h
    kernel_w = (kernel_w-1)*(dilation-1)+kernel_w
    
    output_h = math.floor((input_h - kernel_h) / stride + 1)
    output_w = math.floor((input_w - kernel_w) / stride + 1)
    output = torch.zeros(batch_size, out_channel, output_h, output_w)
    
    if bias is None:
        bias = torch.zeros(out_channel)
    
    for b in range(batch_size):
        for c in range(out_channel):
            for i in range(0, input_h - kernel_h + 1, stride):
                for j in range(0, input_w - kernel_w + 1, stride):
                    region = input[b,:,i:i+kernel_h:dilation, j:j+kernel_w:dilation]
                    output[b,c,int(i/stride), int(j/stride)] = torch.sum(region*kernel[c]) + bias[c]                
    return output
 
batch_size = 4
in_channel = 4
out_channel = 16
dilation = 2
input = torch.rand(batch_size, in_channel ,5,5)
kernel = torch.rand(out_channel, in_channel, 3,3)
bias = torch.rand(out_channel)
 
my_output = my_conv(input, kernel, padding=1, stride=2, bias=bias, dilation=dilation)
output = F.conv2d(input, kernel, padding=1, stride=2, bias=bias, dilation=dilation)
 
assert torch.allclose(my_output, output)

相关文章:

  • OpenCV(二) —— 颜色通道提取 边界填充 数值计算 图像融合
  • OpenCV四) —— 图像形态学处理(腐蚀操作 膨胀操作 开运算与闭运算 梯度运算 礼貌与黑帽)
  • OpenCV(五) —— 图像梯度处理 边缘检测(Sobel算子 Scharr算子 laplacian算子 Canny算子)
  • OpenCV(六) —— 边缘检测(Canny)
  • OpenCV(七) —— 图像金字塔(拉普拉斯金字塔) 轮廓检测(轮廓特征 轮廓近似 轮廓绘制 边界矩形 外接圆 ) 傅里叶变换
  • OpenCV(八) —— 直方图(mask操作 (自适应)直方图均衡化) 模板匹配 图像特征(harri角点检测)
  • TPU 使用TPU训练tensorflow初探(Colab)
  • 搜索中的TSA(树搜索算法) GSA(图搜索算法) UCS(代价一致) CSP(约束满足问题)
  • 二分图(二分图判断之染色法 最大匹配 最佳匹配 匈牙利算法)
  • 位图索引Bitmap indexes(数据库索引)
  • YOLO算法(二)—— Yolov2 yolo9000
  • YOLO算法(三)—— Yolov3 Yolo系列网络优缺点
  • Python的__future__模块
  • 启发函数heuristic 与 A*
  • 什么是non-trivial
  • 【React系列】如何构建React应用程序
  • 【每日笔记】【Go学习笔记】2019-01-10 codis proxy处理流程
  • es的写入过程
  • Java 多线程编程之:notify 和 wait 用法
  • opencv python Meanshift 和 Camshift
  • php ci框架整合银盛支付
  • Python 基础起步 (十) 什么叫函数?
  • Rancher如何对接Ceph-RBD块存储
  • 更好理解的面向对象的Javascript 1 —— 动态类型和多态
  • 我是如何设计 Upload 上传组件的
  • 3月7日云栖精选夜读 | RSA 2019安全大会:企业资产管理成行业新风向标,云上安全占绝对优势 ...
  • #pragma once与条件编译
  • #每日一题合集#牛客JZ23-JZ33
  • #周末课堂# 【Linux + JVM + Mysql高级性能优化班】(火热报名中~~~)
  • (顶刊)一个基于分类代理模型的超多目标优化算法
  • (附源码)ssm经济信息门户网站 毕业设计 141634
  • (原創) 如何刪除Windows Live Writer留在本機的文章? (Web) (Windows Live Writer)
  • (转)eclipse内存溢出设置 -Xms212m -Xmx804m -XX:PermSize=250M -XX:MaxPermSize=356m
  • (转载)从 Java 代码到 Java 堆
  • .bat批处理出现中文乱码的情况
  • .dat文件写入byte类型数组_用Python从Abaqus导出txt、dat数据
  • .form文件_SSM框架文件上传篇
  • .net core 控制台应用程序读取配置文件app.config
  • .net 程序发生了一个不可捕获的异常
  • .NET/C# 在代码中测量代码执行耗时的建议(比较系统性能计数器和系统时间)...
  • .Net程序猿乐Android发展---(10)框架布局FrameLayout
  • .NET开源全面方便的第三方登录组件集合 - MrHuo.OAuth
  • @column注解_MyBatis注解开发 -MyBatis(15)
  • [ CTF ] WriteUp- 2022年第三届“网鼎杯”网络安全大赛(白虎组)
  • [ Linux 长征路第五篇 ] make/Makefile Linux项目自动化创建工具
  • [] 与 [[]], -gt 与 > 的比较
  • [bzoj1901]: Zju2112 Dynamic Rankings
  • [CSDN首发]鱿鱼游戏的具体玩法详细介绍
  • [JDK工具-2] javap 类文件解析工具-帮助理解class文件,了解Java编译器机制
  • [luoguP3159] [CQOI2012]交换棋子(最小费用最大流)
  • [nginx] LEMP 架构随笔
  • [NISACTF 2022]join-us
  • [NOIP 2015]Day.1 T2 信息传递 【最小环】
  • [PHP]加密解密函数
  • [python] dataclass 快速创建数据类