微调(fine tuning)
是计算机视觉中非常重要的一种技术。
微调的作用:
- 让在大数据集上训练得到的模型,能够提高在小数据集上任务的精度(例如用ImageNet上训练的模型去识别热狗数据集)
- 微调是
迁移学习(transfer learning)
中的一种技术,将从 源数据集 学到的知识迁移到 目标数据集
计算机视觉中的深度神经网络,可以视为两个部分:
- 特征抽取:将原始像素变成容易线性分割的特征
- 输出层:线性分类器来做分类
微调的步骤
微调包含4个步骤:
- 在源数据集上预训练神经网络,即源网络
- 创建一个新的神经网络模型,即目标模型。将源模型
除输出层之外的设计和架构
复制到目标模型上。- 源数据集和目标数据集应该是类似的
- 源数据集在数量、类别上最好大于目标数据集
- 当目标数据集比源数据集小得多时,微调有助于提高模型的泛化能力
- 添加输出层,输出数量为目标数据集的类别数,随机初始化该层。
- 在目标数据集上训练目标模型。
- 微调部分的学习率小
- 输出层的学习率大
# 微调部分:特征抽取
finetune_net = torchvision.models.resnet18(pretrained=True)
# 新的输出层,类别为目标数据集的类别(例如:热狗二分类)
finetune_net.fc = nn.Linear(finetune_net.fc.in_features, 2)
# 输出层随机初始化参数
nn.init.xavier_uniform_(finetune_net.fc.weight);
# 如果param_group=True,输出层中的模型参数将使用十倍的学习率
def train_fine_tuning(net, learning_rate, batch_size=128, num_epochs=5,param_group=True):train_iter = torch.utils.data.DataLoader(torchvision.datasets.ImageFolder(os.path.join(data_dir, 'train'), transform=train_augs),batch_size=batch_size, shuffle=True)test_iter = torch.utils.data.DataLoader(torchvision.datasets.ImageFolder(os.path.join(data_dir, 'test'), transform=test_augs),batch_size=batch_size)devices = d2l.try_all_gpus()loss = nn.CrossEntropyLoss(reduction="none")if param_group:params_1x = [param for name, param in net.named_parameters()if name not in ["fc.weight", "fc.bias"]]# 输出层中的模型参数将使用十倍的学习率trainer = torch.optim.SGD([{'params': params_1x},{'params': net.fc.parameters(),'lr': learning_rate * 10}],lr=learning_rate, weight_decay=0.001)else:trainer = torch.optim.SGD(net.parameters(), lr=learning_rate,weight_decay=0.001)d2l.train_ch13(net, train_iter, test_iter, loss, trainer, num_epochs,devices)
微调可以视为一种正则化:
- 使用更小的学习率
- 使用更少的数据迭代
更多的微调技术
- 如果源数据集中的部分类别和目标数据集中的相同,可以提取 源模型的输出层中的相关部分 来初始化目标模型的输出层。
- 神经网络通常学习有层次的特征表示,可以固定底部的一些层(更强的正则)。
- 低层次的特征更通用(简答的图形)
- 高层次的特征更和数据集相关(语义信息)