Darknet 代码分析(之二,parse_network_cfg_custom函数)

parse_network_cfg_custom函数中,读取配置文件是先把各个section读取出来,然后再解析。
yolov3.cfg里面只有几个不同的section,分别是[net]、[convolutional]、[shortcut]、[yolo]、[route]、[upsample],下面分别探究。

NET(全局)

参考 YOLO配置文件理解

参数名称 类型 默认值 说明
Testing - -
Training - -
batch int 1 前向计算梯度和通过反向传导更新权重值的计算中一次处理的图片文件的数量。
subdivisions int 1 批处理被细分为许多“块”。块的图像在gpu上并行运行。在darknet代码中,会将batch/subdivisions命名为batch,这个值设置比batch小往往回出现out out memory的问题。
width int 416 图像的宽,32的倍数
height int 416 图像的高,32的倍数
channels int 3 按照stackflow上的说法,用下图来表述channels=4的情况:在左边,我们有一个4x4像素的单一通道,重组层将大小减小到一半,然后在不同通道中创建4个相邻像素的通道。我认为可能是表示颜色通道。
momentum float 0.9 见 深度学习中momentum的作用 一文的解释
decay float 0.0005 权重衰减正则项,防止过拟合
angle int 0 通过旋转角度来生成更多训练样本
saturation float 1.5 通过调整饱和度来生成更多训练样本
exposure float 1.5 通过调整曝光量来生成更多训练样本
hue float 0.1 通过调整色调来生成更多训练样本
learning_rate float 0.001 初始学习率
burn_in int 1000 对于第首个burn_in批的训练,缓慢地提高学习率,直到它的最终值等于learning_rate设定的值。通过对学习率的监控可以了解到对于Loss函数的收敛的贡献情况
max_batches int 1000 训练达到max_batches后停止学习
policy string steps 调整学习率的策略。policy取值:CONSTANT, STEP, EXP, POLY, STEPS, SIG, RANDOMpolicy=steps 表示使用下面的steps参数和scales参数来调整训练时的学习速度
steps int array 1000,2000 如取值是1000,2000,则表示在第1000个训练批次和2000个批次后调整learning_rate
scales float array 0.1,0.1 在1000个训练批次后,LR = 0.1, 然后在2000个训练批次后LR *= 0.1, 也就是说再执行一次调整

Darknet 代码分析(之二,parse_network_cfg_custom函数)_第1张图片

convolutional

参数:

参数名称 类型 默认值 说明
batch_normalize bool 1 是否非规范化这个layer,见函数denormalize_convolutional_layer
filters int 255 输出多少个特征图。filters =(classes + 5) x 3
size int 3 卷积核的尺寸
stride int 1 卷积运算的步长
pad bool 0 指定padding的方式
padding int 0 padding由 padding参数指定。如果pad为1,padding大小为size/2
activation string logistic “logistic”、“loggy”、“relu”、“elu”、“relie”、“plse”、“hardtan”、 “lhtan”、 “linear”、ramp"、“leaky”、“tanh”、"stair"是合法的激活函数值。
binary int 0 暂未见使用,先不管
xnor int 0 暂未见使用,先不管
bin_output int 0 暂未见使用,先不管

相应代码段:

    int n = option_find_int(options, "filters",1);
    int size = option_find_int(options, "size",1);
    int stride = option_find_int(options, "stride",1);
    int pad = option_find_int_quiet(options, "pad",0);
    int padding = option_find_int_quiet(options, "padding",0);
    if(pad) padding = size/2;
    char *activation_s = option_find_str(options, "activation", "logistic");
    int batch_normalize = option_find_int_quiet(options, "batch_normalize", 0);
    int binary = option_find_int_quiet(options, "binary", 0);
    int xnor = option_find_int_quiet(options, "xnor", 0);
    int use_bin_output = option_find_int_quiet(options, "bin_output", 0);

shortcut

参数:

参数名称 类型 默认值 说明
shortcut int - 指向其他layer的索引偏移值,yolov3里面是-3
activation string - 激活函数类型,yolov3里面是“linear”

相应代码段:

layer parse_shortcut(list *options, size_params params, network net)
{
    char *l = option_find(options, "from");
    int index = atoi(l);
    if(index < 0) index = params.index + index;

    int batch = params.batch;
    layer from = net.layers[index];

    layer s = make_shortcut_layer(batch, index, params.w, params.h, params.c, from.out_w, from.out_h, from.out_c);

    char *activation_s = option_find_str(options, "activation", "linear");
    ACTIVATION activation = get_activation(activation_s);
    s.activation = activation;
    return s;
}

yolo

参数:

参数名称 类型 默认值 说明
classes int 20
num int 1
mask int 0
max int 90
jitter float 0.2
focal_loss int 0
ignore_thresh float 0.5
truth_thresh int 1
random int 0
map string “”
anchors string “”

相应代码段:

layer parse_yolo(list *options, size_params params)
{
    int classes = option_find_int(options, "classes", 20);
    int total = option_find_int(options, "num", 1);
    int num = total;

    char *a = option_find_str(options, "mask", 0);
    int *mask = parse_yolo_mask(a, &num);
    int max_boxes = option_find_int_quiet(options, "max", 90);
    layer l = make_yolo_layer(params.batch, params.w, params.h, num, total, mask, classes, max_boxes);
    if (l.outputs != params.inputs) {
        printf("Error: l.outputs == params.inputs \n");
        printf("filters= in the [convolutional]-layer doesn't correspond to classes= or mask= in [yolo]-layer \n");
        exit(EXIT_FAILURE);
    }
    //assert(l.outputs == params.inputs);

    //l.max_boxes = option_find_int_quiet(options, "max", 90);
    l.jitter = option_find_float(options, "jitter", .2);
    l.focal_loss = option_find_int_quiet(options, "focal_loss", 0);

    l.ignore_thresh = option_find_float(options, "ignore_thresh", .5);
    l.truth_thresh = option_find_float(options, "truth_thresh", 1);
    l.random = option_find_int_quiet(options, "random", 0);

    char *map_file = option_find_str(options, "map", 0);
    if (map_file) l.map = read_map(map_file);

    a = option_find_str(options, "anchors", 0);
    if (a) {
        int len = strlen(a);
        int n = 1;
        int i;
        for (i = 0; i < len; ++i) {
            if (a[i] == ',') ++n;
        }
        for (i = 0; i < n && i < total*2; ++i) {
            float bias = atof(a);
            l.biases[i] = bias;
            a = strchr(a, ',') + 1;
        }
    }
    return l;
}

route

route layer只有一个参数,layers,指定一个输入的layer。

route_layer parse_route(list *options, size_params params, network net)
{
    char *l = option_find(options, "layers");
    int len = strlen(l);
    if(!l) error("Route Layer must specify input layers");
    int n = 1;
    int i;
    for(i = 0; i < len; ++i){
        if (l[i] == ',') ++n;
    }

    int *layers = calloc(n, sizeof(int));
    int *sizes = calloc(n, sizeof(int));
    for(i = 0; i < n; ++i){
        int index = atoi(l);
        l = strchr(l, ',')+1;
        if(index < 0) index = params.index + index;
        layers[i] = index;
        sizes[i] = net.layers[index].outputs;
    }
    int batch = params.batch;

    route_layer layer = make_route_layer(batch, n, layers, sizes);

    convolutional_layer first = net.layers[layers[0]];
    layer.out_w = first.out_w;
    layer.out_h = first.out_h;
    layer.out_c = first.out_c;
    for(i = 1; i < n; ++i){
        int index = layers[i];
        convolutional_layer next = net.layers[index];
        if(next.out_w == first.out_w && next.out_h == first.out_h){
            layer.out_c += next.out_c;
        }else{
            layer.out_h = layer.out_w = layer.out_c = 0;
        }
    }

    return layer;
}

upsample

顾名思义,这个layer是用来做上采样的,只有stride和scale两个参数,代码如下

layer parse_upsample(list *options, size_params params, network net)
{

    int stride = option_find_int(options, "stride", 2);
    layer l = make_upsample_layer(params.batch, params.w, params.h, params.c, stride);
    l.scale = option_find_float_quiet(options, "scale", 1);
    return l;
}

你可能感兴趣的:(yolo)