0 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
Run Code Online (Sandbox Code Playgroud)
但是,我正在尝试为输入大小为 (3,448,224) 的网络实现类数 = 8。
我不知道如何在 forward 方法中更改 x.view 以及我应该删除多少层以获得最佳性能。请帮忙。
如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)
Run Code Online (Sandbox Code Playgroud)
有两种流行的方法可以进行迁移学习。假设我们M在非常大的数据集上训练了一个模型D_large,现在我们想将模型学到的“知识”转移M到我们的新模型中M',在其他数据集上,例如D_other(其大小小于D_large)。
使用 的(大部分)部分M作为我们新的架构,M'并使用在 上训练的权重初始化这些部分D_large。我们可以开始M'在数据集上训练模型D_other,让它学习上述部分的权重,M以在我们的新数据集上找到最佳权重。这通常称为模型微调M'。
与上述方法相同,除了在训练之前M'我们冻结这些部分的所有参数并开始M'对我们的数据集进行训练D_other。在这两种情况下,这些零件M大多是模型中的第一个组件M'(基础)。然而,在这种情况下,我们在向后传递期间参考那些部分。这提高了训练速度并减少了训练过程中所需的内存。M称为从输入数据集(或特征提取器)中提取特征的模型。两种方法获得的准确度可能会有所不同。但是,这种方法可以保证模型不会在小数据集上过拟合。就准确性而言,这是一个好点。另一方面,当我们冻结 的权重时M,我们不需要在前向传递中存储一些中间值(每个隐藏层的隐藏输出),也不需要计算gradients
除了Alexnet,许多 ImageNet 上的预训练模型已经由 Facebook 团队提供,例如 ResNet、VGG。
为了在模型大小方面最符合您的要求,最好使用 VGG11 和 ResNet,它们的模型系列中参数最少。
我只是以 VGG11 为例:
torchvision。Linear层替换模型中的最后一层以执行分类。这意味着您可以重用Mto 的几乎所有内容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
Run Code Online (Sandbox Code Playgroud)
在旧的torchvision包版本中,没有self.avgpool = nn.AdaptiveAvgPool2d((size, size))哪个更难训练我们的输入大小,这与[3, 224, 224]训练 ImageNet 中使用的不同。你可以做一点努力,如下所示:
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.
Run Code Online (Sandbox Code Playgroud)
在torchvision.models.