在认识了数据集结构和完成了数据集准备后,就可以开始了模型的训练之旅了,这里采用的是paddlexAPI方式,下面以PPYOLOTiny模型例,代码如下:
# 获取标签总数
num_classes = len(train_dataset.labels)
# 初始化模型
model = pdx.det.PPYOLOTiny(num_classes=num_classes, backbone='ResNet50_vd_dcn')
### 模型的参数说明 ###
# num_classes (int): 类别数。默认为80。
# backbone (str): YOLOv3的backbone网络,取值范围为['MobileNetV3']。默认为'MobileNetV3'。
# anchors (list|tuple): anchor框的宽度和高度。默认为[[10, 15], [24, 36], [72, 42], [35, 87], [102, 96], [60, 170], [220, 125], [128, 222], [264, 266]]。
# anchor_masks (list|tuple): 在计算YOLOv3损失时,使用anchor的mask索引。默认为[[6, 7, 8], [3, 4, 5], [0, 1, 2]]。
# use_iou_aware (bool): 是否使用IoU Aware分支。默认为False。
# use_spp (bool): 是否使用Spatial Pyramid Pooling结构。默认为True。
# use_drop_block (bool): 是否使用Drop Block。默认为True。
# scale_x_y (float): 调整中心点位置时的系数因子。默认为1.05。
# ignore_threshold (float): 在计算PPYOLOv2损失时,IoU大于ignore_threshold的预测框的置信度被忽略。默认为0.5。
# label_smooth (bool): 是否使用label smooth。默认为False。
# use_iou_loss (bool): 是否使用IoU loss。默认为True。
# use_matrix_nms (bool): 是否使用Matrix NMS。默认为False。
# nms_score_threshold (float): 检测框的置信度得分阈值,置信度得分低于阈值的框应该被忽略。默认为0.005。
# nms_topk (int): 进行NMS时,根据置信度保留的最大检测框数。如果为-1则全部保留。默认为1000。
# nms_keep_topk (int): 进行NMS后,每个图像要保留的总检测框数。默认为100。
# nms_iou_threshold (float): 进行NMS时,用于剔除检测框IOU的阈值。默认为0.45。
# 启动模型训练
model.train(
num_epochs=170,
train_dataset=train_dataset,
train_batch_size=4,
eval_dataset=eval_dataset,
pretrain_weights='COCO',
learning_rate=0.005 / 12,
warmup_steps=1000,
warmup_start_lr=0.0,
lr_decay_epochs=[105, 135, 150],
save_interval_epochs=5,
early_stop=True,
early_stop_patience=10,
save_dir='output/ppyolov2_r50vd_dcn')
#### 模型训练参数说明 #####
# num_epochs (int): 训练迭代轮数。
# train_dataset (paddlex.dataset): 训练数据集。
# train_batch_size (int): 训练数据batch大小,默认为64。目前检测仅支持单卡batch大小为1进行评估,train_batch_size参数不影响评估时的batch大小。
# eval_dataset (paddlex.dataset or None): 评估数据集。当该参数为None时,训练过程中不会进行模型评估。默认为None。
# optimizer (paddle.optimizer.Optimizer): 优化器。当该参数为None时,使用默认优化器:paddle.optimizer.lr.PiecewiseDecay衰减策略,paddle.optimizer.Momentum优化方法。
# save_interval_epochs (int): 模型保存间隔(单位:迭代轮数)。默认为1。
# log_interval_steps (int): 训练日志输出间隔(单位:迭代次数)。默认为10。
# save_dir (str): 模型保存路径。默认为'output'。
# pretrain_weights (str ort None): 若指定为'.pdparams'文件时,则从文件加载模型权重;若为字符串’IMAGENET’,则自动下载在ImageNet图片数据上预训练的模型权重(仅包含backbone网络);若为字符串’COCO’,则自动下载在COCO数据集上预训练的模型权重;若为None,则不使用预训练模型。默认为'IMAGENET'。
# learning_rate (float): 默认优化器的学习率。默认为0.001。
# warmup_steps (int): 默认优化器进行warmup过程的步数。默认为0。
# warmup_start_lr (int): 默认优化器warmup的起始学习率。默认为0.0。
# lr_decay_epochs (list): 默认优化器的学习率衰减轮数。默认为[216, 243]。
# lr_decay_gamma (float): 默认优化器的学习率衰减率。默认为0.1。
# metric ({'COCO', 'VOC', None}): 训练过程中评估的方式。默认为None,根据用户传入的Dataset自动选择,如为VOCDetection,则metric为'VOC';如为COCODetection,则metric为'COCO'。
# use_ema (bool): 是否使用指数衰减计算参数的滑动平均值。默认为False。
# early_stop (bool): 是否使用提前终止训练策略。默认为False。
# early_stop_patience (int): 当使用提前终止训练策略时,如果验证集精度在early_stop_patience个epoch内连续下降或持平,则终止训练。默认为5。
# use_vdl (bool): 是否使用VisualDL进行可视化。默认为True。
# resume_checkpoint (str): 恢复训练时指定上次训练保存的模型路径,例如output/ppyolov2/best_model。若为None,则不会恢复训练。默认值为None。
训练参数调整
1.num_epochs的调整
num_epochs是模型训练迭代的总轮数(模型对训练集全部样本过一遍即为一个epoch),用户可以设置较大的数值,根据模型迭代过程在验证集上的指标表现,来判断模型是否收敛,进而提前终止训练。此外也可以使用train接口中的early_stop策略,模型在训练过程会自动判断模型是否收敛自动中止。
2.batch_size和learning_rate
Batch Size指模型在训练过程中,前向计算一次(即为一个step)所用到的样本数量 如若使用多卡训练, batch_size会均分到各张卡上(因此需要让batch size整除卡数) Batch Size跟机器的显存/内存高度相关,batch_size越高,所消耗的显存/内存就越高 PaddleX在各个train接口中均配置了默认的batch size(默认针对单GPU卡),如若训练时提示GPU显存不足,则相应调低BatchSize,如若GPU显存高或使用多张GPU卡时,可相应调高BatchSize。
如若用户调整batch size,则也注意需要对应调整其它参数,特别是train接口中默认的learning_rate值。如在YOLOv3模型中,默认train_batch_size为8,learning_rate为0.000125,当用户将模型在2卡机器上训练时,可以将train_batch_size调整为16, 那么同时learning_rate也可以对应调整为0.000125 * 2 = 0.00025
3.warmup_steps和warmup_start_lr
在训练模型时,一般都会使用预训练模型,例如检测模型在训练时使用backbone在ImageNet数据集上的预训练权重。但由于在自行训练时,自己的数据与ImageNet数据集存在较大的差异,可能会一开始由于梯度过大使得训练出现问题,这种情况下可以在刚开始训练时,让学习率以一个较小的值,慢慢增长到设定的学习率。warmup_steps和warmup_start_lr就是起到这个作用,模型开始训练时,学习率会从warmup_start_lr开始,在warmup_steps个batch数据迭代后线性增长到设定的学习率。
例如YOLOv3的train接口,默认train_batch_size为8,learning_rate为0.000125, warmup_steps为1000, warmup_start_lr为0.0;在此参数配置下表示,模型在启动训练后,在前1000个step(每个step使用一个batch的数据,即8个样本)内,学习率会从0.0开始线性增长到设定的0.000125。
4.lr_decay_epochs和lr_decay_gamma
lr_decay_epochs用于让学习率在模型训练后期逐步衰减,它一般是一个list,如[6, 8, 10],表示学习率在第6个epoch时衰减一次,第8个epoch时再衰减一次,第10个epoch时再衰减一次。每次学习率衰减为之前的学习率*lr_decay_gamma。
例如YOLOv3的train接口,默认num_epochs为270,learning_rate为0.000125, lr_decay_epochs为[213, 240],lr_decay_gamma为0.1;在此参数配置下表示,模型在启动训练后,在前213个epoch中,训练时使用的学习率为0.000125,在第213至240个epoch之间,训练使用的学习率为0.000125x0.1=0.0000125,在240个epoch之后,使用的学习率为0.000125x0.1x0.1=0.00000125
5.参数设定时的约束
根据上述几个参数,可以了解到学习率的变化分为WarmUp热身阶段和Decay衰减阶段,
Wamup热身阶段:随着训练迭代,学习率从较低的值逐渐线性增长至设定的值,以step为单位 Decay衰减阶段:随着训练迭代,学习率逐步衰减,如每次衰减为之前的0.1, 以epoch为单位 step与epoch的关系:1个epoch由多个step组成,例如训练样本有800张图像,train_batch_size为8, 那么每个epoch都要完整用这800张图片训一次模型,而每个epoch总共包含800//8即100个step
如果训练过程被终止,需要恢复训练时,可执行如下代码
model.train(
num_epochs=170,
train_dataset=train_dataset,
train_batch_size=4,
eval_dataset=eval_dataset,
pretrain_weights=None,
learning_rate=0.005 / 12,
warmup_steps=1000,
warmup_start_lr=0.0,
lr_decay_epochs=[105, 135, 150],
save_interval_epochs=5,
early_stop=True,
early_stop_patience=10,
resume_checkpoint="output/ppyolotiny/epochs_xx",
save_dir='output/ppyolotiny')
务必指定resume_checkpoint为上次训练的某个epoch,同时需设置pretrain_weights=None
非常详细
优秀