PyTorch 模型输入形状

She*_*zod 3 python deep-learning conv-neural-network pytorch

我加载了一个自定义 PyTorch 模型,我想找出它的输入形状。像这样的东西:

model.input_shape
Run Code Online (Sandbox Code Playgroud)

是否有可能获得这些信息?


更新: print()并且summary()不显示此模型的输入形状,因此它们不是我要找的。

Ale*_*sai 9

print(model)
Run Code Online (Sandbox Code Playgroud)

将为您提供模型的摘要,您可以在其中看到每一层的形状。

您还可以使用pytorch-summary包。

如果您的网络将 FC 作为第一层,您可以轻松计算出其输入形状。您提到前面有一个卷积层。由于还存在全连接层,网络将仅针对一种特定的输入大小生成输出。我建议通过使用各种形状来解决这个问题,即向玩具批次提供某种形状,然后检查 FC 层之前的 Conv 层的输出。

由于这取决于第一个 FC 层之前的网络架构(转换层数、内核数等),因此我无法为您提供正确输入的确切公式。如前所述,您必须通过试验各种输入形状以及第一个 FC 之前得到的网络输出来弄清楚这一点。(几乎)总是有办法用代码解决问题,但我现在想不出其他的办法。

  • 这个答案偏离主题,“print()”和“pytorch-summery”不显示输入形状。它们显示了每一层的输出形状。 (5认同)
  • 但这与“input_shape”无关 (4认同)

uke*_*emi 5

PyTorch 的灵活性

PyTorch 模型是非常灵活的对象,以至于它们不强制执行或通常不期望数据的固定输入形状。

如果您有某些层,则可能存在限制,例如:

  • 扁平化后跟宽度为 N 的完全连接层将强制原始输入的尺寸 (M1 x M2 x ... Mn) 具有等于 N 的乘积
  • N 个输入通道的 2d 卷积将强制数据为 3 维,第一个维度的大小为 N

但是正如您所看到的,这些都没有强制执行数据的整体形状。

我们现在可能没有意识到,但在更复杂的模型中,正确设置第一个线性层的大小有时会令人沮丧。我们听说过一些著名的从业者输入任意数字,然后依靠 PyTorch 的错误消息来回溯其线性层的正确大小的故事。跛脚,嗯?不,这都是合法的!

  • 使用 PyTorch 进行深度学习

调查

简单案例:第一层是全连接的

如果模型的第一层是全连接层,则第一层print(model)将详细说明单个样本的预期维度。

模棱两可的案例:CNN

然而,如果它是一个卷积层,因为它们是动态的,并且会在输入允许的范围内尽可能长/宽,所以没有简单的方法可以从模型本身检索这些信息。1这种灵活性意味着对于许多架构,多种兼容的输入大小2都可以被网络接受。

这是 PyTorch 的动态计算图的一个特性。

人工检查

你需要做的是调查网络架构,一旦你找到了一个可解释的层(如果存在,例如完全连接),就用它的维度“向后工作”,确定之前的层(例如池化和卷积)如何具有压缩/修改它。

例子

例如,在使用 PyTorch 进行深度学习(8.5.1)的以下模型中:

class NetWidth(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(3, 32, kernel_size=3, padding=1)
        self.conv2 = nn.Conv2d(32, 16, kernel_size=3, padding=1)
        self.fc1 = nn.Linear(16 * 8 * 8, 32)
        self.fc2 = nn.Linear(32, 2)
    
    def forward(self, x):
        out = F.max_pool2d(torch.tanh(self.conv1(x)), 2)
        out = F.max_pool2d(torch.tanh(self.conv2(out)), 2)
        out = out.view(-1, 16 * 8 * 8)
        out = torch.tanh(self.fc1(out))
        out = self.fc2(out)
        return out
Run Code Online (Sandbox Code Playgroud)

我们看到模型接受输入 2.d。带有3通道的图像和:

  • Conv2d -> 将其发送到具有 32 个通道的相同大小的图像
  • max_pool2d(,2) -> 将每个维度的图像大小减半
  • Conv2d -> 将其发送到具有 16 个通道的相同大小的图像
  • max_pool2d(,2) -> 将每个维度的图像大小减半
  • view -> 重塑形象
  • Linear-> 获取一个大小的张量16 * 8 * 8并发送到大小32
  • ...

因此,向后工作,我们有:

  • 形状张量 16 * 8 * 8
  • 未重塑形状(通道 x 高度 x 宽度)
  • un-max_pooled 在 2d 中,因子为 2,所以高度和宽度减半
  • 从 16 个通道未卷积到 32 个
    假设:产品中可能有 16 个因此指的是通道数,并且看到的图像view形状为 (channels, 8,8),当前为 (channels, 16, 16) 2
  • un-max_pooled 在 2d 中,因子为 2,因此高度和宽度再次减半(通道,32,32)
  • 从 32 个通道未卷积到 3 个

因此,假设 kernel_size 和 padding 足以使卷积本身保持图像尺寸,则输入图像的形状很可能是 (3,32,32),即 RGB 32x32 像素方形图像。


笔记:

  1. 甚至外部包也pytorch-summary要求您提供输入形状以显示每一层的输出形状。

  2. 然而,它可以是产生等于 8*8 的任何 2 个数字,例如 (64,1)、(32,2)、(16,4) 等,但是由于代码被编写为 8*8,因此作者很可能使用了实际的方面。