Python 如何重构cnn层的输出张量,以供简单pytorch模型中的线性层使用

Python 如何重构cnn层的输出张量,以供简单pytorch模型中的线性层使用,python,deep-learning,pytorch,Python,Deep Learning,Pytorch,给定具有维度的pytorch输入数据集: dat.shape = torch.Size([128, 3, 64, 64]) 这是一个有监督的学习问题:我们有一个单独的labels.txt文件,其中包含每个输入观察的一个C类。C的值由labeles文件中不同值的数量计算得出,目前为个位数 我可以在如何对执行多类分类的卷积层和线性层网络的简单混合层进行网格划分方面提供帮助。目的是通过: 两个cnn层,每个层后面都有maxpooling 线性读出层 输出/标签前的softmax激活 这是我的故障/损

给定具有维度的pytorch输入数据集:

dat.shape = torch.Size([128, 3, 64, 64])
这是一个有监督的学习问题:我们有一个单独的labels.txt文件,其中包含每个输入观察的一个C类。C的值由labeles文件中不同值的数量计算得出,目前为个位数

我可以在如何对执行多类分类的卷积层和线性层网络的简单混合层进行网格划分方面提供帮助。目的是通过:

两个cnn层,每个层后面都有maxpooling 线性读出层 输出/标签前的softmax激活 这是我的故障/损坏网络的核心。我无法确定以下各项所需的适当尺寸/形状:

 Output of Convolutional layer -> Input of Linear [Readout] layer
模型培训由以下人员开始:

        Xout = model(dat)
这导致:

运行时错误:大小不匹配,m1:[128 x 1568],m2:[8192 x 6]

在linear1输入端。这里需要什么?注:我见过通配符输入大小的用法,例如通过视图:

如果包含此项,则错误更改为

运行时错误:大小不匹配,m1:[28672 x 7],m2:[8192 x 6]

对于如何考虑和计算cnn层/线性层输入/输出大小的一些建议,我们将不胜感激。

错误 您错误计算了卷积堆栈的输出大小。它实际上是[batch,32,7,7],而不是[batch,32,16,16]

您必须使用重塑或视图,因为Conv2d的输出有4个维度[批次、通道、宽度、高度],而nn的输入。线性需要有2个维度[批次、特征]

将其用于nn。线性:

在未来:

其他可能性 当前的新体系结构使用跨通道的池,通常称为全局池。在PyTorch中有一个或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]的图像可以传递到网络。

所以问题在于您定义nn.Linear的方式。将输入大小设置为32*16*16,这不是输出图像的形状,但数字32/16表示Conv2d期望输入的通道数及其输出

如果将printx.shape添加到完全连接的层入口之前,您将获得:

torch.Size([Batch, 32, 7, 7])
所以你的计算应该是7*7*32:

然后使用:

x = x.view(x.size(0), -1)
x = self.linear1(x)

会很好用的。您可以在中了解视图的功能:

添加AdaptiveAvgPool2d非常适合具有多个图像大小的情况;我想自己加上去+第1次!对于第一种方法和32x7x7大小,您是否计算过,通过O=W-K+2*P/S+1?@javadba,您可以在PyTorch文档中找到精确的公式。这一次,我刚刚打印了线性之前的形状属性。另外,通常情况下,在Conv中,当kernel_size=3时,使用padding=1,这样形状就保持不变,整个过程就更容易理解了。
x = self.linear1(x.view(x.shape[0], -1))
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([Batch, 32, 7, 7])
self.linear1 = nn.Linear(32*7*7, C)
x = x.view(x.size(0), -1)
x = self.linear1(x)