【问题标题】:Changing input dimension for AlexNet更改 AlexNet 的输入维度
【发布时间】:2019-09-12 14:33:19
【问题描述】:

我是初学者,我正在尝试实现 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 的网络。

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

【问题讨论】:

    标签: conv-neural-network transfer-learning


    【解决方案1】:

    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)
    

    迁移学习

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

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

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

    实现

    除了Alexnet,Facebook 团队已经提供了很多 ImageNet 上的预训练模型,例如 ResNet、VGG。

    为了在模型大小方面最符合您的要求,最好使用 VGG11 和模型家族中参数最少的 ResNet。

    我只是以VGG11为例:

    1. torchvision 获取预训练模型。
    2. 冻结此模型的所有参数。
    3. 用新的Linear 层替换模型中的最后一层以执行分类。这意味着您可以重用 MM' 的所有大部分内容。
    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 包版本中,没有self.avgpool = nn.AdaptiveAvgPool2d((size, size)),这使得我们的输入大小更难训练,这与训练 ImageNet 中使用的[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.
    

    torchvision.models尝试不同的模型。

    【讨论】:

      猜你喜欢
      • 2017-05-08
      • 2020-01-11
      • 1970-01-01
      • 2020-03-09
      • 1970-01-01
      • 2017-02-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多