改进2:合并BN层到卷积层
目的:提升模型前向推理的速度
include/darknet.h
#ifndef ENABLE_FUSE_CONV_BATCHNORM
#define ENABLE_FUSE_CONV_BATCHNORM
#endif
#ifdef ENABLE_FUSE_CONV_BATCHNORM
void fuse_conv_batchnorm(network net);
#endif
src/network.c
#ifdef ENABLE_FUSE_CONV_BATCHNORM
void fuse_conv_batchnorm(network net)
{
int j;
for (j = 0; j < net.n; ++j) {
layer *l = &net.layers[j];
if (l->type == CONVOLUTIONAL) {
//printf(" Merges Convolutional-%d and batch_norm \n", j);
if (l->batch_normalize) {
int f;
for (f = 0; f < l->n; ++f)
{
l->biases[f] = l->biases[f] - (double)l->scales[f] * l->rolling_mean[f] / (sqrt((double)l->rolling_variance[f] + .000001));
const size_t filter_size = l->size*l->size*l->c / l->groups;
int i;
for (i = 0; i < filter_size; ++i) {
int w_index = f*filter_size + i;
l->weights[w_index] = (double)l->weights[w_index] * l->scales[f] / (sqrt((double)l->rolling_variance[f] + .000001));
}
}
l->batch_normalize = 0;
#ifdef GPU
if (gpu_index >= 0) {
push_convolutional_layer(*l);
}
#endif
}
}
else {
//printf(" Fusion skip layer type: %d \n", l->type);
}
}
}
#endif //ENABLE_FUSE_CONV_BATCHNORM
src/demo.c
void demo(char *cfgfile, char *weightfile, float thresh, int cam_index, const char *filename, char **names, int classes, int delay, char *prefix, int avg_frames, float hier, int w, int h, int frames, int fullscreen)
{
//demo_frame = avg_frames;
image **alphabet = load_alphabet();
demo_names = names;
demo_alphabet = alphabet;
demo_classes = classes;
demo_thresh = thresh;
demo_hier = hier;
printf("Demo\n");
net = load_network(cfgfile, weightfile, 0);
set_batch_network(net, 1);
#ifdef ENABLE_FUSE_CONV_BATCHNORM
fuse_conv_batchnorm(*net);
#endif
......
}
src/detector.c
void validate_detector(char *datacfg, char *cfgfile, char *weightfile, char *outfile)
{
int j;
list *options = read_data_cfg(datacfg);
char *valid_images = option_find_str(options, "valid", "data/train.list");
char *name_list = option_find_str(options, "names", "data/names.list");
char *prefix = option_find_str(options, "results", "results");
char **names = get_labels(name_list);
char *mapf = option_find_str(options, "map", 0);
int *map = 0;
if (mapf) map = read_map(mapf);
network *net = load_network(cfgfile, weightfile, 0);
set_batch_network(net, 1);
#ifdef ENABLE_FUSE_CONV_BATCHNORM
fuse_conv_batchnorm(*net);
#endif
......
}
void validate_detector_recall(char *cfgfile, char *weightfile)
{
network *net = load_network(cfgfile, weightfile, 0);
set_batch_network(net, 1);
#ifdef ENABLE_FUSE_CONV_BATCHNORM
fuse_conv_batchnorm(*net);
#endif
......
}
void test_detector(char *datacfg, char *cfgfile, char *weightfile, char *filename, float thresh, float hier_thresh, char *outfile, int fullscreen)
{
list *options = read_data_cfg(datacfg);
char *name_list = option_find_str(options, "names", "data/names.list");
char **names = get_labels(name_list);
image **alphabet = load_alphabet();
network *net = load_network(cfgfile, weightfile, 0);
set_batch_network(net, 1);
#ifdef ENABLE_FUSE_CONV_BATCHNORM
fuse_conv_batchnorm(*net);
#endif
......
}
训练及性能测试:
./darknet detector train cfg/voc.data cfg/yolov3-voc.cfg darknet53.conv.74
./darknet detector valid cfg/voc.data cfg/yolov3-voc-test.cfg backup/yolov3-voc_final.weights
python reval_voc.py --voc_dir /home/bai/darknet/VOCdevkit --year 2007 --image_set test --classes /home/bai/darknet/data/voc.names testVOC