【问题标题】:Pytorch + Residual Network throws unexpected: TypeError: 'NoneType' object is not callablePytorch + Residual Network 抛出意外:TypeError: 'NoneType' object is not callable
【发布时间】:2020-03-09 19:51:41
【问题描述】:

我正在深入深度学习的世界,由于 Python 是我最杰出的编程语言,我决定从 Pytorch 框架入手。在tutorial 之后,我实现了一个 50 层的 ResNet。之后我尝试用更简单的块制作 ResNet-18,如下所示:

class baseBlock(torch.nn.Module):
  expansion = 1
  def __init__(self,input_planes,planes,stride=1,dim_change=None):
    super(baseBlock,self).__init__()
    #Declare convolutional layers with batch norms
    self.conv1 = torch.nn.Conv2d(input_planes, planes, stride=stride, kernel_size=3, padding=1)
    self.bn1   = torch.nn.BatchNorm2d(planes)
    self.conv2 = torch.nn.Conv2d(planes, planes, stride=1, kernel_size=3, padding=1)
    self.bn2   = torch.nn.BatchNorm2d(planes)
    self.dim_change = dim_change

  def forward(self,x):
    #Save the residue
    res = x
    output = F.relu(self.bn1(self.conv1(x)))
    output = self.bn2(self.conv2(output))

    if self.dim_change is not None:
      res = self.dim_change(res)

    output += res
    output = F.relu(output)

    return output

我将代码分为块和实际的神经网络,以使其更易于理解。 NN 的其余代码是:

class ResNet(torch.nn.Module):
  def __init__(self,block,num_layers,classes=10):
    super(ResNet,self).__init__()
    #according to research paper
    self.input_planes = 64
    self.conv1  = torch.nn.Conv2d(3,64,kernel_size =3,stride=1,padding=1)
    self.bn1    = torch.nn.BatchNorm2d(64)
    self.layer1 = self._layer(block, 64, num_layers[0], stride=1)
    self.layer2 = self._layer(block, 128, num_layers[1], stride=2)
    self.layer3 = self._layer(block, 256, num_layers[2], stride=2)
    self.layer4 = self._layer(block, 512, num_layers[3], stride=2)
    self.avaragePool = torch.nn.AvgPool2d(kernel_size=4,stride=1)
    self.fc = torch.nn.Linear(512*block.expansion, classes)


  def _layer(self,block,planes,num_layers,stride=1):
    dim_change = None
    if stride != 1 or planes != self.input_planes*block.expansion:
      dim_change = torch.nn.Sequential(torch.nn.Conv2d(self.input_planes, planes*block.expansion, kernel_size = 1, stride=stride),
                                                        torch.nn.BatchNorm2d(planes*block.expansion))
      netLayers = []
      netLayers.append(block(self.input_planes,planes,stride=stride, dim_change=dim_change))

      self.input_planes = planes*block.expansion

      for i in range(1,num_layers):
        netLayers.append(block(self.input_planes,planes))
        self.input_planes = planes * block.expansion

      return torch.nn.Sequential(*netLayers)


  def forward(self,x):
    x = F.relu(self.bn1(self.conv1(x)))

    #Problem at this layer
    x = self.layer1(x) <- NoneType object is not callable
    x = self.layer2(x)
    x = self.layer3(x)
    x = self.layer4(x)

    x = F.avg_pool2d(x,4)
    x = x.view(x.size(0),-1)
    x = self.fc(x)

    return x

问题出现在代码上标记的 layer1 中的最后一个 forward 函数上。如果我评论它,网络会继续计算(显然它稍后会引发错误,因为尺寸不正确但它仍然会做一些事情)。如果我在第一层更改步幅,问题也会解决,但由于相同的维度原因,稍后仍会引发错误。我似乎没有弄清楚问题是什么。我使用标准的 CIFAR10 数据集对其进行训练,并且训练代码尽可能标准。

如果我可以提供任何其他信息,请告诉我。谢谢

【问题讨论】:

    标签: python deep-learning conv-neural-network pytorch resnet


    【解决方案1】:

    这是一个简单的错字。你的returnif 内,而stride==1 的唯一层是layer1

    def _layer(self,block,planes,num_layers,stride=1):
        dim_change = None
        if stride != 1 or planes != self.input_planes*block.expansion:
            # [...]
            return torch.nn.Sequential(*netLayers)
    

    因此,对于layer1,没有return,因此没有None

    【讨论】:

    • 你是对的,我正在寻找一个更复杂的错误并错过了这个缩进错误。这个问题可以被认为已经解决,但我仍然有一个相关的问题。我无法理解 *netLayers 的使用以及如何使用它。我通过在 if 语句后添加这段代码解决了这个问题:else: netLayers = [] netLayers.append(block(self.input_planes,planes)) return torch.nn.Sequential(*netLayers) 网络训练,损失函数下降,准确性上升,但我想知道为什么会这样。感谢您的宝贵时间。
    • @CarlosHernandezPerez 对不起,但我没有得到问题。你不了解星运营商还是别的什么?评论不适用于此类事情,但也许我可以告诉您是否值得提出另一个问题。
    • 我将在这里停止提问,因为再花几个小时的编码会给我答案。您的回复很有帮助,谢谢。
    猜你喜欢
    • 2021-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-25
    • 2014-11-16
    • 2018-03-31
    • 2021-10-22
    相关资源
    最近更新 更多