Tensorflow中conv2d的两种padding方式(SAME与VALID)选择以及与Pytorch中对比

说明

自己的学习总结,参考了其他一些博客并加上了自己的一些理解,所以有部分直接复制的内容变量表示会不同(侵删),如有谬误,欢迎指正

基础知识

变量表示

输入图片的宽和高:i_w 和 i_h
输出特征图的宽和高:o_w 和 o_h
过滤器的宽和高:f_w 和 f_h
宽和高方向的步长:s_w 和 s_h
宽和高方向总的补零个数:pad_w 和 pad_h
顶部和底部的补零个数:pad_top 和 pad_bottom
左部和右部的补零个数:pad_left 和 pad_right

padding参数的作用是决定在进行卷积或池化操作时,是否对输入的图像矩阵边缘补0。

计算公式

正卷积

在正卷积时,一般我们希望卷积输入形状为输出形状的几倍,例如输入 256_256,输出 128_128,所以 o_w = i_w / s_w,又有 o_w = (i_w - f_w + pad_w) / s_w + 1, 所以可以得出 pad_w = f_w - s_wpad_h 类推。

反卷积

同理,在反卷积时,我们希望卷积输出形状为输入形状的几倍,例如输入 8_8,输出 256_256,所以 o_w = i_w * s_w,又有 o_w = i_w * s_w + f_w - s_w - pad_w, 所以可以得出 pad_w = f_w - s_w 不变,pad_h 类推。

SAME和VALID解释

VALID:边缘不填充

VALID方式就是这个单词的意思,也就是不进行填充,对于多出来的数据,直接丢掉

向上取整是为了1/strides_width一定是取1,这里的“1”是因为filter即使一步不动,原本也会有一步的输出

输入宽和高的公式分别为:
output_width=(in_width-filter_width+1)/strides_width #(结果向上取整)
output_height=(in_height-filter_height+1)/strides_height #(结果向上取整)

等价于:
output_width=(in_width-filter_width)/strides_width+1 #(结果向下取整)
output_height=(in_height-filter_height)/strides_height+1 #(结果向下取整)

SAME:边缘填充

SAME方式是为了避免丢弃信息,即fliter一定会把原有特征图全走一遍

计算输出大小以及补零数

向上取整的原因就是当特征图没有走完,但再走一步会超过边界时,补零走完这一步,然后结束这个方向上的卷积

# 输出的宽和高将与卷积核没关系,具体公式如下:
output_width=in_width/strides_width #(结果向上取整)
 
output_height=in_height/strides_height #(结果向上取整)
 
# 这里有一个很重要的知识点——补零的规则,见如下公式:
pad_height=max((out_height-1)*strides_height+filter_height-in_height,0)
 
pad_width=max((out_width-1)*strides_width+filter_width-in_width,0)
 
pad_top=pad_height/2
 
pad_bottom=pad_height-pad_top
 
pad_left=pad_width/2
 
pad_right=pad_width-pad_left

stride为1时的情况

如果卷积的步幅(stride)取值为 1,那么 padding = ‘SAME’ 就是指特征映射的分辨率在卷积前后保持不变,也就是输入(1,4,4),不管fliter怎么取,输出还是(1,4,4);
而 padding = ‘VALID’ 则是要下降 k - 1 个像素(即不填充,k 是卷积核大小)。

注:这时候padding='SAME’等价于padding=k//2,但是当stride不等于1时不成立

Pytorch

same 与 valid

在操作过程中过滤器可能不能将某个方向上的数据刚好处理完,。它可以是字符串{“valid”、“same”},也可以是一个整数元组,该元组给出了两侧应用的隐式填充量。
注意:pytorch仅支持stride=1时使用,这时的补零规则和tf相同(补右补下)

NOTE
padding='valid' is the same as no padding. padding='same' pads the input so the output has the shape as the input. However, this mode doesn’t support any stride values other than 1.

代码示例

import torch.nn as nn
import torch

testa = torch.ones([1, 4, 4])
conv = nn.Conv2d(1, 1, 2, padding='same')

conva = conv(testa)
print(conva)
print(conva.size())

# 输出,可以看到补奇数的时候,补右补下
>>tensor([[[0.8922, 0.8922, 0.8922, 0.2287], 
>>[0.8922, 0.8922, 0.8922, 0.2287], 
>>[0.8922, 0.8922, 0.8922, 0.2287], 
>>[0.7669, 0.7669, 0.7669, 0.4672]]], grad_fn=<SqueezeBackward1>) 
>>torch.Size([1, 4, 4])

补零方式

输入的所有四个边都添加了填充。默认值:0
注意:conv中的padding补零是要加bias的,所以不一定是0

Tensorflow

SAME与VALID

在操作过程中过滤器可能不能将某个方向上的数据刚好处理完,‘SAME’ 为对输入的图像矩阵边缘补零,‘VALID’ 则不补。

补零方式

在padding时,一般是对称地补,左/右各padding一列 或者 上下各padding一行。
当补奇数行时,tf一般把一行0补在下面或者把一列0补在右边。

参考

https://blog.csdn.net/theadore2017/article/details/107232208
https://www.jianshu.com/p/16373af724cc
https://pytorch.org/docs/stable/generated/torch.nn.Conv2d.html?highlight=conv2d#torch.nn.Conv2d

补充说明

Pytorch中的MaxPool目前还不支持same或valid方式

你可能感兴趣的:(pytorch,tensorflow,深度学习)