D4 Pytorch进阶训练技巧


1. 自定义损失函数

pytorch教程之损失函数详解——多种定义损失函数的方法


2. 动态调整学习率

如何实现学习率衰减?

  • 使用官方API

PyTorch已经在torch.optim.lr_scheduler为我们封装好了一些动态调整学习率的方法供我们使用
TORCH.OPTIM

  • 自定义scheduler

自定义函数adjust_learning_rate来改变param_grouplr的值,如实现lr每20epoch下降为1/10.

def adjust_learning_rate(optimizer, epoch):
    lr = args.lr * (0.1 ** (epoch // 30))
    for param_group in optimizer.param_groups:
        param_group['lr'] = lr

训练过程调用

def adjust_learning_rate(optimizer,...):
    ...
optimizer = torch.optim.SGD(model.parameters(),lr = args.lr,momentum = 0.9)
for epoch in range(10):
    train(...)
    validate(...)
    adjust_learning_rate(optimizer,epoch)

3. 模型微调-torchvision

迁移学习(transfer learning),将从源数据集学到的知识迁移到目标数据集上。利用在大数据集上训练的模型可以抽取较通用的图像特征,帮助识别边缘、纹理、形状和物体组成等
模型微调(finetune)
在这里插入图片描述

  1. 实例化网络
  2. 传递pretrained参数
import torchvision.models as models
resnet18 = models.resnet18()
  1. 训练特定层
    通过设置requires_grad = False来冻结部分层
def set_parameter_requires_grad(model, feature_extracting):
    if feature_extracting:
        for param in model.parameters():
            param.requires_grad = False

使用resnet18为例的将1000类改为4类,但是仅改变最后一层的模型参数,不改变特征提取的模型参数

import torchvision.models as models
# 冻结参数的梯度
feature_extract = True
model = models.resnet18(pretrained=True)
set_parameter_requires_grad(model, feature_extract)
# 修改模型
num_ftrs = model.fc.in_features
model.fc = nn.Linear(in_features=num_ftrs, out_features=4, bias=True)

训练过程中,model仍会进行梯度回传,但是参数更新则只会发生在fc层。通过设定参数的requires_grad属性。


4. 模型微调-timm

模型微调timm_深入浅出Pytorch


5. 半精度训练

在这里插入图片描述
设置

  1. 导入模块
from torch.cuda.amp import autocast
  1. 在模型定义的forward()函数前使用修饰器autocast.
@autocast()   
def forward(self, x):
    ...
    return x
  1. 训练过程:在数据输入模型前添加with autocast():
 for x in train_loader:
	x = x.cuda()
	with autocast():
        output = model(x)
        ...

6. 数据增强imgaug

数据增强imgaug_深入浅出Pytorch


7. 使用argparse进行调参

  1. 导入包
  2. 利用包中 ArgumentParser 类生成 parse 对象
  3. 通过对象的 add_argument 函数来增加参数
  4. 用对象的 parse_args 获取解析的参数
import argparse
parser = argparse.ArgumentParser(description='')   # 创建ArgumentParser()对象
parser.add_argument("-A", default = "2", type = ...) # 通过对象的 add_argument 函数来增加参数
args = parser.parse_args()  # 获取解析的参数

更高效的使用argparse修改超参数

定义config.py

import argparse  
  
def get_options(parser=argparse.ArgumentParser()):  
  
    parser.add_argument('--workers', type=int, default=0,  
                        help='number of data loading workers, you had better put it '  
                              '4 times of your gpu')  
  
    parser.add_argument('--batch_size', type=int, default=4, help='input batch size, default=64')  
  
    parser.add_argument('--niter', type=int, default=10, help='number of epochs to train for, default=10')  
  
    parser.add_argument('--lr', type=float, default=3e-5, help='select the learning rate, default=1e-3')  
  
    parser.add_argument('--seed', type=int, default=118, help="random seed")  
  
    parser.add_argument('--cuda', action='store_true', default=True, help='enables cuda')  
    parser.add_argument('--checkpoint_path',type=str,default='',  
                        help='Path to load a previous trained model if not empty (default empty)')  
    parser.add_argument('--output',action='store_true',default=True,help="shows output")  
  
    opt = parser.parse_args()  
  
    if opt.output:  
        print(f'num_workers: {opt.workers}')  
        print(f'batch_size: {opt.batch_size}')  
        print(f'epochs (niters) : {opt.niter}')  
        print(f'learning rate : {opt.lr}')  
        print(f'manual_seed: {opt.seed}')  
        print(f'cuda enable: {opt.cuda}')  
        print(f'checkpoint_path: {opt.checkpoint_path}')  
  
    return opt  
  
if __name__ == '__main__':  
    opt = get_options()

train.py中调用

# 导入必要库
...
import config

opt = config.get_options()

manual_seed = opt.seed
num_workers = opt.workers
batch_size = opt.batch_size
lr = opt.lr
niters = opt.niters
checkpoint_path = opt.checkpoint_path

# 随机数的设置,保证复现结果
def set_seed(seed):
    torch.manual_seed(seed)
    torch.cuda.manual_seed_all(seed)
    random.seed(seed)
    np.random.seed(seed)
    torch.backends.cudnn.benchmark = False
    torch.backends.cudnn.deterministic = True

...


if __name__ == '__main__':
	set_seed(manual_seed)
	for epoch in range(niters):
		train(model,lr,batch_size,num_workers,checkpoint_path)
		val(model,lr,batch_size,num_workers,checkpoint_path)


@夏日回

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值