更改AlexNet的输入尺寸

时间:2019-04-23 11:54:32

标签: conv-neural-network transfer-learning

我是初学者,我正在尝试实现AlexNet进行图像分类。 AlexNet的pytorch实现如下:


class AlexNet(nn.Module):

    def __init__(self, num_classes=1000):
        super(AlexNet, self).__init__()
        self.features = nn.Sequential(
            nn.Conv2d(3, 64, kernel_size=11, stride=4, padding=2),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3, stride=2),
            nn.Conv2d(64, 192, kernel_size=5, padding=2),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3, stride=2),
            nn.Conv2d(192, 384, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv2d(384, 256, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv2d(256, 256, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3, stride=2),
        )
        self.avgpool = nn.AdaptiveAvgPool2d((6, 6))
        self.classifier = nn.Sequential(
            nn.Dropout(),
            nn.Linear(256 * 6 * 6, 4096),
            nn.ReLU(inplace=True),
            nn.Dropout(),
            nn.Linear(4096, 4096),
            nn.ReLU(inplace=True),
            nn.Linear(4096, num_classes),
        )

    def forward(self, x):
        x = self.features(x)
        x = self.avgpool(x)
        x = x.view(x.size(0), 256 * 6 * 6)
        x = self.classifier(x)
        return x

但是,我正在尝试为输入大小为(3,448,224),类别数= 8的情况实现网络。

我不知道如何在正向方法中更改x.view以及应该降低多少层以获得最佳性能。请帮忙。

1 个答案:

答案 0 :(得分:0)

https://github.com/pytorch/vision/releases中所述:

  

因此,torchvision(最新版本)中提供的大多数经过预训练的模型已经添加了self.avgpool = nn.AdaptiveAvgPool2d((size, size)),以解决与输入大小的不兼容问题。因此,您不必太在乎它。

下面是代码,非常简短。

import torchvision
import torch.nn as nn

num_classes = 8
model = torchvision.models.alexnet(pretrained=True)
# replace the last classifier
model.classifier[6] = nn.Linear(4096, num_classes)

# now you can trained it with your dataset of size (3, 448, 224)

转移学习

有两种流行的方法可以进行迁移学习。假设我们在非常大的数据集M中训练了模型D_large,现在我们想将模型M学到的“知识”转移到我们的新模型M'中,例如D_other(其大小比D_large小)的其他数据集。

  1. 使用M的(大部分)部分作为新M'的体系结构,并使用在D_large上训练的权重初始化这些部分。我们可以开始在数据集M'上训练模型D_other,并让其从M学习上述部分的权重,以在新数据集上找到最佳权重。这通常称为微调模型M'

  2. 与上述方法相同,除了在训练M'之前冻结那些部分的所有参数,然后开始在数据集M'上训练D_other。在这两种情况下,M中的那些部分大部分都是模型M'(基础)中的第一部分。但是,在这种情况下,我们将M的那些部分作为模型来从输入数据集(或特征提取器)中提取特征。从这两种方法获得的精度可能会有所不同。但是,此方法可确保模型不会在小型数据集上过拟合。就准确性而言,这是一个很好的观点。另一方面,当冻结M的权重时,我们不需要在前向传递中存储一些中间值(每个隐藏层的隐藏输出),也不需要计算{ {1}}。这样可以提高训练速度并减少训练过程中所需的内存。

实施

gradients一起,Facebook团队已经在ImageNet上提供了许多预训练的模型,例如ResNet,VGG。

要在模型尺寸方面最满足您的要求,最好使用模型系列中参数最少的VGG11和ResNet。

我仅以VGG11为例:

  1. Alexnet获取预训练的模型。
  2. 冻结此模型的所有参数。
  3. 用新的torchvision层替换模型中的最后一层以执行分类。这意味着您可以重用LinearM的大部分内容。
M'

警告

在旧的import torchvision # obtain the pretrained model model = torchvision.models.vgg11(pretrained=True) # freeze the params for param in net.parameters(): param.requires_grad = False # replace with your classifier num_classes = 8 net.classifier[6] = nn.Linear(in_features=4096, out_features=num_classes) # start training with your dataset 软件包版本中,没有torchvision使得难以训练我们的输入大小,这与训练ImageNet中使用的self.avgpool = nn.AdaptiveAvgPool2d((size, size))不同。您可以做一些事情,如下所示:

[3, 224, 224]

class OurVGG11(nn.Module): def __init__(self, num_classes=8): super(OurVGG11, self).__init__() self.vgg11 = torchvision.models.vgg11(pretrained=True) for param in self.vgg11.parameters(): param.requires_grad = False # Add a avgpool here self.avgpool = nn.AdaptiveAvgPool2d((7, 7)) # Replace the classifier layer self.vgg11.classifier[-1] = nn.Linear(4096, num_classes) def forward(self, x): x = self.vgg11.features(x) x = self.avgpool(x) x = x.view(x.size(0), 512 * 7 * 7) x = self.vgg11.classifier(x) return x model = OurVGG11() # now start training `model` on our dataset. 中尝试使用不同的模型。