【深度学习知识】卷积当中的补零操作


1. 卷积输入输出尺寸公式

在这里插入图片描述
这是一条比较完整的输出尺寸公式,考虑到了stride, padding, dilation, 这里的括号表示的是向下取整,这实际上是卷积图的边边剩下的部分比卷积核小,所以抛弃了这次卷积的结果。
其实,若用另一种视角看,可以把空洞卷积当成更改了卷积核尺寸K的值,K -> d × (K-1) +1,因此该公式可以更简洁的被表示为
Out = floor((In + 2P − K)/S+1)

1.1 tensorflow 版本

tensorflow 版本的padding是通过直接选模式参数进行的,可选’SAME’,’VALID’.前者是通过padding在前后左右补零,使得输出尺寸保持不变(或以步长倍数缩小),非常常用,后者则是不进行padding,实际上应该是等价于上边总公式P=0的情况。
SAME: Out = ceil(In/S)
VALID: Out = ceil((In − K + 1)/S)

1.2 pytorch 版本

>>> m = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3)
>>> input = torch.randn(20,3,24,24)
>>> m(input).shape
torch.Size([20, 64, 12, 12])
>>> input = torch.randn(20,3,25,25)
>>> m(input).shape
torch.Size([20, 64, 13, 13])
>>> input = torch.randn(20,3,24,24)
>>> m = nn.Conv2d(3, 64, kernel_size=6, stride=2, padding=3)
>>> m(input).shape
torch.Size([20, 64, 13, 13])
>>> m = nn.Conv2d(3, 64, kernel_size=6, stride=2, padding=2)
>>> m(input).shape
torch.Size([20, 64, 12, 12])

>>> input = torch.randn(20,3,25,25)
>>> m = nn.Conv2d(3, 64, kernel_size=6, stride=2, padding=3)
>>> m(input).shape
torch.Size([20, 64, 13, 13])
>>> m = nn.Conv2d(3, 64, kernel_size=6, stride=2, padding=2)
>>> m(input).shape
torch.Size([20, 64, 12, 12])

这里可以观察到:

  • 若是需要保持
  • 对于奇数卷积核,通过让padding=(k-1)/2,即可实现SAME的效果。即输出尺寸保持不变或以步长倍数缩小(对于奇数输入尺寸则向上取整)
  • 对于偶数卷积核,若是偶数输入尺寸,则padding=floor((k-1)/2)可实现SAME的效果
  • 对于偶数卷积核,若是奇数输入尺寸,则padding=ceil((k-1)/2)可实现SAME的效果

因此,建议不要用偶数卷积核。。。然后记住padding=(k-1)/2,即可实现tf中SAME的效果了。把padding带入一开始的总公式,可以得到Out = floor((In − 1)/S+1),这实际上与SAME公式等效,可以看下边代码的暴力验证。

>>> a = lambda x:np.ceil(x/5)
>>> b = lambda x:np.floor((x-1)/5+1)
>>> c = [np.random.randint(6,100) for i in range(10)]
>>> [a(rand)==b(rand) for rand in c]
[True, True, True, True, True, True, True, True, True, True]

2. 总结

虽然想了半天这个公式,但实际使用时好像也就SAME功能用得比较多,因此记住核心:

  • 用奇数卷积核 padding=(k-1)/2
  • 若是空洞卷积,则代入K -> d × (K-1) +1

猜你喜欢

转载自blog.csdn.net/tobefans/article/details/125428881
今日推荐