1. 程式人生 > >Darknet 程式碼分析(之二,parse_network_cfg_custom函式)

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, 也就是說再執行一次調整

在這裡插入圖片描述

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;
}