写在前面
本系列博客记录了作者上手MXNet的全过程。作者在接触MXNet之前主要使用keras,和一点tensorflow,因此在上手MXNet之前有一点deep learning的项目基础。主要参考资料为MXNet官方教程,也阅读了一些有价值的博客。
博客结构为:先列出作者对于该阶段的期望目标,以及各目标完成过程中的笔记(仅记下个人认为重要的),再附上学习过程中自己的提问(solved & unsolved,天马行空的提问,欢迎讨论)。
本阶段目标
任务 | 优先级 | 预计花时间 | 完成状态 | 遇到问题 | 补充 |
了解MXNet中模型的整个inference过程 | 4hour | ![]() | |||
MXNet学习资料整理整理 | P0 | 1.5hour | ![]() | ||
分析VGG案例 | P1 | 2hour | |||
分析SSD案例 | P2 | 3hour |
具体笔记
task1 体会整个inference过程
数据 | 准备数据 | 使用mx.io.ImageRecordIter()来读取 | |
数据预处理 | |||
网络 | 预训练模型导入 | 使用mx.model.load_checkpoint()导入预训练模型 训练好的模型参数是用.params文件保存,网络结构是用.json文件保存 | |
模型结构修改 | get_fine_tune_model()函数进行修改
| ||
模型参数初始化 | mxnet.initializer包用来管理模型参数初始化,例如mxnet.initializer.Xavier 预训练模型中不修改的层不需要再初始化了 | ||
模型初始化 | mxnet.module.Module | 为了? | |
训练 | 学习率变化策略 | 使用mx.lr_scheduler.MultiFactorScheduler类,学习率的改变由epoch和factor决定 | |
训练超参数 | 初始学习率:learning_rate、梯度下降中的动量参数:momentum、正则项参数:wd、学习率变化策略参数:lr_scheduler | ||
评价函数 | 定义在~/incubator-mxnet/blob/master/python/mxnet/metric.py中,评价函数的基类是mxnet.metric.EvalMetric,可以根据这个类自定义评价函数 | ||
logging记录 | 下方logging笔记 | ||
开始训练 |
|
- 关于两种数据格式
`.rec`文件 | `.lst`和图像结合的方式 | ||
pro | con | pro | con |
比较稳定,移植到别的电脑上也能复现 | 占空间(差不多1万张图像生成的.rec文件是1G),而且增删数据不大灵活 | 读取灵活且不占空间 |
|
- 关于训练集和测试集的处理
train和val数据集比较大的区别一方面是val数据集不需要做shuffle操作,另一方面在最后的预处理操作中不需要类似crop或mirror等数据增强操作,但是归一化操作(mean=True和std=True)在`train`和`val`数据集中要么都做,要么都不做,建议都做。另外要提一下最后一个参数aug_list,这个参数的输入是mx.image.CreateAugmenter()函数,这个函数就是该类中管理数据预处理的函数,可以看到在下面的代码中添加了输入图像尺寸:(3,224,224)、resize操作、crpo操作、mirror操作等等。
processing | train set | val set |
Shuffle | ![]() | ![]() |
数据增强(crop\mirror等) | ![]() | ![]() |
归一化 | ![]() | ![]() |
- 关于model.fit
模型训练的入口就是调用前面初始化得到的model的fit方法。接下来介绍下各参数的含义:train_data和eval_data分别表示训练数据和测试数据。begin_epoch表示从第几个epoch开始训练。num_epoch表示一共要训练多少个epoch。eval_metric和validation_metric分别表示训练和测试时候的评价函数。kvstore默认是local。optimizer表示优化方式,默认是'sgd'。`optimizer_params`是优化相关的参数。`arg_params`和`aux_params`这两个参数默认是None,如果想要用预训练的模型来初始化,那么这两个参数就是预训练模型的参数。`initializer`是参数初始化的方式。`allow_missing`参数默认是False,如果设置为True,表示对于`arg_params`和`aux_params`未涉及的层采用`initializer`方式进行初始化。`batch_end_callback`参数是`mx.callback.Speedometer()`函数,该函数的作用是每隔多少个batch显示一次结果,所以该函数主要有两个输入,一个是batch_size,另一个是你指定的间隔多少个batch显示一次结果,如下代码中是20。`epoch_end_callback`参数调用的是`mx.callback.do_checkpoint()`函数,该函数的作用是每隔period个epoch保存训练得到的模型,因此该函数的第一个输入是保存模型的路径和名称,比如下面代码的`args.save_result+args.save_name`,第二个输入是每隔几个epoch保存一次模型,比如下面代码的2,注意`period`默认值是1,常用默认值。
model.fit(train_data=train,
eval_data=val,
begin_epoch=epoch,
num_epoch=num_epoch,
eval_metric=eval_metric,
validation_metric=val_metric,
kvstore=kv,
optimizer='sgd',
optimizer_params=optimizer_params,
arg_params=arg_params,
aux_params=aux_params,
initializer=initializer,
allow_missing=True,
batch_end_callback=mx.callback.Speedometer(args.batch_size, 20),
epoch_end_callback=mx.callback.do_checkpoint(args.save_result+args.save_name,period=2))
- 关于自定义评价函数
定义:mxnet.metric.EvalMetric这个类没有办法直接使用,正确的打开方式是自定义一个继承该基础类的类,写好评价标准后在训练时调用这个类。
使用:无论是自己写的还是官方提供的评价函数,都是通过mxnet.metric.CompositeEvalMetric()类的add方法来添加
from my_metric import *
eval_metric = mx.metric.CompositeEvalMetric()
eval_metric.add(Accuracy()) # 自定义的
eval_metric.add(['CrossEntropy']) # 官方的
task2 MXNet学习资料整理
task3 分析MXNet的VGG项目
项目地址:
task4 分析MXNet的SSD项目
其他笔记:argparse
argparse这个模块做命令行选项和参数解析
其他笔记:logging
import logging
logging.info(args) # 开始训练模型的时候打印出args中的参数信息
logger = logging.getLogger() #创建了一个Logger记录器
logger.setLevel(logging.INFO) #设置日志级别,logging.INFO,表示代码正常运行时候的日志
formatter = logging.Formatter('%(asctime)s - %(message)s')
hdlr = logging.FileHandler(args.save_result+ '/train.log') #将日志保存在指定目录下(args.save_result)
hdlr.setFormatter(formatter) #设置日志的格式
logger.addHandler(hdlr) #将设置好的Handler添加到Logger对象中
console = logging.StreamHandler() #在终端输出信息
console.setFormatter(formatter)
logger.addHandler(console)
学习过程问题记录
本阶段感想
初学者刚接触MXNet的感受就是:网上教程和资料非常多!github\csdn博客和官网都有很多东西,但有点乱不清楚按照什么顺序来,目前对gluon和symbol还是很晕。所以我先将资料进行整理,再选出一套理论知识和代码相结合的资料供自己学习,后续如果有疑问还能再查漏补缺。