darknet源码剖析 模型训练初探
Posted mazinkaiser1991
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了darknet源码剖析 模型训练初探相关的知识,希望对你有一定的参考价值。
终于到了最核心的部分了,模型训练的过程由两个部分组成,分别是正向传播与反向传播的过程。
首先来看模型的正向传播过程,还是根据函数的调用过程。
(1)train_network(network.c)
int batch = net->batch;
int n = d.X.rows / batch;
根据yolov1的配置,batch的值为8,d.X.rows的值为64,因此n的值也为8。
for(i = 0; i < n; ++i)
get_next_batch(d, batch, i*batch, net->input, net->truth);
float err = train_network_datum(net);
sum += err;
return (float)sum/(n*batch);
通过上面的代码可以明确,yolo的训练过程是每次获取batch张图片,共执行n次。每次训练时调用train_network_datum函数进行训练,并返回损失。最后train_network函数返回平均损失。
(2)train_network_datum(network.c)
*net->seen += net->batch;
batch表示每个batch训练的图片数量,seen表示已经训练的图片的数量。
net->train = 1;
forward_network(net);
backward_network(net);
float error = *net->cost;
将网络设置为训练模式,并执行正向传播与反向传播,同时获取网络的损失。
if(((*net->seen)/net->batch)%net->subdivisions == 0) update_network(net);
如果(*net->seen)/net->batch是net->subdivisions的整倍数,则更新网络参数。此处的net->seen为64的整倍数则会更新一次网络,正好与yolov1.cfg中batch的设置相等,若当前GPU的内存较小,可以通过增大subdivisions的方式,之前的分析中已经发现,batch的实际数字是batch/subdivisions(yolov1.cfg配置)。此处((*net->seen)/net->batch)%net->subdivisions的值恰好等于batch的设置,表明网络每个batch张图片更新一次。
以上内容总结起来就是一句话:由于GPU内存不足可以增大subdivisions的值,此时net->batch的值就会减小,但是网络参数的更新仍然按照batch的大小(yolov1.cfg配置的值)
return error;
最后返回损失。
forward、backward与update均包括GPU与非GPU版本。若在编译阶段定义了GPU,则执行每一层的forward_gpu函数,否则调用forward函数。backward与update的过程类似。以forward的CPU执行过程为例:
network net = *netp;
int i;
for(i = 0; i < net.n; ++i)
net.index = i;
layer l = net.layers[i];
if(l.delta)
fill_cpu(l.outputs * l.batch, 0, l.delta, 1);
l.forward(l, net);
net.input = l.output;
if(l.truth)
net.truth = l.output;
calc_network_cost(netp);
for循环逐层调用每一层的forward函数,forward函数调用结束后将net.input指向每一层的output。若当前层为dropout层则l.delta有效,否则为0。最后计算网络的损失。
以上是关于darknet源码剖析 模型训练初探的主要内容,如果未能解决你的问题,请参考以下文章
YOLO-Darknet实战:自建数据集训练YOLOv4模型
YOLO-Darknet实战:自建数据集训练YOLOv4模型
模型训练ubuntu 编译 Darknet 与 YOLO 训练