给出一个维度为pytorch
的输入数据集:
dat.shape = torch.Size([128, 3, 64, 64])
这是一个监督学习问题:对于每个输入观察,我们都有一个单独的labels.txt
文件,其中包含C
类之一。 C
的值是由labeles文件中不同值的数量计算出来的,目前以一位数字表示。
我可以在如何对执行多类分类的卷积和线性图层网络的简单混合的图层进行网格化方面提供帮助。目的是要通过:
这是我(故障/断开)网络的核心。我无法确定所需的正确尺寸/形状:
Output of Convolutional layer -> Input of Linear [Readout] layer
class CNNClassifier(torch.nn.Module):
def __init__(self):
super().__init__()
self.conv1 = nn.Conv2d(3, 16, 3)
self.maxpool = nn.MaxPool2d(kernel_size=3,padding=1)
self.conv2 = nn.Conv2d(16, 32, 3)
self.linear1 = nn.Linear(32*16*16, C)
self.softmax1 = nn.LogSoftmax(dim=1)
def forward(self, x):
x = self.conv1(x)
x = self.maxpool(F.leaky_relu(x))
x = self.conv2(x)
x = self.maxpool(F.leaky_relu(x))
x = self.linear1(x) # Size mismatch error HERE
x = self.softmax1(x)
return x
模型的培训始于:
Xout = model(dat)
结果为:
在RuntimeError:大小不匹配,m1:[128 x 1568],m2:[8192 x 6]
linear1
输入中输入。这里需要什么?请注意,我已经看到了通配符输入大小的用法,例如通过view
:
..
x = x.view(x.size(0), -1)
x = self.linear1(x) # Size mismatch error HERE
如果包含该内容,则错误更改为
RuntimeError:大小不匹配,m1:[28672 x 7],m2:[8192 x 6]
对于如何思考和计算cnn层/线性层输入/输出大小的一些指示将不胜感激。
答案 0 :(得分:2)
您已经错误地计算了卷积堆栈的输出大小。实际上是[batch, 32, 7, 7]
而不是[batch, 32, 16, 16]
。
您必须使用reshape
(或view
),因为Conv2d
的输出具有4个维度([batch, channels, width, height]
),而nn.Linear
的输入则需要有2个维度([batch, features]
)。
将此用于nn.Linear
:
self.linear1 = nn.Linear(32 * 7 * 7, C)
这在forward
中:
x = self.linear1(x.view(x.shape[0], -1))
当前的新体系结构使用跨渠道的池化(通常称为全局池化)。在PyTorch中有一个torch.nn.AdaptiveAvgPool2d
(或Max
池)。使用此方法可以使输入图像的高度和宽度大小可变,因为每个通道仅一个值用作nn.Linear
的输入。看起来是这样:
class CNNClassifier(torch.nn.Module):
def __init__(self, C=10):
super().__init__()
self.conv1 = nn.Conv2d(3, 16, 3)
self.maxpool = nn.MaxPool2d(kernel_size=3, padding=1)
self.conv2 = nn.Conv2d(16, 32, 3)
self.pooling = torch.nn.AdaptiveAvgPool2d(output_size=1)
self.linear1 = nn.Linear(32, C)
self.softmax1 = nn.LogSoftmax(dim=1)
def forward(self, x):
x = self.conv1(x)
x = self.maxpool(F.leaky_relu(x))
x = self.conv2(x)
x = self.maxpool(F.leaky_relu(x))
x = self.linear1(self.pooling(x).view(x.shape[0], -1))
x = self.softmax1(x)
return x
因此现在torch.Size([128, 3, 64, 64])
和torch.Size([128, 3, 128, 128])
的图像可以传递到网络了。
答案 1 :(得分:2)
问题在于您定义nn.Linear
的方式。您将输入大小设置为32*16*16
,它不是输出图像的形状,但是数字32
/ 16
代表Conv2d
期望的“通道”暗淡的数量输入和输出内容。
如果您要在完全连接的层的入口之前添加print(x.shape)
,则会得到:
torch.Size([Batch, 32, 7, 7])
所以您的计算应该是7*7*32
:
self.linear1 = nn.Linear(32*7*7, C)
然后使用:
x = x.view(x.size(0), -1)
x = self.linear1(x)
可以正常工作。您可以在How does the "view" method work in PyTorch?
中了解view
的用途。