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 24 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-nn.ConvTransposed2d()

上采样下采样以及Pytorch中的卷积与反卷积(转置卷积)方法介绍(conv2d和convTranspose2d)

上采样下采样以及Pytorch中的卷积与反卷积(转置卷积)方法介绍(conv2d和convTranspose2d)

pytorch 建立模型的几种方法

Pytorch重要函数(nn.Conv2d;nn.ConvTranspose2d)

Pytorch保存和重装模型