PyTorch 的 Conv2d 真的没有 padding=same 选项吗?
Posted
技术标签:
【中文标题】PyTorch 的 Conv2d 真的没有 padding=same 选项吗?【英文标题】:Is there really no padding=same option for PyTorch's Conv2d? 【发布时间】:2020-02-06 23:04:51 【问题描述】:我目前正在构建一个可以处理时间序列数据的卷积神经网络 (CNN)。
更具体地说,数据是(100, 40)
形状的财务数据,100
表示100个时间戳,40
表示40个特征。
我使用的 CNN 使用不对称内核大小(即 1 x 2
和 4 x 1
)和不对称步幅(即 1 x 2
用于 1 x 2
层,1 x 1
用于 4 x 1
层) .
为了保持高度尺寸保持100
,我需要对数据应用一些填充。我正在研究如何做到这一点,并注意到使用 TensorFlow 或 Keras 的人只需使用 padding='same'
,但根据我发现的许多资源,包括 this thread on Github,此选项在 PyTorch 中显然不可用。
我发现根据some answers in this question 和this answer on the PyTorch discussion forum,我可以手动计算我需要如何填充我的数据并且可以使用torch.nn.ZeroPad2d
来解决我的问题,因为看起来很正常@987654325 @layers 不支持非对称填充(我相信我需要的总填充是高 3 宽 0)。
我为测试而编写的实验代码是这样的:
import torch
import torch.nn as nn
conv = nn.Conv2d(1, 1, kernel_size=(4, 1))
pad = nn.ZeroPad2d((0, 0, 2, 1)) # Add 2 to top and 1 to bottom.
x = torch.randint(low=0, high=9, size=(100, 40))
x = x.unsqueeze(0).unsqueeze(0)
y = pad(x)
x.shape # (1, 1, 100, 40)
y.shape # (1, 1, 103, 40)
print(conv(x.float()).shape)
print(conv(y.float()).shape)
# Output
# x -> (1, 1, 97, 40)
# y -> (1, 1, 100, 40)
如您所见,它确实在尺寸大小保持不变的意义上起作用。但是,我一直想知道那里真的没有padding='same'
选项吗?另外,我们如何知道是将 padding 2 应用到顶部还是底部?
谢谢。
编辑
这有点晚了,但如果有人好奇我是如何解决这个问题的,我基本上是手动添加填充以模拟padding=same
选项。
【问题讨论】:
***.com/questions/55140554/…看看那个,它会给你一个线索。 说真的,由于其静态计算图,Tensorflow 中的该功能是可能的。在 PyTorch 中,有一个动态计算图,所以可能很难实现(否则他们早就这么做了)。在nn.Conv2D
内,如你所说,只有对称填充,但不同的维度可以做不同的填充。
我认为@akshayk07 是对的,而 pytorch 的动态特性使它变得困难;这是 pytorch 中“相同”填充的一个很好的实现(用于 2d 转换):github.com/rwightman/pytorch-image-models/blob/master/timm/…
【参考方案1】:
前段时间我遇到了同样的问题,所以我自己使用ZeroPad2d
层实现了它,就像您尝试做的那样。这是正确的公式:
from functools import reduce
from operator import __add__
kernel_sizes = (4, 1)
# Internal parameters used to reproduce Tensorflow "Same" padding.
# For some reasons, padding dimensions are reversed wrt kernel sizes,
# first comes width then height in the 2D case.
conv_padding = reduce(__add__,
[(k // 2 + (k - 2 * (k // 2)) - 1, k // 2) for k in kernel_sizes[::-1]])
pad = nn.ZeroPad2d(conv_padding)
conv = nn.Conv2d(1, 1, kernel_size=kernel_sizes)
print(x.shape) # (1, 1, 103, 40)
print(conv(y.float()).shape) # (1, 1, 103, 40)
另外,正如@akshayk07 和@Separius 所提到的,我可以确认是pytorch 的动态特性使它变得困难。 Here 是来自 Pytorch 开发人员的关于这一点的帖子。
【讨论】:
【参考方案2】:现在好像有,在 pytorch 1.9.1
,根据docs.
padding='valid'
与无填充相同。padding='same'
垫 输入,因此输出具有作为输入的形状。然而,这种模式 不支持 1 以外的任何步幅值。
【讨论】:
以上是关于PyTorch 的 Conv2d 真的没有 padding=same 选项吗?的主要内容,如果未能解决你的问题,请参考以下文章
上采样下采样以及Pytorch中的卷积与反卷积(转置卷积)方法介绍(conv2d和convTranspose2d)
上采样下采样以及Pytorch中的卷积与反卷积(转置卷积)方法介绍(conv2d和convTranspose2d)