Python 如何使用PyTorch在预先训练的模型上添加新层?(给出了一个示例。)
我正在使用Python 如何使用PyTorch在预先训练的模型上添加新层?(给出了一个示例。),python,keras,pytorch,vgg-net,pre-trained-model,Python,Keras,Pytorch,Vgg Net,Pre Trained Model,我正在使用Keras并试图分析使用具有有意义权重的层和随机初始化的层构建的模型对精度的影响 凯拉斯: 我加载VGG19带有include\u top=False的预训练模型加载方法参数 model=keras.applications.VGG19(包括\u top=False,weights=“imagenet”,输入\u shape=(img\u宽度,img\u高度,3)) Pytork: 我加载VGG19预训练模型,直到与加载KERA的前一个模型相同的层 model=torch.hub.l
Keras
并试图分析使用具有有意义权重的层和随机初始化的层构建的模型对精度的影响
凯拉斯:
我加载VGG19
带有include\u top=False的预训练模型
加载方法参数
model=keras.applications.VGG19(包括\u top=False,weights=“imagenet”,输入\u shape=(img\u宽度,img\u高度,3))
Pytork:
我加载VGG19
预训练模型,直到与加载KERA的前一个模型相同的层
model=torch.hub.load('pytorch/vision:v0.6.0','vgg19',pretrained=True)
new_base=(list(model.children())[:-2])[0]
加载模型后,下图显示了这些模型的摘要。(Pytorch
,Keras
)
到目前为止没有问题。之后,我想在这些预先训练好的模型上添加一个展平层和一个完全连接的层。我和Keras一起做的,但我不能和PyTorch一起做
new_model.summary()的输出为:
我的问题是,我如何在
PyTorch
中添加一个新层?如果您只想替换分类器部分,您只需这样做即可。即:
model=torch.hub.load('pytorch/vision:v0.6.0','vgg19',pretrained=True)
model.classifier=nn.Linear(model.classifier[0]。in_特征,4096)
打印(模型)
将为您提供:
之前:
VGG(
(features): Sequential(
(0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(1): ReLU(inplace=True)
(2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(3): ReLU(inplace=True)
(4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(5): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(6): ReLU(inplace=True)
(7): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(8): ReLU(inplace=True)
(9): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(10): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(11): ReLU(inplace=True)
(12): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(13): ReLU(inplace=True)
(14): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(15): ReLU(inplace=True)
(16): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(17): ReLU(inplace=True)
(18): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(19): Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(20): ReLU(inplace=True)
(21): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(22): ReLU(inplace=True)
(23): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(24): ReLU(inplace=True)
(25): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(26): ReLU(inplace=True)
(27): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(28): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(29): ReLU(inplace=True)
(30): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(31): ReLU(inplace=True)
(32): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(33): ReLU(inplace=True)
(34): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(35): ReLU(inplace=True)
(36): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
)
(avgpool): AdaptiveAvgPool2d(output_size=(7, 7))
(classifier): Sequential(
(0): Linear(in_features=25088, out_features=4096, bias=True)
(1): ReLU(inplace=True)
(2): Dropout(p=0.5, inplace=False)
(3): Linear(in_features=4096, out_features=4096, bias=True)
(4): ReLU(inplace=True)
(5): Dropout(p=0.5, inplace=False)
(6): Linear(in_features=4096, out_features=1000, bias=True)
)
)
之后:
VGG(
(features): Sequential(
(0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(1): ReLU(inplace=True)
(2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(3): ReLU(inplace=True)
(4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(5): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(6): ReLU(inplace=True)
(7): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(8): ReLU(inplace=True)
(9): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(10): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(11): ReLU(inplace=True)
(12): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(13): ReLU(inplace=True)
(14): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(15): ReLU(inplace=True)
(16): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(17): ReLU(inplace=True)
(18): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(19): Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(20): ReLU(inplace=True)
(21): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(22): ReLU(inplace=True)
(23): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(24): ReLU(inplace=True)
(25): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(26): ReLU(inplace=True)
(27): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(28): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(29): ReLU(inplace=True)
(30): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(31): ReLU(inplace=True)
(32): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(33): ReLU(inplace=True)
(34): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(35): ReLU(inplace=True)
(36): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
)
(avgpool): AdaptiveAvgPool2d(output_size=(7, 7))
(classifier): Linear(in_features=25088, out_features=4096, bias=True)
)
还要注意,当您想要改变现有的体系结构时,您有两个阶段。您首先获得所需的模块(这就是您在那里所做的),然后必须将其包装为nn.Sequential
,因为您的列表没有实现forward()
,因此您无法真正向其提供任何信息。它只是一个模块的集合
因此,一般来说,您需要这样做(例如):
features=nn.ModuleList(您的_model.children())[:-1]
模型=nn.顺序(*特征)
#继续进行您希望在模型上执行的其他更改
请注意,如果要创建一个新模型,并打算像以下那样使用它:
output = model(imgs)
您需要以第二种顺序包装功能和新图层。也就是说,像这样做:
features=nn.ModuleList(您的_model.children())[:-1]
模型特征=nn.顺序(*特征)
一些或更多层=nn.顺序(第1层,
第二层,
... )
模型=nn.顺序(模型特征,
一些(更多层)
#
输出=模型(imgs)
否则,您必须执行以下操作:
features\u output=model.features(imgs)
输出=模型分类器(特征\输出)
来自PyTorch教程:
Torchvision提供了八种不同长度的VGG版本,其中一些具有批量规格化层。这里我们使用VGG-11进行批处理规范化。输出层类似于Alexnet,即
(分类器):顺序(
...
(6) :线性(输入特征=4096,输出特征=1000,偏差=True)
)
因此,我们使用相同的技术来修改输出层
model.classifier[6]=nn.Linear(4096,num_类)
new_base.add_模块?这是否回答了您的问题?实际上我不想使用模型作为分类器,我将使用模型作为特征提取器,我需要为每个图像(从第一个FC层)提取(14096)特征向量。另一方面,当我这样做时,我想添加没有有意义权重的FC层(不属于imagenet),FC层应该具有PyTorch中定义的默认权重。例如,在Keras中添加在模型上的FC层具有使用He_初始化而不是imagenet初始化的权重。我没有说你想将其用作分类器,我说,如果你想替换分类器,它很容易。如果您需要分类器之前的功能,只需使用
model.features
。如果你需要添加一个新的图层,就按照我的方法来做。只需添加一个新层。其权重未初始化。有关图层初始化,请参见。请参阅我的最新更新。