1.在两个数据集相似度较高的情况下,使用预训练模型可以不冻结,如果目标数据集与预训练数据集相似,那么卷积层所学习的低级特征通常是共享的,不会因为任务差异而需要大幅度改变。因此,微调(即对所有层进行训练)不会引起特征表示的显著改变,反而可以帮助模型更好地学习任务相关的细节,不冻结任何层可以让模型有更大的灵活性来调整每一层的权重,最终能更好地适应目标任务。
经过实验证明,确实不冻结的精度更高一些。
2.冻结的话,一般冻结前面几层,微调后面几层。以resnet18为例:
# 冻结部分层
class ResNet_18(nn.Module):
def __init__(self, num_classes=7):
super(ResNet_18, self).__init__()
ResNet18 = torchvision.models.resnet18(pretrained=False)
# 加载预训练权重
checkpoint = torch.load('')
ResNet18.load_state_dict(checkpoint['state_dict'], strict=True)
# 去掉最后两个层:全连接层和全局平均池化
self.base = nn.Sequential(*list(ResNet18.children())[:-2])
# 处理输出
self.output = nn.Sequential(nn.Dropout(0.5), Flatten())
self.classifier = nn.Linear(512, num_classes)
# 冻结部分层,默认冻结 ResNet-18 的卷积层和残差块
for param in self.base.parameters():
param.requires_grad = False
# 如果你希望仅冻结到某一层,类似下面这样:
# for name, param in self.base.named_parameters():
# if 'layer4' not in name: # 只训练最后的 layer4 层及其后的层
# param.requires_grad = False
def forward(self, image):
feature_map = self.base(image)
feature_map = F.avg_pool2d(feature_map, feature_map.size()[2:])
feature = self.output(feature_map)
feature = F.normalize(feature, dim=1)
out = self.classifier(feature)
return out, feature