pytorch 实现学习率设置 观察数据具体调整

Iona ·
更新时间:2024-11-13
· 551 次阅读

摘要

学习率的设置也是训练好模型的关键点之一,所以需要掌握常用的学习率的设置,一种是使用自带函数,另一种是自己设置每个阶段的学习率作为调整,

模型保存方式

在学习率调整的时候你是没有办法直接感觉多少epoch能训练出来,所以保存模型的时候最好是可以继续训练的形式,例如我在训练102分类的时候acc达到93的时候基本很难再增进了这时候就要在考虑一下学习率的设置,开始的时候全程0.001,所以这时候将学习率改为0.0001会有更好的效果。所以保存可以中断训练继续的保存很重要

net = resnet50.Resnet().cuda() criterion = nn.CrossEntropyLoss() optimizer = optim.Adam(net.parameters(),lr=0.001) checkpoint = torch.load(PATH) net.load_state_dict(checkpoint['model_state_dict']) optimizer.load_state_dict(checkpoint['optimizer_state_dict']) epoch = checkpoint['epoch'] loss = checkpoint['loss'] #这部分是加载,只有训练一次之后才有的模型可以这样加载,对应保存部分 torch.save({'epoch':epoch, 'model_state_dict': net.state_dict(), 'optimizer_state_dict': optimizer.state_dict(), 'loss': loss },PATH) #这部分代码写在每个训练当中进行保存, 自带函数调整 import torch import torch.optim as optim from torch.optim import lr_scheduler from torchvision.models import AlexNet import matplotlib.pyplot as plt model = AlexNet(num_classes=2) optimizer = optim.SGD(params=model.parameters(), lr=0.05) # lr_scheduler.StepLR() # Assuming optimizer uses lr = 0.05 for all groups # lr = 0.05 if epoch < 30 # lr = 0.005 if 30 <= epoch < 60 # lr = 0.0005 if 60 <= epoch < 90 scheduler = lr_scheduler.StepLR(optimizer, step_size=30, gamma=0.1) plt.figure() x = list(range(100)) y = [] for epoch in range(100): scheduler.step() lr = scheduler.get_lr() print(epoch, scheduler.get_lr()[0]) y.append(scheduler.get_lr()[0]) plt.plot(x, y) plt.show()

在这里插入图片描述
函数的重点使用注意二个点就可以,step_size的设置就是每个多少个epoch变动一次,变动的大小幅度是乘gamma。在使用自带的学习率规则调整只需要在训练的批次当中加上lrScheduler.step()进行调成即可,具体如下

lrScheduler = optim.lr_scheduler.StepLR(optimizer, step_size=1, gamma=0.95) for epoch in range(pre_epoch, EPOCH): for i, data in enumerate(trainloader): ... lrScheduler.step() ... 自定义学习率 train_cfg = dict( warmup=5, lr=[0.004, 0.002, 0.0004, 0.00004, 0.000004], step_lr=dict( COCO=[90, 110, 130, 150, 160], ), ) def adjust_learning_rate(optimizer, epoch, train_cfg): global lr # 在warmup 训练期间,学习率先行增大到初始学习率lr[0] = 0.04 if epoch = epoch: lr = train_cfg.lr[i] break # lr = train_cfg.init_lr * (gamma ** (step_index)) for param_group in optimizer.param_groups: param_group['lr'] = lr

在训练模型中一个比较好的点就是学习率预热,先从小的学习率开始慢慢增大,训练数据更加平稳,具体使用如下

optimizer = optim.Adam(net.parameters(),lr=0.004) for epoch in range(pre_epoch, EPOCH): for i, data in enumerate(trainloader): ... adjust_learning_rate(optimizer,epoch,train_cfg) ... 总结

学习率的变化最好是结合训练情况及时调整,整体流程就是开始学习率预热,中间调整lr最大为0.05左右,到acc提升到末尾的时候,可以将lr在设置到0.00005左右的大小。

其他重要细节点

在训练的时候有几个比较重要的点,就是训练集分为训练集和验证集的时候,最好是保持数据的类别比例分开,将训练集和验证集分为9:1的比例比较协调,在其中要保证每个类别的比例基本没有太大变化。比如猫狗比例3:7,那么验证集的提取比例也应为3:7。
预训练权重也是可以极大的加快训练速度,大部分数据集都可以使用预训练权重。使用预训练权重有个最要要的细节是transform.normalize的使用

针对预训练权重初始化训练

大部分的网络预训练都是在1000分类的图像训练,所以transforms.Normalize的设置是不同的,这种归一化可以使得数据更加稳定,训练的效果更好,使得自己的数据集均值和标准差符合imagenet的分布,是预训练权重效果完全展现,所以,只要使用了预训练权重就要设置transforms.Normalize

if 'coco' in args.dataset: mean_vals = [0.471, 0.448, 0.408] std_vals = [0.234, 0.239, 0.242] elif 'imagenet' in args.dataset: mean_vals = [0.485, 0.456, 0.406] std_vals = [0.229, 0.224, 0.225]

对不同的预训练过的模型设置值,在没有预训练权重的时候需要自己去计算mean和std的值,代码如下

import torchvision.transforms as transforms import torch.nn as nn import numpy as np import pandas as pd import torch.optim as optim from torch.utils.data.sampler import SubsetRandomSampler from efficientnet_pytorch import EfficientNet from PIL import Image from tqdm import tqdm import torch.nn.functional as F import torch import random from torch.autograd import Variable from torch.utils.data import Dataset, DataLoader train_df = pd.read_csv('./54_data/train.csv') train_df['filename'] = train_df['filename'].apply(lambda x: './54_data/train/{0}'.format(x)) class MyDataset(Dataset): def __init__(self, df, transform): self.df = df self.transform = transform def __getitem__(self, index): img = Image.open(self.df['filename'].iloc[index]).convert('RGB') img = self.transform(img) return img, torch.from_numpy(np.array(self.df['label'].iloc[index])) def __len__(self): return len(self.df) train_transform = transforms.Compose([ transforms.Resize([224, 224]), transforms.ToTensor(), ]) train_data = MyDataset(train_df, train_transform) dataloader = DataLoader(train_data, batch_size=10, shuffle=True) mean = torch.zeros(3) std = torch.zeros(3) print('==> Computing mean and std..') for inputs, targets in dataloader: for i in range(3): # print(inputs) mean[i] += inputs[:, i, :, :].mean() std[i] += inputs[:, i, :, :].std() mean.div_(len(dataloader)) std.div_(len(dataloader)) print(mean) print(std)

计算出来之后再去设置自己的mean和std的值,具体如下

tf = transforms.Compose([ lambda x: Image.open(x).convert('RGB'), # string path= > image data transforms.Resize((int(self.resize * 1.25), int(self.resize * 1.25))), transforms.RandomRotation(15), transforms.CenterCrop(self.resize), transforms.ToTensor(), transforms.Normalize(mean=[0.436424, 0.433079, 0.330037], std=[0.252266, 0.247213, 0.250690]) ])
作者:视觉盛宴



pytorch 数据 学习率 学习

需要 登录 后方可回复, 如果你还没有账号请 注册新账号