Pytorch + Residual Network throws unexpected: TypeError: 'NoneType' object is not callable
Pytorch + Residual Network throws unexpected: TypeError: 'NoneType' object is not callable
我正在深入学习深度学习的世界,由于 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最后一个前向函数上,也就是代码上标注的。如果我评论它,网络会继续计算(显然它稍后会抛出错误,因为尺寸不正确但它仍然会做一些事情)。如果我改变第一层的步幅,问题也会解决,但由于相同的尺寸原因,稍后仍会抛出错误。我似乎没有弄清楚问题是什么。我使用标准的 CIFAR10 数据集对其进行训练,训练代码是标准的。
如果我可以提供任何其他信息,请告诉我。谢谢
这是一个简单的错字。你的 return
在 if
里面,唯一有 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
。
我正在深入学习深度学习的世界,由于 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最后一个前向函数上,也就是代码上标注的。如果我评论它,网络会继续计算(显然它稍后会抛出错误,因为尺寸不正确但它仍然会做一些事情)。如果我改变第一层的步幅,问题也会解决,但由于相同的尺寸原因,稍后仍会抛出错误。我似乎没有弄清楚问题是什么。我使用标准的 CIFAR10 数据集对其进行训练,训练代码是标准的。
如果我可以提供任何其他信息,请告诉我。谢谢
这是一个简单的错字。你的 return
在 if
里面,唯一有 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
。