1. 程式人生 > >YOLO配置檔案理解以及解析過程

YOLO配置檔案理解以及解析過程

原文地址:點選這裡
如有侵權,聯絡刪除

YOLO配置檔案理解

[net]
batch=64                           每batch個樣本更新一次引數。
subdivisions=8                     如果記憶體不夠大,將batch分割為subdivisions個子batch,每個子batch的大小為batch/subdivisions。
                                   在darknet程式碼中,會將batch/subdivisions命名為batch。
height=416                         input影象的高
width
=416 Input影象的寬 channels=3 Input影象的通道數 momentum=0.9 動量 decay=0.0005 權重衰減正則項,防止過擬合 angle=0 通過旋轉角度來生成更多訓練樣本 saturation = 1.5 通過調整飽和度來生成更多訓練樣本 exposure = 1.5 通過調整曝光量來生成更多訓練樣本 hue
=.1 通過調整色調來生成更多訓練樣本 learning_rate=0.0001 初始學習率 max_batches = 45000 訓練達到max_batches後停止學習 policy=steps 調整學習率的policy,有如下policy:CONSTANT, STEP, EXP, POLY, STEPS, SIG, RANDOM steps=100,25000,35000 根據batch_num調整學習率 scales=10,.1,.1 學習率變化的比例,累計相乘 [convolutional] batch_normalize
=1 是否做BN filters=32 輸出多少個特徵圖 size=3 卷積核的尺寸 stride=1 做卷積運算的步長 pad=1 如果pad為0,padding由 padding引數指定。如果pad為1,padding大小為size/2 activation=leaky 啟用函式: logistic,loggy,relu,elu,relie,plse,hardtan,lhtan,linear,ramp,leaky,tanh,stair [maxpool] size=2 池化層尺寸 stride=2 池化步進 [convolutional] batch_normalize=1 filters=64 size=3 stride=1 pad=1 activation=leaky [maxpool] size=2 stride=2 ...... ...... ####### [convolutional] batch_normalize=1 size=3 stride=1 pad=1 filters=1024 activation=leaky [convolutional] batch_normalize=1 size=3 stride=1 pad=1 filters=1024 activation=leaky [route] the route layer is to bring finer grained features in from earlier in the network layers=-9 [reorg] the reorg layer is to make these features match the feature map size at the later layer. The end feature map is 13x13, the feature map from earlier is 26x26x512. The reorg layer maps the 26x26x512 feature map onto a 13x13x2048 feature map so that it can be concatenated with the feature maps at 13x13 resolution. stride=2 [route] layers=-1,-3 [convolutional] batch_normalize=1 size=3 stride=1 pad=1 filters=1024 activation=leaky [convolutional] size=1 stride=1 pad=1 filters=125 region前最後一個卷積層的filters數是特定的,計算公式為filter=num*(classes+5) 5的意義是5個座標,論文中的tx,ty,tw,th,to activation=linear [region] anchors = 1.08,1.19, 3.42,4.41, 6.63,11.38, 9.42,5.11, 16.62,10.52 預選框,可以手工挑選, 也可以通過k means 從訓練樣本中學出 bias_match=1 classes=20 網路需要識別的物體種類數 coords=4 每個box的4個座標tx,ty,tw,th num=5 每個grid cell預測幾個box,和anchors的數量一致。當想要使用更多anchors時需要調大num,且如果調大num後訓練時Obj趨近0的話可以嘗試調大object_scale softmax=1 使用softmax做啟用函式 jitter=.2 通過抖動增加噪聲來抑制過擬合 rescore=1 暫理解為一個開關,非0時通過重打分來調整l.delta(預測值與真實值的差) object_scale=5 柵格中有物體時,bbox的confidence loss對總loss計算貢獻的權重 noobject_scale=1 柵格中沒有物體時,bbox的confidence loss對總loss計算貢獻的權重 class_scale=1 類別loss對總loss計算貢獻的權重 coord_scale=1 bbox座標預測loss對總loss計算貢獻的權重 absolute=1 thresh = .6 random=0 random為1時會啟用Multi-Scale Training,隨機使用不同尺寸的圖片進行訓練。

darknet對應程式碼

找到cfg檔案解析的程式碼,選擇detector demo 作為入口

darknet.c檔案 main 函式開始

    } else if (0 == strcmp(argv[1], "detector")){
    run_detector(argc, argv);

Detector.c檔案 run_detector函式

char *prefix = find_char_arg(argc, argv, "-prefix", 0);
float thresh = find_float_arg(argc, argv, "-thresh", .24);
float hier_thresh = find_float_arg(argc, argv, "-hier", .5);
int cam_index = find_int_arg(argc, argv, "-c", 0);
int frame_skip = find_int_arg(argc, argv, "-s", 0);
if(argc < 4){
    fprintf(stderr, "usage: %s %s [train/test/valid] [cfg] [weights (optional)]\n", argv[0], argv[1]);
    return;
}
char *gpu_list = find_char_arg(argc, argv, "-gpus", 0);
char *outfile = find_char_arg(argc, argv, "-out", 0);
else if(0==strcmp(argv[2], "demo")) {
    list *options = read_data_cfg(datacfg);
    int classes = option_find_int(options, "classes", 20);
    char *name_list = option_find_str(options, "names", "data/names.list");
    char **names = get_labels(name_list);
    demo(cfg, weights, thresh, cam_index, filename, names, classes, frame_skip, prefix, hier_thresh);
}

read_data_cfg函式解析配置檔案,儲存到options指標。

class

int classes = option_find_int(options, "classes", 20);

classes為YOLO可識別的種類數

batch、learning_rate、momentum、decay和 subdivisions

demo.c檔案demo函式

net = parse_network_cfg(cfgfile);

Parser.c檔案 parse_network_cfg函式

list *sections = read_cfg(filename);
node *n = sections->front;
if(!n) error("Config file has no sections");
network net = make_network(sections->size - 1);
net.gpu_index = gpu_index;
size_params params;

section *s = (section *)n->val;
list *options = s->options;
if(!is_network(s)) error("First section must be [net] or [network]");
parse_net_options(options, &net);

parse_net_options函式

net->batch = option_find_int(options, "batch",1);
net->learning_rate = option_find_float(options, "learning_rate", .001);
net->momentum = option_find_float(options, "momentum", .9);
net->decay = option_find_float(options, "decay", .0001);
int subdivs = option_find_int(options, "subdivisions",1);
net->time_steps = option_find_int_quiet(options, "time_steps",1);
net->batch /= subdivs;
net->batch *= net->time_steps;
net->subdivisions = subdivs;
  • learning_rate為初始學習率,訓練時的真正學習率和學習率的策略及初始學習率有關。
  • momentum為動量,在訓練時加入動量可以幫助走出local minima 以及saddle point。
  • decay是權重衰減正則項,用來防止過擬合。

  • batch的值等於cfg檔案中的batch/subdivisions 再乘以time_steps。

  • time_steps在yolo預設的cfg中是沒有配置的,所以是預設值1。
    因此batch可以認為就是cfg檔案中的batch/subdivisions。

前面有提到batch的意義是每batch個樣本更新一次引數。

而subdivisions的意義在於降低對GPU memory的要求。
darknet將batch分割為subdivisions個子batch,每個子batch的大小為batch/subdivisions,並將子batch命名為batch。

我們看下訓練時和batch有關的程式碼

Detector.c檔案的train_detector函式

ifdef GPU

    if(ngpus == 1){
        loss = train_network(net, train);
    } else {
        loss = train_networks(nets, ngpus, train, 4);
    }
#else
    loss = train_network(net, train);
#endif

Network.c檔案的train_network函式

int batch = net.batch;
int n = d.X.rows / batch;
float *X = calloc(batch*d.X.cols, sizeof(float));
float *y = calloc(batch*d.y.cols, sizeof(float));

int i;
float sum = 0;
for(i = 0; i < n; ++i){
    get_next_batch(d, batch, i*batch, X, y);
    float err = train_network_datum(net, X, y);
    sum += err;
}

train_network_datum函式

*net.seen += net.batch;
......
......
forward_network(net, state);
backward_network(net, state);
float error = get_network_cost(net);
if(((*net.seen)/net.batch)%net.subdivisions == 0) update_network(net);

我們看到,只有((*net.seen)/net.batch)%net.subdivisions == 0時才會更新網路引數。
*net.seen是已經訓練過的子batch數,((*net.seen)/net.batch)%net.subdivisions的意義正是已經訓練過了多少個真正的batch。
policy、steps和scales

Parser.c檔案 parse_network_cfg函式

char *policy_s = option_find_str(options, "policy", "constant");
net->policy = get_policy(policy_s);
net->burn_in = option_find_int_quiet(options, "burn_in", 0);
if(net->policy == STEP){
    net->step = option_find_int(options, "step", 1);
    net->scale = option_find_float(options, "scale", 1);
} else if (net->policy == STEPS){
    char *l = option_find(options, "steps");   
    char *p = option_find(options, "scales");   
    if(!l || !p) error("STEPS policy must have steps and scales in cfg file");

    int len = strlen(l);
    int n = 1;
    int i;
    for(i = 0; i < len; ++i){
        if (l[i] == ',') ++n;
    }
    int *steps = calloc(n, sizeof(int));
    float *scales = calloc(n, sizeof(float));
    for(i = 0; i < n; ++i){
        int step    = atoi(l);
        float scale = atof(p);
        l = strchr(l, ',')+1;
        p = strchr(p, ',')+1;
        steps[i] = step;
        scales[i] = scale;
    }
    net->scales = scales;
    net->steps = steps;
    net->num_steps = n;
} else if (net->policy == EXP){
    net->gamma = option_find_float(options, "gamma", 1);
} else if (net->policy == SIG){
    net->gamma = option_find_float(options, "gamma", 1);
    net->step = option_find_int(options, "step", 1);
} else if (net->policy == POLY || net->policy == RANDOM){
    net->power = option_find_float(options, "power", 1);
}

get_policy函式

if (strcmp(s, "random")==0) return RANDOM;
if (strcmp(s, "poly")==0) return POLY;
if (strcmp(s, "constant")==0) return CONSTANT;
if (strcmp(s, "step")==0) return STEP;
if (strcmp(s, "exp")==0) return EXP;
if (strcmp(s, "sigmoid")==0) return SIG;
if (strcmp(s, "steps")==0) return STEPS;
fprintf(stderr, "Couldn't find policy %s, going with constant\n", s);
return CONSTANT;

學習率動態調整的策略有多種,YOLO預設使用的是steps。

yolo-voc.cfg檔案:

steps=100,25000,35000

scales=10,.1,.1

Network.c檔案get_current_rate函式

int batch_num = get_current_batch(net);
int i;
float rate;
switch (net.policy) {
    case CONSTANT:
        return net.learning_rate;
    case STEP:
        return net.learning_rate * pow(net.scale, batch_num/net.step);
    case STEPS:
        rate = net.learning_rate;
        for(i = 0; i < net.num_steps; ++i){
            if(net.steps[i] > batch_num) return rate;
            rate *= net.scales[i];
            //if(net.steps[i] > batch_num - 1 && net.scales[i] > 1) reset_momentum(net);
        }
        return rate;

get_current_batch獲取的是(*net.seen)/(net.batch*net.subdivisions),即真正的batch。

steps的每個階段是根據batch_num劃分的,根據配置檔案,學習率會在batch_num達到100、25000、35000時發生改變。

當前的學習率是初始學習率與當前階段及之前所有階段對應的scale的總乘積。

convolutional超引數載入

Parser.c檔案parse_network_cfg函式

LAYER_TYPE lt = string_to_layer_type(s->type);
        if(lt == CONVOLUTIONAL){
            l = parse_convolutional(options, params);

parse_convolutional函式

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");
ACTIVATION activation = get_activation(activation_s);

int batch,h,w,c;
h = params.h;
w = params.w;
c = params.c;
batch=params.batch;
if(!(h && w && c)) error("Layer before convolutional layer must output image.");
int batch_normalize = option_find_int_quiet(options, "batch_normalize", 0);

需要注意的是如果enable了pad,cfg檔案中的padding不會生效,實際的padding值為size/2。

random

YOLOv2新增了一些訓練技巧,Multi-Scale Training就是其中之一,如果random置為1,會啟用Multi-Scale Training。
啟用Multi-Scale Training時每10個Batch,網路會隨機地選擇一個新的圖片尺寸,由於使用的down samples是32,所以不同的尺寸大小也選擇為32的倍數{320,352…..608},最小320*320,最大608*608,網路會自動改變尺寸,並繼續訓練的過程。
這一策略讓網路在不同的輸入尺寸上都能達到一個很好的預測效果,同一網路能在不同解析度上進行檢測。當輸入圖片尺寸比較小的時候跑的比較快,輸入圖片尺寸比較大的時候精度高。

route 和 reorg

YOLOv2新增了Fine-Grained Features技巧,參考特徵金字塔和ResNet,把高解析度特徵與低解析度特徵聯絡在一起,從而增加對小物體的識別精度。

這裡寫圖片描述

借用一下ResNet的identity mappings示意圖
YOLOv2加上了一個Passthrough Layer來取得之前的某個26*26解析度的層的特徵。這個Passthrough layer把26 * 26的特徵圖與13 * 13的特徵圖聯絡在一起,把相鄰的特徵堆積在不同的Channel之中,類似與Resnet的Identity Mapping,從而把26*26*512變成13*13*2048。
route層起連線作用,reorg層來match特徵圖尺寸。

相關推薦

YOLO配置檔案理解以及解析過程

原文地址:點選這裡 如有侵權,聯絡刪除 YOLO配置檔案理解 [net] batch=64 每batch個樣本更新一次引數。 subdivisions=8

YOLO配置檔案理解

http://www.infocool.net/kb/WWW/201703/317548.html [ net]

Django讀取配置檔案的機制解析

django.conf.init.py class LazySettings(LazyObject): """ A lazy proxy for either global Django settings or a custom settings object.

卡爾曼濾波的理解以及推導過程

針對的系統為: 狀態方程       X(k)=AX(k-1)+Bu(k-1)+W(k-1) 測量方程       Z(k)=HX(k)+V(k)  &

hibernate配置檔案解釋以及增刪改查

配置檔案 hibernate核心配置檔案hibernate.cfg.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibe

Spring Boot Configuration 配置檔案讀取以及自定義配置檔案

新增configuration  maven依賴 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configurati

YOLO學習筆記】之YOLO配置檔案詳解

在YOLO初體驗中,應用到了一個字尾名為cfg的檔案,在darknet中有一個資料夾,下面有各種各樣的cfg檔案 這些cfg檔案都是YOLO的配置檔案,負責YOLO所需資料集的訓練工作,接下來,給大家詳細講解一下配置檔案。講解配置檔案,我以 yolov2-tiny.

Mybatis之Configuration初始化(配置檔案.xml的解析

原始碼解讀第一步我覺著應該從Mybatis如何解析配置檔案開始。 1.先不看跟Spring整合如何解析,先看從SqlSessionFactoryBuilder如果解析的。 1 String resouce = "conf.xml"; 2 InputStream is = Resources.getR

22.配置檔案讀取以及驗證(二)

獲取Document 尋找文件DTD的定義(EntityResolver) ​ 在驗證xml之前,需要找到這個xml的申明檔案(DTD or XSD), 在 dtd/xsd + 驗證模式的作用下,對xml進行驗證. 此dtd/xsd, 通常宣告為一網路地址,如

SpringBoot配置分析、獲取到SpringBoot配置檔案資訊以及幾種獲取配置檔案資訊的方式

SpringBoot的預設的配置檔案application.properties配置檔案。 1、第一種方式直接獲取到配置檔案裡面的配置資訊。 第二種方式是通過將已經注入到容器裡面的bean,然後再注入Environment這個bean進行獲取。具體操作如下所示: 1 package com.bie

spring xml配置檔案bean的解析定義

spring為解析xml建立bean提供了一種非常解藕的方式。 整體架構面向介面程式設計,AbstractApplicationContext的refresh方法被呼叫時,在重新整理BeanFactory的時候會解析配置檔案。框架提供了: 介面 org.springframework.beans.fact

udev配置檔案理解

!/bin/sh -e ### BEGIN INIT INFO # Provides: udev # Required-Start: mountvirtfs # Required-Stop: # Default-Start: S

《Hadoop》之"踽踽獨行"(九)Hadoop叢集的四個配置檔案的屬性解析

在啟動hadoop叢集的守護執行緒時,一定會載入並執行相關的class位元組碼檔案。通過common模組和hdfs模組裡的原始碼可以看到,它們讀取了相關的配置檔案。 hadoop-common-2.7.3-sources.jar下的org.apache.hadoop.conf.Configura

配置檔案方法以及處理編碼集為UTF-8步驟 Oracle資料庫的連線配置內含讀取配置

建配置檔案步驟: 右擊專案src -->New-->File--> db.properties(配置檔名) 處理編碼集為UTF-8步驟: 右擊 db.properties(配置檔

修改Keepalived配置檔案位置以及重定向Keepalived日誌的輸出路徑

上一篇博文主要講述瞭如何使用Keepalived實現tomcat伺服器的雙機熱備。這篇博文是對上一篇博文的擴充套件,主要講述如何修改Keepalived的預設配置檔案的路徑以及重定向Keepalived日誌的輸出路徑。關於如何安裝keepalived以及keepalived的

Linux網路介面配置檔案ifcfg-eth0解析配置

 在Windows上配置網路比較容易,有圖形化介面可操作。在Linux中往往是通過命令修改檔案的方式配置網路,因此不僅需要知道配置哪個檔案,還要知道檔案中每個配置引數的功能。在Redhat/Fedora等Linux中,網路配置檔案一般是/etc/sysconfig/netwo

Linux網路介面配置檔案ifcfg-eth0解析

        在Windows上配置網路比較容易,有圖形化介面可操作。在Linux中往往是通過命令修改檔案的方式配置網路,因此不僅需要知道配置哪個檔案,還要知道檔案中每個配置引數的功能。在Redhat/Fedora等Linux中,網路配置檔案一般是/etc/sysconf

nodejs-http 對form表單上傳檔案資料的解析過程

前幾天碰到了一個需求,允許接收前端使用者上傳的檔案。 當時為了解決問題索性就上github搜了下,找了一個基於nodejs的開發外掛。 後來功能實現後覺得意猶未盡,於是自己想試試去寫一個類似功能的外掛,方便以後拓展,然後就這麼開始了。 先來說說應用層的ht

XmlBeanDefinitionReader-----Spring原始碼解析 配置檔案裝載與解析

以下內容有部分摘自網路 步驟A. 讀取 Resource 檔案形成 Document 模型     類圖: XmlBeanFactory -> XmlBeanDefinitionReader     Spring 使用 XmlBeanDefinitionReade

Tomcat初始化方法中如何注入配置檔案內容以及獲取當前伺服器埠號

在使用tomcat監聽器初始化方法時,往往需要注入配置檔案中的某個內容,此時在初始化方法中使用spring註解是不可行的,可以採用Spring工具類獲取Bean,從而得到自己想要的值。這樣做需要新建一個實體類,屬性即為你想要獲取的內容,然後交給spring管理,實體類對