使用 Pytorch 的 *list、.children() 和 nn.sequential 创建的模型会产生不同的输出张量

Posted

技术标签:

【中文标题】使用 Pytorch 的 *list、.children() 和 nn.sequential 创建的模型会产生不同的输出张量【英文标题】:Model Created With Pytorch's *list, .children(), and nn.sequential Produces Different Output Tensors 【发布时间】:2021-12-10 01:26:51 【问题描述】:

我目前正在尝试在我的模型中使用预训练的 DenseNet。我正在关注本教程:https://pytorch.org/hub/pytorch_vision_densenet/,它运行良好,输入为 [1,3,244,244],它返回一个 [1,1000] 张量,完全符合预期。 但是,目前我正在使用此代码将预训练的 Densenet 加载到我的模型中,并将其用作“特征提取”模型。这是init函数中的代码

base_model = torch.hub.load('pytorch/vision:v0.10.0', 'densenet121', pretrained=True)

self.base_model = nn.Sequential(*list(base_model.children())[:-1])

并且在 forward 函数中就是这样使用的

x = self.base_model(x)

然而,这采用相同的输入,返回一个大小为:([1, 1024, 7, 7]) 的张量。我不知道是什么不工作,我认为这是由于 DenseNet 将所有层连接在一起,但我不知道如何让它以相同的方法工作。关于如何在我自己的模型中使用预训练 DenseNet 的任何提示?

【问题讨论】:

【参考方案1】:

通常nn.Modulesforward 定义中包含逻辑,这意味着仅将模型转换为顺序块就无法访问它。最值得注意的是,您通常会发现 CNN 和网络的分类器层之间发生了下采样和/或扁平化。这是 DenseNet 的。

如果您查看 Torchvision 对 DenseNet here 的前向实现,您会看到:

def forward(self, x: Tensor) -> Tensor:
    features = self.features(x)
    out = F.relu(features, inplace=True)
    out = F.adaptive_avg_pool2d(out, (1, 1))
    out = torch.flatten(out, 1)
    out = self.classifier(out)
    return out

您可以看到 CNN self.features(形状为 (*, 1024, 7, 7))输出的张量如何通过 ReLU、自适应平均池进行处理,并在馈送到分类器(最后一层)之前进行展平。

【讨论】:

以上是关于使用 Pytorch 的 *list、.children() 和 nn.sequential 创建的模型会产生不同的输出张量的主要内容,如果未能解决你的问题,请参考以下文章

在 pytorch 中使用我自己的数据集训练简单的 RNN

PyTorch网络搭建中*list的用法解析

pytorch-获取模型中间结果,*list的含义

PyTorch网络搭建中*list的用法解析

ASP.NET MVC 5 如何在同一视图中编辑 Parent 和 List<> 类型 Child

使用 JPA Hibernate 自动保存子对象