实现能够在训练过程中手动更改学习率

深度学习框架PyTorch一书的学习-第六章-实战指南pytorch Debug —交互式调试工具Pdb (ipdb是增强版的pdb)-1-在pytorch中使用pytorch实现性别检测三篇文章的基础上写的这篇文章

之前我们使用的是:

exp_lr_scheduler = optim.lr_scheduler.StepLR(optimizer_conv, step_size=3, gamma=0.1)

去自动递减学习率,但是这种方法还是十分死板的,希望实现能够手动根据收敛地效果去更改学习率的大小。所以在这里就是用了ipdb调试工具

1)

首先我们会使用argparse去实现命令行解析,实现通过设置--debugFile命令,然后通过生成和删除指定文件夹去进入调试状态:

def getArgs():
#设置解析
    parser = argparse.ArgumentParser()
    parser.add_argument(‘--debugFile‘, nargs=‘?‘, default=‘None‘, type=str)
    args = parser.parse_args()
    return vars(args) #用vars()内建函数化为字典  

2)然后在train_model()函数中添加:

                        # 进入debug模式
                        # print(‘args : ‘, args[‘debugFile‘])
                        if os.path.exists(args[‘debugFile‘]):
                            import ipdb;
                            ipdb.set_trace()

实现当读取到该指定的文件夹后进入调试状态

3)

整个代码如下:

# coding:utf8
from torchvision import datasets, models
from torch import nn, optim
from torchvision import transforms as T
from torch.utils import data

import os
import copy
import time
import torch
import argparse

#首先进行数据的处理
data_dir = ‘./data‘
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

#转换图片数据
normalize = T.Normalize([0.485, 0.456, 0.406],[0.229, 0.224, 0.225])
data_transforms ={
    ‘train‘: T.Compose([
        T.RandomResizedCrop(224),#从图片中心截取
                T.RandomHorizontalFlip(),#随机水平翻转给定的PIL.Image,翻转概率为0.5
        T.ToTensor(),#转成Tensor格式,大小范围为[0,1]
        normalize
    ]),

    ‘val‘: T.Compose([
        T.Resize(256),#重新设定大小
        T.CenterCrop(224),
        T.ToTensor(),
        normalize
    ]),
}

#加载图片
#man的label为0, woman的label为1
image_datasets = {x : datasets.ImageFolder(os.path.join(data_dir, x), data_transforms[x]) for x in [‘train‘, ‘val‘]}

#得到train和val中的数据量
dataset_sizes = {x : len(image_datasets[x].imgs) for x in [‘train‘, ‘val‘]}
dataloaders = {x : data.DataLoader(image_datasets[x], batch_size=4, shuffle=True,num_workers=4) for x in [‘train‘, ‘val‘]}

#然后选择使用的模型
model_conv = models.resnet18(pretrained=True)
#冻结参数,不训练卷积层网络
#for param in model_conv.parameters():
#    param.requires_grad = False

#提取fc全连接层中固定的参数,后面的训练只对全连接层的参数进行优化
fc_features = model_conv.fc.in_features
#修改类别为2,即man和woman
model_conv.fc = nn.Linear(fc_features, 2)
model_conv.to(device)
#定义使用的损失函数为交叉熵代价函数
criterion = nn.CrossEntropyLoss()
#定义使用的优化器
#optimizer_conv = optim.SGD(model_conv.fc.parameters(), lr=0.0001, momentum=0.9)
#optimizer_conv = optim.SGD(model_conv.parameters(), lr=0.0001, momentum=0.9)
optimizer_conv = optim.Adam(model_conv.parameters(), lr=0.0001, betas=(0.9, 0.99))
#设置自动递减的学习率,等间隔调整学习率,即在7个step时,将学习率调整为 lr*gamma
# exp_lr_scheduler = optim.lr_scheduler.StepLR(optimizer_conv, step_size=3, gamma=0.1)
#exp_lr_scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer_conv, mode=‘min‘, verbose=True)

# 训练模型
# 参数说明:
# model:待训练的模型
# criterion:评价函数
# optimizer:优化器
# scheduler:学习率
# num_epochs:表示实现完整训练的次数,一个epoch表示一整個训练周期
# def train_model(model, criterion, optimizer, scheduler, args, num_epochs=20):
def train_model(model, criterion, optimizer, args, num_epochs=20):
    # 定义训练开始时间
    since = time.time()
    #用于保存最优的权重
    best_model_wts = copy.deepcopy(model.state_dict())
    #最优精度值
    best_train_acc = 0.0
    best_val_acc = 0.0
    best_iteration = 0

    # # meters,统计指标:平滑处理之后的损失,还有混淆矩阵
    # loss_meter = meter.AverageValueMeter()#能够计算所有数的平均值和标准差,用来统计一个epoch中损失的平均值
    # confusion_matrix = meter.ConfusionMeter(2)#用来统计分类问题中的分类情况,是一个比准确率更详细的统计指标

    # 对整个数据集进行num_epochs次训练
    for epoch in range(num_epochs):
        print(‘Epoch {}/{}‘.format(epoch, num_epochs - 1))
        print(‘-‘ * 10)

        #用于存储train acc还没有与val acc比较之前的值
        temp = 0
        # Each epoch has a training and validation phase
        # 每轮训练训练包含`train`和`val`的数据
        for phase in [‘train‘, ‘val‘]:
            if phase == ‘train‘:
                # 学习率步进
                # scheduler.step()
                # 设置模型的模式为训练模式(因为在预测模式下,采用了`Dropout`方法的模型会关闭部分神经元)
                model.train()  # Set model to training mode
            else:
            # 预测模式
                model.eval()   # Set model to evaluate mode

            running_loss = 0.0
            running_corrects = 0

            # Iterate over data.
            # 遍历数据,这里的`dataloaders`近似于一个迭代器,每一次迭代都生成一批`inputs`和`labels`数据,
            # 一批有四个图片,一共有dataset_sizes[‘train‘]/4或dataset_sizes[‘val‘]/4批
            # 这里循环几次就看有几批数据
            for inputs, labels in dataloaders[phase]:
                inputs = inputs.to(device)   # 当前批次的训练输入
                labels = labels.to(device)  # 当前批次的标签输入
                # print(‘input : ‘, inputs)
                # print(‘labels : ‘, labels)

                # 将梯度参数归0
                optimizer.zero_grad()

                # 前向计算
                # track history if only in train
                with torch.set_grad_enabled(phase == ‘train‘):
                    # 相应输入对应的输出
                    outputs = model(inputs)
                    # print(‘outputs : ‘, outputs)
                    # 取输出的最大值作为预测值preds,dim=1,得到每行中的最大值的位置索引,用来判别其为0或1
                    _, preds = torch.max(outputs, 1)
                    # print(‘preds : ‘, preds)
                    # 计算预测的输出与实际的标签之间的误差
                    loss = criterion(outputs, labels)
                    # backward + optimize only if in training phase
                    if phase == ‘train‘:
                    # 对误差进行反向传播
                        loss.backward()
                        #scheduler.step(loss) #当使用的学习率递减函数为optim.lr_scheduler.ReduceLROnPlateau时,使用在这里
                        # 执行优化器对梯度进行优化
                        optimizer.step()

                        # loss_meter.add(loss.item())
                        # confusion_matrix.add(outputs.detach(), labels.detach()) 

                        # 进入debug模式
                        # print(‘args : ‘, args[‘debugFile‘])
                        if os.path.exists(args[‘debugFile‘]):
                            import ipdb;
                            ipdb.set_trace()

                # statistics
                # 计算`running_loss`和`running_corrects`
                #loss.item()得到的是此时损失loss的值
                #inputs.size(0)得到的是一批图片的数量,这里为4
                #两者相乘得到的是4张图片的总损失
                #叠加得到所有数据的损失
                running_loss += loss.item() * inputs.size(0)
                #torch.sum(preds == labels.data)判断得到的结果中有几个正确,running_corrects得到四个中正确的个数
                #叠加得到所有数据中判断成功的个数
                running_corrects += torch.sum(preds == labels.data)

        # 当前轮的损失,除以所有数据量个数得到平均loss值
            epoch_loss = running_loss / dataset_sizes[phase]
            # 当前轮的精度,除以所有数据量个数得到平均准确度
            epoch_acc = running_corrects.double() / dataset_sizes[phase]

            print(‘{} Loss: {:.4f} Acc: {:.4f}‘.format(phase, epoch_loss, epoch_acc))

            # deep copy the model
            # 对模型进行深度复制
            if phase == ‘train‘ and epoch_acc > best_train_acc:
                temp = epoch_acc
            if phase ==‘val‘ and epoch_acc > 0 and epoch_acc < temp:
                best_train_acc = temp
                best_val_acc = epoch_acc
                best_iteration = epoch
                best_model_wts = copy.deepcopy(model.state_dict())

    # 计算训练所需要的总时间
    time_elapsed = time.time() - since
    print(‘Training complete in {:.0f}m {:.0f}s‘.format(time_elapsed // 60, time_elapsed % 60))
    print(‘Best epoch: {:4f}‘.format(best_iteration))
    print(‘Best train Acc: {:4f}‘.format(best_train_acc))
    print(‘Best val Acc: {:4f}‘.format(best_val_acc))

    # load best model weights
    # 加载模型的最优权重
    model.load_state_dict(best_model_wts)
    return model

def getArgs():
#设置解析
    parser = argparse.ArgumentParser()
    parser.add_argument(‘--debugFile‘, nargs=‘?‘, default=‘None‘, type=str)
    args = parser.parse_args()
    return vars(args) #用vars()内建函数化为字典  

if __name__ == ‘__main__‘:
    args_dist = getArgs()
    print(args_dist)
    # model_train = train_model(model_conv, criterion, optimizer_conv, exp_lr_scheduler, args_dist)
    model_train = train_model(model_conv, criterion, optimizer_conv, args_dist)
    torch.save(model_train, ‘GenderTest1_18.pkl‘)

4)

然后运行:

(deeplearning) userdeMBP:resnet18 user$ python train.py --debugFile=./debug
{‘debugFile‘: ‘./debug‘}
Epoch 0/19
----------
train Loss: 0.7313 Acc: 0.6000
val Loss: 0.6133 Acc: 0.5500
Epoch 1/19
----------
train Loss: 0.3051 Acc: 0.9500
val Loss: 0.5630 Acc: 0.7000
Epoch 2/19
----------
train Loss: 0.1872 Acc: 0.9000
val Loss: 0.8300 Acc: 0.6500
Epoch 3/19
----------
train Loss: 0.3791 Acc: 0.8500
val Loss: 1.1445 Acc: 0.6000
Epoch 4/19
----------
train Loss: 0.4880 Acc: 0.8000
val Loss: 0.5832 Acc: 0.7000
Epoch 5/19
----------

这时候在当前文件夹下生成一个名为debug的文件夹,就会进入调试模式:

Epoch 5/19
----------
--Call--
> /anaconda3/envs/deeplearning/lib/python3.6/site-packages/torch/autograd/grad_mode.py(129)__exit__()
    128
--> 129     def __exit__(self, *args):
    130         torch.set_grad_enabled(self.prev)

ipdb> u   #进入上一条命令
> /Users/user/pytorch/gender_test_work/resnet18/train.py(151)train_model()
    150                             import ipdb;
--> 151                             ipdb.set_trace()
    152 

ipdb> for group in optimizer.param_groups: group[‘lr‘] #查看当前的学习率值
0.0001
ipdb> for group in optimizer.param_groups: group[‘lr‘]=0.01  #更改为新的学习率值

然后这时候删除debug文件夹,在调试中运行c命令继续向下运行:

ipdb> c
train Loss: 1.0321 Acc: 0.7500
val Loss: 8590.6042 Acc: 0.6000
Epoch 6/19
----------
train Loss: 2.5962 Acc: 0.4000
val Loss: 23884.8344 Acc: 0.5000
Epoch 7/19
----------
train Loss: 1.0793 Acc: 0.5500
val Loss: 65956.7039 Acc: 0.5000
Epoch 8/19
----------
train Loss: 1.6199 Acc: 0.4500
val Loss: 16973.9813 Acc: 0.5000
Epoch 9/19
----------
train Loss: 1.4478 Acc: 0.3500
val Loss: 1580.6444 Acc: 0.5000
Epoch 10/19
----------

然后再生成debug文件夹进入调试命令,查看此时的学习率,可见此时的学习率果然为调后的0.01:

Epoch 10/19
----------
> /Users/user/pytorch/gender_test_work/resnet18/train.py(151)train_model()
    150                             import ipdb;
--> 151                             ipdb.set_trace()
    152 

ipdb> for group in optimizer.param_groups: group[‘lr‘]
0.01
ipdb>  

上面的训练结果什么的不要太在意,只是为了演示随便跑的

5)

中间有出现一个问题:

SyntaxError: non-default argument follows default argument

这种错误原因是将没有默认值的参数在定义时放在了有默认值的参数的后面

如:

def train_model(model, criterion, optimizer, scheduler, num_epochs=200, args_dist):

应该写成:

def train_model(model, criterion, optimizer, scheduler, args_dist, num_epochs=200):

原文地址:https://www.cnblogs.com/wanghui-garcia/p/10750161.html

时间: 2024-08-24 09:53:44

实现能够在训练过程中手动更改学习率的相关文章

DeepLearning tutorial(2)机器学习算法在训练过程中保存参数

我是小白,说的不是很好,请原谅 @author:wepon @blog:http://blog.csdn.net/u012162613/article/details/43169019 参考:pickle - Python object serialization.DeepLearning Getting started 一.python读取"***.pkl.gz"文件 用到Python里的gzip以及cPickle模块,简单的使用代码如下,如果想详细了解可以参考上面给出的链接. [p

TensorFlow之tf.nn.dropout():防止模型训练过程中的过拟合问题

一:适用范围: tf.nn.dropout是TensorFlow里面为了防止或减轻过拟合而使用的函数,它一般用在全连接层 二:原理: dropout就是在不同的训练过程中随机扔掉一部分神经元.也就是让某个神经元的激活值以一定的概率p,让其停止工作,这次训练过程中不更新权值,也不参加神经网络的计算.但是它的权重得保留下来(只是暂时不更新而已),因为下次样本输入时它可能又得工作了 三:函数介绍: tf.nn.drop(x,  keep_prob, noise_shape=None, seed=Non

(转)理解YOLOv2训练过程中输出参数含义

最近有人问起在YOLOv2训练过程中输出在终端的不同的参数分别代表什么含义,如何去理解这些参数?本篇文章中我将尝试着去回答这个有趣的问题. 刚好现在我正在训练一个YOLOv2模型,拿这个真实的例子来讨论再合适不过了,下边是我训练中使用的 .cfg 文件(你可以在cfg文件夹下找到它): 以下是训练过程中终端输出的一个截图: 以上截图显示了所有训练图片的一个批次(batch),批次大小的划分根据我们在 .cfg 文件中设置的subdivisions参数.在我使用的 .cfg 文件中 batch =

调参过程中的参数 学习率,权重衰减,冲量(learning_rate , weight_decay , momentum)

无论是深度学习还是机器学习,大多情况下训练中都会遇到这几个参数,今天依据我自己的理解具体的总结一下,可能会存在错误,还请指正. learning_rate , weight_decay , momentum这三个参数的含义. 并附上demo. 我们会使用一个例子来说明一下: 比如我们有一堆数据,我们只知道这对数据是从一个黑盒中得到的,我们现在要寻找到那个具体的函数f(x),我们定义为目标函数T. 我们现在假定有存在这个函数并且这个函数为: 我们现在要使用这对数据来训练目标函数. 我们可以设想如果

关于级联分类器训练过程中遇到的问题

最近在做级联分类器的训练,训练和识别过程中不断的遇到的问题,现在把想起来的问题记录下来,方便以后再遇见的时候可以方便查阅,如果有同样做此项目的朋友,欢迎交流! 训练时负样本的准备: 我们自己制作了一个工具,将训练和识别所需要的所有步骤集中在一起,而不需要一个.bat一个.bat的训练或者识别.但是我们的工具在负样本准备阶段,不管是训练还是识别,只要样本个数超过30000个就会提示“遇到不适当的参数”的提醒,我检查了内存分配,数组大小检查,及有可能的逻辑错误,仍然出现这个讨厌的东西.但是也不能不训

模型训练过程中的训练集、训练开发集、开发集和测试集总结

36.什么时候你应该在不同分布上做训练和测试 当你的猫app已经上传10000张图,你已经人工标记它们有没有猫,同时你有200000张互联网上下载的图,这时你要怎么划分训练开发测试集呢? 当你训练深度学习模型时,可能必须用到那200000张图,那么训练和测试集的分布就不同,这会怎样影响你的工作呢? 当然将210000张图片随机分裂到训练开发测试集是一种方法,但我(吴恩达)不推荐这种方法,记住选择开发测试集的推荐方法是:选择你未来预期会得到的数据来作为开发测试集. 大多数学术文章假设训练开发测试集

OpenCV中的Haar+Adaboost(七):分类器训练过程

本节文章讲解OpenCV中Haar+Adaboost的训练过程.此文章假定读者已经了解前面5章的内容,包括Haar特征,弱分类器和强分类器结构,以及GAB等内容. 在opencv_traincascade.exe程序中,有如下参数 如上输入的boostParams中的6个参数决用于决定训练过程: 1. 参数bt选择Boosting类型(默认GAB),本系列文章五中已经介绍了 2. minHitRate和maxFalseAlarmRate限定训练过程中各种阈值大小,文章六已经介绍了 3. 参数we

09 使用Tensorboard查看训练过程

打开Python Shell,执行以下代码: import tensorflow as tf import numpy as np #输入数据 x_data = np.linspace(-1,1,300)[:, np.newaxis] noise = np.random.normal(0,0.05, x_data.shape) y_data = np.square(x_data)-0.5+noise #输入层 with tf.name_scope('input_layer'): #输入层.将这两

caffe绘制训练过程的loss和accuracy曲线

转自:http://blog.csdn.net/u013078356/article/details/51154847 在caffe的训练过程中,大家难免想图形化自己的训练数据,以便更好的展示结果.如 果自己写代码记录训练过程的数据,那就太麻烦了,caffe中其实已经自带了这样的小工具 caffe-master/tools/extra/parse_log.sh  caffe-master/tools/extra/extract_seconds.py和 caffe-master/tools/ext