如何在 PyTorch 中为预训练模型添加层?

时间:2021-05-13 06:41:23

标签: python deep-learning pytorch

我想在 layer normalization 层之后添加 AdaptiveAvgPool2d 函数,在 L2 normalization 之后添加 fc layer。我希望我的 fc layer 输出为 200,所以尝试不包含 fc 层而不是它创建新的 fc layer,但它没有删除 fc layers 带有预训练模型,我正在使用 {{ 1}}。

我的代码:

googlenet

我得到的输出:

class GoogleNet(nn.Module):
    def __init__(self):
        super(GoogleNet,self).__init__()
        self.model = googlenet_pytorch.GoogLeNet.from_pretrained('googlenet')
        
        self.fc = nn.Linear(1024,200, bias=False),
        
    def forward(self, x):
        batch_size ,_,_,_ =x.shape
        x = self.model.extract_features(x)
        x = self.model._avg_pooling(x)
        x = F.layer_norm(x,x.size[1:],elementwise_affine=False)
        x = self.fc(x)
        x = F.normalize(x, p=2, dim=1)
        return x

我想要的输出:

      .....  
      .....  
      .....

(aux1): InceptionAux(
      (conv): BasicConv2d(
        (conv): Conv2d(512, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (bn): BatchNorm2d(128, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)
      )
      (fc1): Linear(in_features=2048, out_features=1024, bias=True)
      (fc2): Linear(in_features=1024, out_features=1000, bias=True)
    )
    (aux2): InceptionAux(
      (conv): BasicConv2d(
        (conv): Conv2d(528, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (bn): BatchNorm2d(128, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)
      )
      (fc1): Linear(in_features=2048, out_features=1024, bias=True)
      (fc2): Linear(in_features=1024, out_features=1000, bias=True)
    )
    (avgpool): AdaptiveAvgPool2d(output_size=(1, 1))
    (dropout): Dropout(p=0.2, inplace=False)
    (fc): Linear(in_features=1024, out_features=1000, bias=True)
  )
)

如果有人需要知道这个问题的解决代码,在iacob的回答的帮助下我解决了,我把它添加为an answer

3 个答案:

答案 0 :(得分:1)

在打印模型时,PyTorch 将打印每一层,直到在 forward 中遇到错误,而不管模型是否会运行(在适当格式化的输入数据上)。

在加载主干 GoogLeNet 模型后,您的代码中存在许多问题,因此您在此之后添加的所有层在打印时都无法显示。显而易见的问题是:

  • 您必须删除 , 之后的 self.fc = nn.Linear(1024,200, bias=False), 否则它将被解释为 tuple
  • GoogLeNet 没有属性 _avg_pooling
  • x.size 不可下标。使用函数调用 x.size()[1:] 或使用 x.shape[1:]
  • F.layer_norm() 没有参数 elementwise_affine

您需要更正这些以使模型运行,like so

答案 1 :(得分:1)

根据@iacob对代码进行更正后,我解决了问题。

正确的代码:

class GoogleNet(nn.Module):
    def __init__(self):
        super(GoogleNet,self).__init__()
        self.model = googlenet_pytorch.GoogLeNet.from_pretrained('googlenet')
        self.avgpool = nn.AdaptiveAvgPool2d((1,1))
        self.layernorm = nn.LayerNorm(1024,elementwise_affine=True)
        self._fc = nn.Linear(1024,200, bias=False)
    def forward(self, x):
        batch_size ,_,_,_ =x.shape
        x = self.model.extract_features(x)
        x = self.model.avgpool(x)
        x = x.view(-1, 1024)
        x = self.layernorm(x)
        x = self._fc(x)
        x = F.normalize(x, p=2, dim=1)
        return x

在此之后,我创建了一个 GoogleNet() 实例并将我不需要的层转换为 Identity()。

dep = GoogleNet()
dep.model.aux1 = Identity()
dep.model.aux2 = Identity()
dep.model.avgpool = Identity()
dep.model.dropout = Identity()
dep.model.fc = Identity()

答案 2 :(得分:0)

我认为您可以删除最后一层,然后添加您想要的层。

所以在你的情况下:

class GoogleNet(nn.Module):
    def __init__(self):
        super(GoogleNet,self).__init__()

        # load the original google net
        self.model = googlenet_pytorch.GoogLeNet.from_pretrained('googlenet')
        
        # remove the last two layers (fc and dropout)
        self.model = nn.Sequential(*list(self.model.children())[:-2])
        
        # add your dropout layer
        self.dropout = nn.Dropout(0.2, inplace=False)

        # add your dense layer
        self.fc = nn.Linear(1024, 200, bias=False)
        
    def forward(self, x):
        batch_size, _, _, _ = x.shape

        # I dont know what this does but I'll leave it here
        x = self.model.extract_features(x)
        # but I would add x = self.model(x) instead

        # insert your layer normalization
        x = F.layer_norm(x,x.size[1:],elementwise_affine=False)
        
        # put droput layer back on
        x = self.dropout(x)
        
        x = self.fc(x)

        x = F.normalize(x, p=2, dim=1)

        return x

但请注意,当您打印模型摘要时,它不会向您显示归一化层。它不会打印您在 F. 中使用 forward() 添加的内容,只会打印您在 __init__() 中所做的初始化。