Fine Tune

Concept and Principle

  • 一般神经网络的架构都分为两块:

    • 特征抽取部分
    • 线性分类部分
  • 微调

    • 一个模型特征提取部分可以作为上游模型训练其他任务

    • pre-train的过程一般是一个大数据集上的正常训练任务,而在fine-tune的过程中使用更强的正则化、更小的学习率、更少的epoch

    • 原数据集和目标数据集要相似,且原数据集比目标数据集要大

  • 微调的一些技巧

    • 重用分类器权重:原数据集中也可能有下游任务数据的部分标号,可以用预训练模型分类器中对应标号的对应向量来初始化下游任务分类部分
    • 固定前面的层:神经网络中靠近输入的层更加通用,可以固定底部的一些层的参数不参与更新
    • 对于个人或小企业来说,通常不会从头开始训练模型,而是进行微调

Implementation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
from torchvision import models,transforms
from torch import nn,optim
import torch
import d2l

train_iter,test_iter=d2l.load_data_fashion_mnist(64)

train_aug=transforms.Compose([
transforms.Resize((224,224)),
transforms.RandomHorizontalFlip(),
# transforms.ToTensor(), #在load时已经将PIL转化为了Tensor
transforms.Normalize([0.485,0.456,0.406],[0.229,0.224,0.225]),

])

test_aug=transforms.Compose([
transforms.Resize((224,224)),
# transforms.ToTensor(),
transforms.Normalize([0.485,0.456,0.406],[0.229,0.224,0.225])
])


# 指定预训练模型
finetune_res=models.resnet18(pretrained=True,progress=True)
# 将分类器部分重新设计,in_features属性记录了原模型的本层的输入特征数
finetune_res.fc=nn.Linear(finetune_res.fc.in_features,10)
# 初始化新分类器参数
nn.init.xavier_uniform_(finetune_res.fc.weight)

loss_f=nn.CrossEntropyLoss()
# 增加正则化并且学习率应该设得很小
opt=optim.Adam(finetune_res.parameters(),weight_decay=0.1,lr=5e-5)

# 不需要迭代很多轮
d2l.train(
5,loss_f,opt,finetune_res,train_iter,
save_name="res18_pretrained",device=torch.device("cuda:0"),
aug=train_aug
)