一. Caffe、Tensorflow的padding策略

在之前的转载过的一篇文章——《tensorflow ckpt文件转caffemodel时遇到的坑》提到过,caffe的padding方式和tensorflow的padding方式有很大的区别,输出无法对齐。这是为什么呢?

下面简单回顾一下

卷积操作输出的形状计算公式是这样的:

output_shape = (image_shape-filter_shape+2*padding)/stride + 1

因为padding前面的系数是2,所以在padding时,一般是对称地补,左/右各padding一列 或者 上下各padding一行。

那么问题来了,如果stride是2,而括号里算出来的值刚好是奇数怎么办?那就再偷偷摸摸补一列padding或者补一行padding。

于是,caffe和tensorflow的区别就出来了。

caffe偷偷摸摸地把一行0补在上面 或者 把一列0补在左边,tensorflow正好镜像对称,把一行0补在下面或者把一列0补在右边。这就是导致输出对齐不了的原因,前面几层输出的feature map的中间还能勉强对上,随着网络结构的加深,到fc之前已经完全对不上了。

也就是说

  • caffe的padding策略是把0补在左上
  • tensorflow的padding策略是把0补在右下

那么,PyTorch的padding策略是怎样的呢?在介绍padding策略之前,先简单的介绍一下PyTorch中的nn.Conv2d算子。

二. nn.Conv2d简单说明

nn.Conv2d的介绍主要译自官网

nn.Conv2d的功能是:对由多个输入平面组成的输入信号进行二维卷积,以最简单的例子进行说明:

输入信号的形式为(N,Cin,H,W)(N,C_{in},H,W)(N,Cin​,H,W) ,NNN表示batch size,CinC_{in}Cin​表示channel个数,HHH,WWW分别表示特征图的高和宽。

参数说明:

  • stride(步长):控制cross-correlation的步长,可以设为1个int型数或者一个(int, int)型的tuple。

  • padding(补0):控制zero-padding的数目。

  • dilation(扩张):控制kernel点(卷积核点)的间距; 也被称为 "à trous"算法. 可以在此github地址查看:Dilated convolution animations

  • groups(卷积核个数):这个比较好理解,通常来说,卷积个数唯一,但是对某些情况,可以设置范围在1 —— in_channels中数目的卷积核:

At groups=1, all inputs are convolved to all outputs.
At groups=2, the operation becomes equivalent to having two conv layers side by side, each seeing half the input channels, and producing half the output channels, and both subsequently concatenated.
At groups=in_channels, each input channel is convolved with its own set of filters (of size ⌊out_channelsin_channels⌋
).

注意:kernel_size, stride, padding, dilation 不但可以是一个单个的int——表示在高度和宽度使用这个相同的int作为参数
也可以使用一个(int1, int2)的元组(本质上单个的int就是相同int的(int, int))。在元组中,第1个参数对应高度维度,第2个参数对应宽度维度。

还有一点需要提醒的是:卷积核的size的选择可能导致input中某几行(最后几行)没有关联起来,这是因为我们默认使用的模式是valid,而不是full(在tensorflow中也称为same)。如果想要充分利用input的话,则依赖于用户对padding以及stride等参数的设置。相比tensorflow,PyTorch需要用户清楚的知道的自己的卷积核选取对结果的影响。

参数的详细说明(基于PyTorch0.4.1)

下图中的HoutH_{out}Hout​和WoutW_{out}Wout​是根据我们在nn.Conv2d中设置的padding,dilation,kernel_size,stride等参数得到的输出特征图的高度和宽度。

三. nn.Conv2d中的padding操作

nn.Conv2d简单介绍完了,现在来讲讲padding在nn.Conv2d中怎么实现的,也就是怎么补的0,或者说补0的策略。

Q1: padding是卷积之后还是卷积之前还是卷积之后实现的?

padding是在卷积之前补0,如果愿意的话,可以通过使用torch.nn.Functional.pad来补非0的内容。

Q2:padding补0的默认策略是什么?

四周都补!如果pad输入是一个tuple的话,则第一个参数表示高度上面的padding,第2个参数表示宽度上面的
下面将展示一个padding = 1的例子:


显然,padding=1的效果是:原来的输入层基础上,上下左右各补了一行!除此之外我们看到,上下左右都是0.9862,那么,这个东西是啥呢?为什么不是0呢?

为了这个问题,我甚至还去PyTorch论坛上献丑了,估计大家可能也知道是咋回事了…
是的!是Bias!我问的问题是这样的:
Calculation detail in nn.Conv2d

Hello, I just can’t figure out the way nn.Conv2d calculate the output . The result calculated from torch is not the same as some machine learning course had taught.For example, likes the code below:>> m = torch.nn.Conv2d(1, 1, 3, padding=0)
>> m(input)
tensor([[[[ 0.5142,  0.3803,  0.2687],[-0.4321,  1.1637,  1.0675],[ 0.1742,  0.0869, -0.4451]]]], grad_fn=<ThnnConv2DBackward>)
>> input
tensor([[[[ 0.7504,  0.1157,  1.4940, -0.2619, -0.4732],[ 0.1497,  0.0805,  2.0829, -0.0925, -1.3367],[ 1.7471,  0.5205, -0.8532, -0.7358, -1.3931],[ 0.1159, -0.2376,  1.2683, -0.0959, -1.3171],[-0.1620, -1.8539,  0.0893, -0.0568, -0.0758]]]])
>> m.weight
Parameter containing:
tensor([[[[ 0.2405,  0.3018,  0.0011],[-0.1691, -0.0701, -0.0334],[-0.0429,  0.2668, -0.2152]]]], requires_grad=True)for the left top element 0.5142, it’s not the output equals to>> import numpy as np
>> w = np.array([[0.2405,  0.3018,  0.0011],
>>              [-0.1691, -0.0701, -0.0334],
>>              [-0.0429,  0.2668, -0.2152]])
# top-left 3x3 matrix of 5x5
>> x = np.array([[ 0.7504,  0.1157,  1.4940],
>>               [ 0.1497,  0.0805,  2.0829],
>>               [1.7471,  0.5205, -0.8532]])
>> print(np.sum(w*x))
#  0.364034 != 0.5142
0.36403412999999996My Question here is: Why Could the output not equal to 0.5142?Further more, when i add paramter padding into nn.Conv2d,
The outcome seems obscure to me as below, thanks a lot for explain that to me.Thank you!>> input
tensor([[[[ 0.7504,  0.1157,  1.4940, -0.2619, -0.4732],[ 0.1497,  0.0805,  2.0829, -0.0925, -1.3367],[ 1.7471,  0.5205, -0.8532, -0.7358, -1.3931],[ 0.1159, -0.2376,  1.2683, -0.0959, -1.3171],[-0.1620, -1.8539,  0.0893, -0.0568, -0.0758]]]])
# set padding from 0 to 1 equals to (1, 1)
>> m1 = torch.nn.Conv2d(1, 1, 1, padding=1)
>> m1(input)
tensor([[[[0.9862, 0.9862, 0.9862, 0.9862, 0.9862, 0.9862, 0.9862],[0.9862, 1.0771, 1.0002, 1.1672, 0.9544, 0.9288, 0.9862],[0.9862, 1.0043, 0.9959, 1.2385, 0.9749, 0.8242, 0.9862],[0.9862, 1.1978, 1.0492, 0.8828, 0.8970, 0.8174, 0.9862],[0.9862, 1.0002, 0.9574, 1.1398, 0.9745, 0.8266, 0.9862],[0.9862, 0.9665, 0.7615, 0.9970, 0.9793, 0.9770, 0.9862],[0.9862, 0.9862, 0.9862, 0.9862, 0.9862, 0.9862, 0.9862]]]],grad_fn=<ThnnConv2DBackward>)The confused point is that how 0.9862 be calculated?
And what is the default padding strategy in nn.Conv2d?Thank you for reading and answer!

答案也很简单——我没考虑bias!

根据下图,Q2中神秘的0.9862的来历我们就很清楚了,是bias的值。

PyTorch学习笔记(9)——nn.Conv2d和其中的padding策略相关推荐

  1. PyTorch学习笔记:nn.Sigmoid——Sigmoid激活函数

    PyTorch学习笔记:nn.Sigmoid--Sigmoid激活函数 torch.nn.Sigmoid() 功能:逐元素应用Sigmoid函数对数据进行激活,将元素归一化到区间(0,1)内 函数方程 ...

  2. PyTorch学习笔记:nn.Tanh——Tanh激活函数

    PyTorch学习笔记:nn.Tanh--Tanh激活函数 torch.nn.Tanh() 功能:逐元素应用Tanh函数(双曲正切)对数据进行激活,将元素调整到区间(-1,1)内 函数方程: Tanh ...

  3. PyTorch学习笔记:nn.LeakyReLU——LeakyReLU激活函数

    PyTorch学习笔记:nn.LeakyReLU--LeakyReLU激活函数 功能:逐元素对数据应用如下函数公式进行激活 LeakyReLU(x)=max⁡(0,x)+α∗min⁡(0,x)\tex ...

  4. PyTorch学习笔记:nn.ReLU——ReLU激活函数

    PyTorch学习笔记:nn.ReLU--ReLU激活函数 torch.nn.ReLU(inplace=False) 功能:逐元素应用ReLU函数对数据进行激活 函数方程: R e L U ( x ) ...

  5. pytorch 学习笔记:nn.Sequential构造神经网络

    1 两种等价的构造方式 1.1 构建Net类: 1.2 使用torch.nn.Sequential nn.Sequential里面的模块按照顺序进行排列的,所以必须确保前一个模块的输出大小和下一个模块 ...

  6. pytorch学习笔记 torchnn.ModuleList

    1 nn.ModuleList原理 nn.ModuleList,它是一个储存不同 module,并自动将每个 module 的 parameters 添加到网络之中的容器. 你可以把任意 nn.Mod ...

  7. pytorch 学习笔记目录

    1 部分内容 pytorch笔记 pytorch模型中的parameter与buffer_刘文巾的博客-CSDN博客 pytorch学习笔记 torchnn.ModuleList_刘文巾的博客-CSD ...

  8. PyTorch学习笔记(11)——论nn.Conv2d中的反向传播实现过程

    0. 前言 众所周知,反向传播(back propagation)算法 (Rumelhart et al., 1986c),经常简称为backprop,它允许来自代价函数的信息通过网络向后流动,以便计 ...

  9. PyTorch学习笔记2:nn.Module、优化器、模型的保存和加载、TensorBoard

    文章目录 一.nn.Module 1.1 nn.Module的调用 1.2 线性回归的实现 二.损失函数 三.优化器 3.1.1 SGD优化器 3.1.2 Adagrad优化器 3.2 分层学习率 3 ...

最新文章

  1. unordered_map 碰撞处理 重哈希
  2. ElementUI数据联动计算并实现数据校验
  3. 列表初始化和赋值初始化的使用注意事项
  4. 光耦驱动单向可控硅_光耦继电器在实际应用中的作用以及工作原理!!
  5. vue中自定义指令、组件化、生命周期、节流和防抖、获取DOM、mint-ui简介、过渡和动画
  6. iOS开发之常见的URLScheme
  7. python与sql server_Python和SQL Server 2017的强大功能
  8. word文档太大怎么压缩到最小?
  9. 爱希ISee人体感应器,雷达人体存在探测应用,毫米波雷达技术方案
  10. TM1650芯片使用经验
  11. mysql卸载报错2503_Win10系统卸载Skype软件报错2503的解决方法
  12. Information:java: Errors occurred while compiling module
  13. android 辅助服务默认开启,Android 检测辅助功能是否开启,并调整设置页面
  14. [经验教程]拼多多直接免拼是什么意思?
  15. 为什么使用服务器端渲染 (SSR)?
  16. 斗战神服务器正在维护6,17173《斗战神》专区——3月15日维护公告:疲劳刷新改为每天6点...
  17. 计算机作文范文,未来计算机作文范文.docx
  18. webSocket 实现消息推送、心跳、已读消息、加载更多等功能
  19. MVC模式,分层结构
  20. 计算机网络:奈氏准则与香农定理

热门文章

  1. vue 获取id元素_.vue组件中获取DOM元素问题
  2. PDF文件加密了如何破解
  3. 【图像处理】图像锐化的工作原理和算法实现(matlab实现)
  4. PyTorch scatter_ 从懵懂到清晰
  5. Phonegap事件之pause事件
  6. VR全景拍摄时我们应该注意哪些技巧?
  7. 西安“大唐不夜城·现代唐人街”开街 传统与现代混搭并存
  8. 计算机组成-无符号数乘法
  9. 芯片模型算力指标TOPS FLOPS MAC MACC MADD关系
  10. RA layer request failed