解析网络配置文件,初始化网络参数:
parse.c/parse_network_cfg()——>parse.c/parse_network_cfg_custom()——>parse.c/read_cfg()——>list_insert()
先看几个重要的结构体:
- list.h/list结构体
typedef struct list{
int size; //链表中节点的个数
node *front; //front节点指针
node *back; //back节点指针
} list;
- list.h/node结构体
typedef struct node{
void *val; //由具体存放的数据类型决定,如sections中node->val就是section*类型,而section->options->val就是kvp*类型
struct node *next; //指向后一个节点的指针
struct node *prev; //指向前一个节点的指针
} node;
- parse.c/section结构体
typedef struct{
char *type; //层类型
list *options; //层具体参数的链表
}section;
- option_list.h/kvp结构体
typedef struct{
char *key; //例:batch_normalize=1,batch_normalize就是key,1就是val
char *val;
int used; //?暂时不知道这个变量的作用
} kvp;
现在开始走流程:
network parse_network_cfg(char *filename)
{
return parse_network_cfg_custom(filename, 0);
}
network parse_network_cfg_custom(char *filename, int batch)
{
list *sections = read_cfg(filename); //读入网络配置文件存入一个链表,链表的每个节点存放一个section结构体和指向前后
//节点的指针,section存放单个layer的类型和一个存放具体参数的链表类似于存放数据配置文件的那个链表
//看到这里请转到下一个代码段read_cfg,等会再回来~
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; //创建新的layer后,用params来更新当前layer的输入图像的w,h,c,inputs
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);
params.h = net.h;
params.w = net.w;
params.c = net.c;
params.inputs = net.inputs;
if (batch > 0) net.batch = batch;
params.batch = net.batch; //每一层的batch不变
params.time_steps = net.time_steps;
params.net = net;
float bflops = 0;
size_t workspace_size = 0;
n = n->next; //
int count = 0;
free_section(s);
fprintf(stderr, "layer filters size input output\n"); //以这个格式输出每层的配置参数,第二种输出参数出世!!!
while(n){
params.index = count;
fprintf(stderr, "%4d ", count);
s = (section *)n->val;
options = s->options;
layer l = {0}; //创建新的layer
LAYER_TYPE lt = string_to_layer_type(s->type); //将layer_type从string转为枚举类型
if(lt == CONVOLUTIONAL){
l = parse_convolutional(options, params);
}else if(lt == LOCAL){
l = parse_local(options, params);
}else if(lt == ACTIVE){
l = parse_activation(options, params);
}else if(lt == RNN){
l = parse_rnn(options, params);
}else if(lt == GRU){
l = parse_gru(options, params);
}else if(lt == CRNN){
l = parse_crnn(options, params);
}else if(lt == CONNECTED){
l = parse_connected(options, params);
}else if(lt == CROP){
l = parse_crop(options, params);
}else if(lt == COST){
l = parse_cost(options, params);
}else if(lt == REGION){
l = parse_region(options, params);
}else if (lt == YOLO) {
l = parse_yolo(options, params);
}else if(lt == DETECTION){
l = parse_detection(options, params);
}else if(lt == SOFTMAX){
l = parse_softmax(options, params);
net.hierarchy = l.softmax_tree;
}else if(lt == NORMALIZATION){
l = parse_normalization(options, params);
}else if(lt == BATCHNORM){
l = parse_batchnorm(options, params);
}else if(lt == MAXPOOL){
l = parse_maxpool(options, params);
}else if(lt == REORG){
l = parse_reorg(options, params); }
else if (lt == REORG_OLD) {
l = parse_reorg_old(options, params);
}else if(lt == AVGPOOL){
l = parse_avgpool(options, params);
}else if(lt == ROUTE){
l = parse_route(options, pa