这些天在复现YOLOV3时,训练过程中遇到了一些问题,在这里记录一下跑网络的过程~
训练指令
注意根据情况修改Makefile文件,并重新make,以及cfg文件夹下yolov3-voc.cfg文件,在darknet目录下执行命令:
格式:./darknet detector train [data_cfg] [network_cfg] [weight] -gpus [gpu_nums]
CPU上训练:
./darknet -ngpu detector train cfg/voc.data cfg/yolov3-voc.cfg darknet.conv.74
多GPU训练:
./darknet detector train cfg/voc.data cfg/yolov3-voc.cfg darknet.conv.74 -gpus 0,1
输出重定向
如果需要将训练过程可视化,则训练时将输出重定向得到训练日志文件;
./darknet detector train cfg/voc.data cfg/yolov3-voc.cfg darknet.conv.74 -gpus 0,1 2>1 | tee train_yolov3.log
从检查点开始恢复训练
./darknet detector train cfg/voc.data cfg/yolov3-voc.cfg backup/yolov3.backup -gpus 0,1
输出解释
forward_yolo_layer()
每个子batch输出一次,详见src文件夹下yolo_layer.c文件的forward_yolo_layer函数。
1 | printf("Region %d Avg IOU: %f, Class: %f, Obj: %f, No Obj: %f, .5R: %f, .75R: %f, count: %d\n", net.index, avg_iou/count, avg_cat/class_count, avg_obj/count, avg_anyobj/(l.w*l.h*l.n*l.batch), recall/count, recall75/count, count); |
Region [xx]
: cfg文件中的layer的索引;Avg IOU
: 当前迭代过程中,预测的bbox和ground truth的平均交并比,理想值为1;Class
: 标注物体的分类准确率,理想值为1;Obj
: 期望该值越接近1越好;No Obj
: 期望该值越小越好;.5R
: IoU=0.5为阈值时,当前子batch中recall值;.75R
: IoU=0.75为阈值时,当前子batch中recall值;count
: 当前subdivision的子batch中所有图片中包含的正样本数。count = 0
表示该批次该尺度上没有检测到对象,会导致Avg IOU
、Class
、obj
、.5R
、.75R
值均为-nan
或nan
。这可能是由于在许多小物体上训练导致的,所以在显存允许的情况下,可适当增大batch
的大小,可一定程度减少nan的出现。
train_detector()
每个batch输出一次loss,详见examples文件夹下detect.c文件中train_detector函数:
1 | printf("%ld: %f, %f avg, %f rate, %lf seconds, %d images\n", get_current_batch(net), loss, avg_loss, get_current_rate(net), what_time_is_it_now()-time, i*imgs); |
问题及解决
CUDA: out of memory
显存不够引起的,修改yolov3-voc.cfg文件。
修改
[net]
层参数,增大subdivisions
或调小batch
,因为训练时实际每次前向的图片数量 = batch/subdivisions。关闭多尺度训练。将所有
[yolo]
层中random
参数修改为random = 0
。
参数调整
Batch_Size:想要模型快速收敛,最好是增大Batch_Size,但可能导致陷入局部最小的情况;减小Batch_Size可能会有更好的效果,但是如果类别数较多,Batch_Size又太小,会导致loss函数震荡不收敛。一般在调试时,根据GPU显存,设置为最大(一般要求为8的倍数),选部分数据跑几个Batch看看loss是否在变小,再选择合适的值。yolov3-voc.cfg文件中对应参数为
batch
。如果内存不够大,增大
subdivision
值,将batch分割,每个子batch大小为 batch/subdivisions。为了应对小目标检测,网络输入大一些更好,即增大
weight
和height
。random = 1
会使用多尺度训练,随机使用不同尺寸的图片进行训练;如果为0,则每次训练图片大小与输入尺寸一致。