Pytorch使用细节总结

Pytorch保存和加载模型
Pytorch保存和加载模型后缀.pt 和.pth

保存整个模型:

torch.save(model,'save.pt')

只保存训练好的权重:

torch.save(model.state_dict(), 'save.pt')

加载模型:

pretrained_dict = torch.load("save.pt")

只加载模型参数:

model.load_state_dict(torch.load("save.pt"))  #model.load_state_dict()函数把加载的权重复制到模型的权重中去

加载某一层的训练到的参数

conv1_weight_state = torch.load('save.pt')['conv1.weight']

Pytorch:多GPU训练网络与单GPU训练网络保存模型的区别
在pytorch中,使用多GPU训练网络需要用到nn.DataParallel:

gpu_ids = [0, 1, 2, 3]
device = t.device("cuda:0" if t.cuda.is_available() else "cpu")  # 只能单GPU运行
net = LeNet()
if len(gpu_ids) > 1:
    net = nn.DataParallel(net, device_ids=gpu_ids)
net = net.to(device)

而使用单GPU训练网络:

device = t.device("cuda:0" if t.cuda.is_available() else "cpu")  # 只能单GPU运行
net = LeNet().to(device)

由于多GPU训练使用了 nn.DataParallel(net, device_ids=gpu_ids) 对网络进行封装,因此在原始网络结构中添加了一层module。网络结构如下:

LeNet(
  (conv1): Conv2d(3, 6, kernel_size=(5, 5), stride=(1, 1))
  (conv2): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1))
  (fc1): Linear(in_features=400, out_features=120, bias=True)
  (fc2): Linear(in_features=120, out_features=84, bias=True)
  (fc3): Linear(in_features=84, out_features=10, bias=True)
)


而不使用多GPU训练的网络结构如下:

LeNet(
  (conv1): Conv2d(3, 6, kernel_size=(5, 5), stride=(1, 1))
  (conv2): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1))
  (fc1): Linear(in_features=400, out_features=120, bias=True)
  (fc2): Linear(in_features=120, out_features=84, bias=True)
  (fc3): Linear(in_features=84, out_features=10, bias=True)
)


由于在测试模型时不需要用到多GPU测试,因此在保存模型时应该把module层去掉。如下:

if len(gpu_ids) > 1:
    t.save(net.module.state_dict(), "model.pth")
else:
    t.save(net.state_dict(), "model.pth")


pytorch多卡并行计算保存模型和加载模型 (遗漏module的解决)

今天使用了多卡进行训练,保存的时候直接是用了下面的代码:

torch.save(net.cpu().state_dict(),'epoch1.pth')

我在测试的时候,想要加载这个训练好的模型,但是报错了,说是字典中的关键字不匹配,我就将新创建的模型,和加载的模型中的关键字都打印了出来,发现夹杂的模型的每个关键字都多了module.。解决方式为:

pre_dict = torch.load('./epoch1.pth')
new_pre = {}
for k,v in pre_dict.items():
    name = k[7:]
    new_pre[name] = v
net.load_state_dict(new_pre)


这就相当于是把不同的关键字都设置成相同的关键字,也将参数加载了进来。

Pytorch保留验证集上最好的模型
方法一:

验证集的作用就是在训练的过程中监测是否训练过度,即过拟合。一般可以默认验证集的损失函数值由下降转向上升(即最小值)处,模型的泛化能力最好。

min_loss_val = 10  # 任取一个大数
best_model = None
min_epoch = 100  # 训练至少需要的轮数
for epoch in range(args.epochs):
    loss_val, loss_acc = train(epoch)
    if epoch > min_epoch and loss_val <= min_loss_val:
        min_loss_val = loss_val
        best_model = copy.deepcopy(model)
model = best_model


方法二:

在训练过程中,需要保存模型来供测试使用,以前采用隔几个epoch就保存模型:

if epoch % 50 == 0:
   torch.save(net.state_dict(),'%d.pth' % (epoch))

这样会导致保存的模型数量太多,占用硬盘空间,而且训练完成后寻找最优的模型也需要对照损失函数曲线去寻找,很不方便。 但如果每次都记录下损失函数的值,只保存验证集上损失最小的时候的模型,就更方便使用,其实设置一个判断条件就行。

min_loss = 100000 # 随便设置一个比较大的数
for epoch in range(epochs):
    train()
    val_loss = val()
    if val_loss < min_loss:
        min_loss = val_loss
        print("save model")
        torch.save(net.state_dict(),'model.pth')


后来我发现,这种方式也有不科学之处,因为在测试集上损失最小的那个epoch的模型不一定就是最好的模型,不一定具有最好的泛化能力。

PyTorch学习之六个学习率调整策略
PyTorch学习率调整策略通过torch.optim.lr_scheduler接口实现。PyTorch提供的学习率调整策略分为三大类,分别是

a. 有序调整:等间隔调整(Step),按需调整学习率(MultiStep),指数衰减调整(Exponential)和 余弦退火(CosineAnnealing)。
b. 自适应调整:自适应调整学习率 ReduceLROnPlateau。
c. 自定义调整:自定义调整学习率 LambdaLR。
1、 等间隔调整学习率 StepLR

等间隔调整学习率,调整倍数为gamma倍,调整间隔为 step_size。间隔单位是step。需要注意的是,step通常是指epoch,不要弄成iteration 了。

torch.optim.lr_scheduler.StepLR(optimizer, step_size, gamma=0.1, last_epoch=-1)

参数:

step_size(int)- 学习率下降间隔数,若为 30,则会在 30、 60、 90…个 step 时,将学习率调整为 lr*gamma。
gamma(float)- 学习率调整倍数,默认为 0.1 倍,即下降 10 倍。
last_epoch(int)- 上一个 epoch 数,这个变量用来指示学习率是否需要调整。当last_epoch 符合设定的间隔时,就会对学习率进行调整。当为-1 时,学习率设置为初始值。
2 、按需调整学习率 MultiStepLR


按设定的间隔调整学习率。这个方法适合后期调试使用,观察loss 曲线,为每个实验定制学习率调整时机。

torch.optim.lr_scheduler.MultiStepLR(optimizer, milestones, gamma=0.1, last_epoch=-1)

参数:

milestones(list)- 一个 list,每一个元素代表何时调整学习率, list 元素必须是递增的。如 milestones=[30,80,120]
gamma(float)- 学习率调整倍数,默认为 0.1 倍,即下降 10 倍。
3 、指数衰减调整学习率 ExponentialLR


按指数衰减调整学习率,调整公式: lr=lr∗gamma∗∗epoch

torch.optim.lr_scheduler.ExponentialLR(optimizer, gamma, last_epoch=-1)

参数:

gamma- 学习率调整倍数的底,指数为 epoch,即 gamma**epoch
4 、余弦退火调整学习率 CosineAnnealingLR


以余弦函数为周期,并在每个周期最大值时重新设置学习率。以初始学习率为最大学习率,以 2 ∗ T m a x 2∗Tmax2∗Tmax为周期,在一个周期内先下降,后上升。

torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max, eta_min=0, last_epoch=-1)

参数:

T_max(int)- 一次学习率周期的迭代次数,即 T_max 个 epoch 之后重新设置学习率。
eta_min(float)- 最小学习率,即在一个周期中,学习率最小会下降到 eta_min,默认值为 0。


5 、自适应调整学习率 ReduceLROnPlateau
当某指标不再变化(下降或升高),调整学习率,这是非常实用的学习率调整策略。
例如,当验证集的loss不再下降时,进行学习率调整;或者监测验证集的accuracy,当accuracy不再上升时,则调整学习率。

torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0.1, patience=10, verbose=False, threshold=0.0001, threshold_mode='rel', cooldown=0, min_lr=0, eps=1e-08)

参数:

mode(str)- 模式选择,有 min 和 max 两种模式, min 表示当指标不再降低(如监测loss), max 表示当指标不再升高(如监测 accuracy)。
factor(float)- 学习率调整倍数(等同于其它方法的 gamma),即学习率更新为 lr = lr * factor
patience(int)- 忍受该指标多少个 step 不变化,当忍无可忍时,调整学习率。
verbose(bool)- 是否打印学习率信息, print(‘Epoch {:5d}: reducing learning rate of group {} to {:.4e}.’.format(epoch, i, new_lr))
threshold_mode(str)- 选择判断指标是否达最优的模式,有两种模式, rel 和 abs。
当 threshold_mode == rel,并且 mode == max 时, dynamic_threshold = best * ( 1 +threshold );
当 threshold_mode == rel,并且 mode == min 时, dynamic_threshold = best * ( 1 -threshold );
当 threshold_mode == abs,并且 mode== max 时, dynamic_threshold = best + threshold ;
当 threshold_mode == rel,并且 mode == max 时, dynamic_threshold = best - threshold;
threshold(float)- 配合 threshold_mode 使用。
cooldown(int)- “冷却时间“,当调整学习率之后,让学习率调整策略冷静一下,让模型再训练一段时间,再重启监测模式。
min_lr(float or list)- 学习率下限,可为 float,或者 list,当有多个参数组时,可用 list 进行设置。
eps(float)- 学习率衰减的最小值,当学习率变化小于 eps 时,则不调整学习率。

6、 自定义调整学习率 LambdaLR


为不同参数组设定不同学习率调整策略。调整规则为,

lr=base_lr∗lmbda(self.last_epoch)

fine-tune 中十分有用,我们不仅可为不同的层设定不同的学习率,还可以为其设定不同的学习率调整策略。

torch.optim.lr_scheduler.LambdaLR(optimizer, lr_lambda, last_epoch=-1)

参数:

lr_lambda(function or list)- 一个计算学习率调整倍数的函数,输入通常为 step,当有多个参数组时,设为 list。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值