微调(linear probing和 full finetune)技巧

应用场景:图像分类 (使用CIFAR10作为测试数据集,ResNet18作为Backbone网络)

数据预处理 (resize_val = 224, n_holes = 1, length在原有的size=32时候为16)

# Image Preprocessing
normalize = transforms.Normalize(mean=[x / 255.0 for x in [125.3, 123.0, 113.9]],
        std = [x / 255.0 for x in [63.0, 62.1, 66.7]])

train_transform = transforms.Compose([])
if args.resize_val != -1:
    train_transform.transforms.append(transforms.Resize((args.resize_val,args.resize_val)))

train_transform.transforms.append(transforms.RandomCrop(args.resize_val, padding=4))
train_transform.transforms.append(transforms.RandomHorizontalFlip())
train_transform.transforms.append(transforms.ToTensor())
train_transform.transforms.append(normalize)
train_transform.transforms.append(Cutout(n_holes=args.n_holes, length=args.length))


test_transform = transforms.Compose([
    transforms.Resize((args.resize_val,args.resize_val)),
    transforms.ToTensor(),
    normalize])

训练优化器和 lr decay方式 (lr =0.01,wd = 5e-4)

criterion = nn.CrossEntropyLoss()
cnn_optimizer = torch.optim.SGD(cnn.parameters(), lr=args.learning_rate,
                                momentum=0.9, nesterov=True, weight_decay=args.wd)


scheduler = MultiStepLR(cnn_optimizer, milestones=[60, 120, 160], gamma=0.2)

(1)从头训练 (from scratch): 直接按照上面的代码进行训练即可

(2)finetune all (没有冻结任何层)

    cnn.load_state_dict(torch.load(path))
    inchannel = cnn.fc.in_features
    cnn.fc = nn.Linear(inchannel, args.num_class)

注意:

a) 在load_state_dict时候,应该使用默认的 1000 类(因为我用的imagenet1k的预训练参数),加载完后才改变成指定的 args.num_class

b) path指的是预训练的参数的地址:可以使用torchvision上提供好的(为了方便我也粘贴一下)

Resnet18: https://download.pytorch.org/models/resnet18-f37072fd.pth

Resnet34: https://download.pytorch.org/models/resnet34-b627a593.pth

Resnet50: https://download.pytorch.org/models/resnet50-0676ba61.pth

 (3) linear probing (冻结了浅层)

    cnn.load_state_dict(torch.load(path))
    inchannel = cnn.fc.in_features
    cnn.fc = nn.Linear(inchannel, args.num_class)
    for k, v in cnn.named_parameters():
        if k.split('.')[0] != 'fc':
            v.requires_grad = False 

但是linear层的微调性能远不如全部finetune,因为可变的层太少了,对于linear层而言,搞不定。

此外,需要注意的一点,我们若不加 .eval() 那么BN和Dropout是默认开的,训练时候如果浅层不参与训练但开着这些层,会让 fc 层更难。 所以我们可以:

cnn.eval()
cnn.fc.train()

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值