原文出处
1. src/network.h(darknet中网络结构体:network)
typedef struct network {
int n; // 网络总层数
int batch;//一张图像被划分成batch x batch个小方块
uint64_t *seen; // 目前已经读入的图片张数(网络已经处理的图片张数)(在make_network()中动态分配内存)
int *t;
float epoch;
int subdivisions;
layer *layers;// 存储网络所有的层,在make_network()中动态分配内存
float *output;
learning_rate_policy policy;
float learning_rate; //学习率
float learning_rate_min;
float learning_rate_max;
int batches_per_cycle;
int batches_cycle_mult;
float momentum;
float decay;
float gamma;
float scale;
float power;
int time_steps;
int step;
int max_batches;
int num_boxes;
int train_images_num;
float *seq_scales;
float *scales;
int *steps;
int num_steps;
int burn_in;
int cudnn_half;
int adam;
float B1;
float B2;
float eps;
int inputs; // 一张输入图片的元素个数,如果网络配置文件中未指定,则默认等于net->h * net->w * net->c,在parse_net_options()中赋值
int outputs;// 一张输入图片对应的输出元素个数,对于一些网络,可由输入图片的尺寸及相关参数计算出,比如卷积层,可以
通过输入尺寸以及跨度、核大小计算出; 对于另一些尺寸,则需要通过网络配置文件指定,如未指定,取默认值1,比如全连接层
int truths;
int notruth;
int h, w, c;
int max_crop;
int min_crop;
float max_ratio;
float min_ratio;
int center;
int flip; // horizontal flip 50% probability augmentaiont for classifier training (default = 1)
int blur;
int mixup;
int letter_box;
float angle;
float aspect;
float exposure;
float saturation;
float hue;
int random;
int track;
int augment_speed;
int sequential_subdivisions;
int init_sequential_subdivisions;
int current_subdivision;
int try_fix_nan;
int gpu_index;
tree *hierarchy;
float *input;// 中间变量,用来暂存某层网络的输入(包含一个batch的输入,比如某层网络完成前向,将其输出赋给该变量,作为下一层的输入,可以参看network.c中的forward_network()与backward_network()两个函数),
// 当然,也是网络接受最原始输入数据(即第一层网络接收的输入)的变量(比如在图像检测训练中,最早在train_detector()->train_network()->get_next_batch()函数中赋值)
float *truth; // 中间变量,与上面的input对应,用来暂存input数据对应的标签数据(真实数据)
float *delta;// 中间变量,用来暂存某层网络的敏感度图(反向传播处理当前层时,用来存储上一层的敏感度图,因为当前层会计算部分上一层的敏感度图,可以参看network.c中的backward_network()函数),
// net.delta并没有在创建网络之初就为其动态分配了内存,而是等到反向传播时,直接将其等于某一层的l.delta(l.delta是在创建每一层网络之初就动态为其分配了内存),这才为net.delta分配了内存,
// 如果没有令net.delta=l.delta,则net.delta是未定义的(没有动态分配内存的)
float *workspace;// 整个网络的工作空间,其元素个数为所有层中最大的l.workspace_size = l.out_h*l.out_w*l.size*l.size*l.c
// (在make_convolutional_layer()计算得到workspace_size的大小,在parse_network_cfg()中动态分配内存,
// 此值对应未使用gpu时的情况),该变量貌似不轻易被释放内存,目前只发现在network.c的resize_network()函数对其进行了释放。
// net.workspace充当一个临时工作空间的作用,存储临时所需要的计算参数,比如每层单张图片重排后的结果
// (这些参数马上就会参与卷积运算),一旦用完,就会被马上更新(因此该变量的值的更新频率比较大)
int train; // 标志参数,网络是否处于训练阶段,如果是,则值为1(这个参数一般用于训练与测试有不同操作的情况,比如dropout层,对于训练,才需要进行forward_dropout_layer()函数,对于测试,不需要进入到该函数)
int index;// 标志参数,当前网络的活跃层(活跃包括前向和反向,可参考network.c中forward_network()与backward_network()函数)
float *cost;
float clip;
#ifdef GPU
//float *input_gpu;
//float *truth_gpu;
float *delta_gpu;
float *output_gpu;
float *input_state_gpu;
float *input_pinned_cpu;
int input_pinned_cpu_flag;
float **input_gpu;
float **truth_gpu;
float **input16_gpu;
float **output16_gpu;
size_t *max_input16_size;
size_t *max_output16_size;
int wait_stream;
#endif
} network;
2. src/layer.h(darknet中的每一层操作的结构体)
struct layer {
LAYER_TYPE type;// 网络层的类型,枚举类型,取值比如DROPOUT,CONVOLUTIONAL,MAXPOOL分别表示dropout层,卷积层,最大池化层,可参见LAYER_TYPE枚举类型的定义
ACTIVATION activation; //激活函数的类型
COST_TYPE cost_type;//损失函数的类型
void(*forward) (struct layer, struct network_state);
void(*backward) (struct layer, struct network_state);
void(*update) (struct layer, int, float, float, float);
void(*forward_gpu) (struct layer, struct network_state);
void(*backward_gpu) (struct layer, struct network_state);
void(*update_gpu) (struct layer, int, float, float, float);
layer *share_layer;
int batch_normalize;
int shortcut;
int batch;
int forced;
int flipped;
int inputs;
int outputs;
int nweights;
int nbiases;
int extra;
int truths;
int h, w, c; // 该层输入图片的高、宽、通道数(一般在各网络层构建函数中赋值,比如make_connected_layer()),
// 第一层网络的h,w,c就是网络初始能够的接收的图片尺寸,而后每一层的h,w,c都与自动匹配上一层相应的输出参数,
// 不再需要配置文件指定(参见parse_network_cfg(),在构建每一层后,会更新params.h,params.w,params.c及params.inputs为上一层相应的输出参数),
// 对于全连接层,h,w直接置为1,c置为l.inputs(参见make_connected_layer())
int out_h, out_w, out_c;// 该层输出图片的高、宽、通道数(一般在各网络层构建函数中赋值,比如make_connected_layer()),
// 对于卷积层,可由上面的h,w,c以及卷积核尺寸、跨度计算出;对于全连接层,out_h,out_w的值直接置为1,
// out_c直接置为l.outputs(参见make_connected_layer())
int n; // 对于卷积层,该参数表示卷积核个数,等于out_c,其值由网络配置文件指定;对于region_layerc层,该参数等于配置文件中的num值
// (该参数通过make_region_layer()函数赋值,而在parser.c中调用的make_region_layer()函数),
// 可以在darknet/cfg文件夹下执行命令:grep num *.cfg便可以搜索出所有设置了num参数的网络,这里面包括yolo.cfg等,其值有
// 设定为3,5,2的,该参数就是Yolo论文中的B,也就是一个cell中预测多少个box。
int max_boxes;
int groups;
int size; // 核尺寸(比如卷积核,池化核等)
int side;
int stride;//步长
int dilation;
int maxpool_depth;
int out_channels;
int reverse;
int flatten;
int spatial;
int pad;// 该层对输入数据四周的补0长度(现在发现在卷积层,最大池化层中有用到该参数),一般在构建具体网络层时赋值(比如make_maxpool_layer()中)
int sqrt;
int sqrt;
int flip;
int index;
int binary;
int xnor;
int peephole;
int use_bin_output;
int steps;
int state_constrain;
int hidden;
int truth;
float smooth;
float dot;
float angle;
float jitter;
float saturation;
float exposure;
float shift;
float ratio;
float learning_rate_scale;
float clip;
int focal_loss;
int noloss;
int softmax;
int classes;// 物体类别种数,一个训练好的网络,只能检测指定所有物体类别中的物体,比如yolo9000.cfg,设置该值为9418,
// 也就是该网络训练好了之后可以检测9418种物体。该参数由网络配置文件指定。目前在作者给的例子中,
// 有设置该值的配置文件大都是检测模型,纯识别的网络模型没有设置该值,我想是因为检测模型输出的一般会为各个类别的概率,
// 所以需要知道这个种类数目,而识别的话,不需要知道某个物体属于这些所有类的具体概率,因此可以不知道。
int coords; // 这个参数一般用在检测模型中,且不是所有层都有这个参数,一般在检测模型最后一层有,比如region_layer层,该参数的含义
// 是定位一个物体所需的参数个数,一般为4个,包括物体所在矩形框中心坐标x,y两个参数以及矩形框长宽w,h两个参数,
// 可以在darknet/cfg文件夹下,执行grep coords *.cfg,会搜索出所有使用该参数的模型,并可看到该值都设置位4
int background;
int rescore;
int objectness;
int does_cost;
int joint;
int noadjust;
int reorg;
int log;
int tanh;
int *mask;
int total;
float bflops;
int adam;
float B1;
float B2;
float eps;
int t;
float alpha;
float beta;
float kappa;
float coord_scale;
float object_scale;
float noobject_scale;
float mask_scale;
float class_scale;
int bias_match;
int random;
float ignore_thresh;
float truth_thresh;
float thresh;
float focus;
int classfix;
int absolute;
int assisted_excitation;
int onlyforward;
int stopbackward;
int dontload;
int dontsave;
int dontloadscales;
int numload;
float temperature;
float probability;
float scale;
char * cweights;
int * indexes;
int * input_layers;
int * input_sizes;
int * map;
int * counts;
float ** sums;
float * rand;
float * cost;
float * state;
float * prev_state;
float * forgot_state;
float * forgot_delta;
float * state_delta;
float * combine_cpu;
float * combine_delta_cpu;
float *concat;
float *concat_delta;
float *binary_weights;
float *biases;
float *bias_updates;
float *scales;
float *scale_updates;
float *weights; // 当前层所有权重系数(连接当前层和上一层的系数,但记在当前层上),对于卷积层,维度为l.n*l.c*l.size*l.size,即卷积核个数乘以卷积核尺寸再乘以输入通道数(各个通道上的权重系数独立不一样);
// 对于全连接层,维度为单张图片输入与输出元素个数之积inputs*outputs,一般在各网络构建函数中动态分配内存(比如make_connected_layer())
float *weight_updates;
float scale_x_y;
float iou_normalizer;
float cls_normalizer;
IOU_LOSS iou_loss;
char *align_bit_weights_gpu;
float *mean_arr_gpu;
float *align_workspace_gpu;
float *transposed_align_workspace_gpu;
int align_workspace_size;
char *align_bit_weights;
float *mean_arr;
int align_bit_weights_size;
int lda_align;
int new_lda;
int bit_align;
float *col_image;
float * delta;
float * output;// 存储该层所有的输出,维度为l.out_h * l.out_w * l.out_c * l.batch,可知包含整个batch输入图片的输出,一般在构建具体网络层时动态分配内存(比如make_maxpool_layer()中)。
// 按行存储:每张图片按行铺排成一大行,图片间再并成一行。
float * output_sigmoid;
int delta_pinned;
int output_pinned;
float * loss;
float * squared;
float * norms;
float * spatial_mean;
float * mean;
float * variance;
float * mean_delta;
float * variance_delta;
float * rolling_mean;
float * rolling_variance;
float * x;
float * x_norm;
float * m;
float * v;
float * bias_m;
float * bias_v;
float * scale_m;
float * scale_v;
float *z_cpu;
float *r_cpu;
float *h_cpu;
float *stored_h_cpu;
float * prev_state_cpu;
float *temp_cpu;
float *temp2_cpu;
float *temp3_cpu;
float *dh_cpu;
float *hh_cpu;
float *prev_cell_cpu;
float *cell_cpu;
float *f_cpu;
float *i_cpu;
float *g_cpu;
float *o_cpu;
float *c_cpu;
float *stored_c_cpu;
float *dc_cpu;
float *binary_input;
uint32_t *bin_re_packed_input;
char *t_bit_input;
struct layer *input_layer;
struct layer *self_layer;
struct layer *output_layer;
struct layer *reset_layer;
struct layer *update_layer;
struct layer *state_layer;
struct layer *input_gate_layer;
struct layer *state_gate_layer;
struct layer *input_save_layer;
struct layer *state_save_layer;
struct layer *input_state_layer;
struct layer *state_state_layer;
struct layer *input_z_layer;
struct layer *state_z_layer;
struct layer *input_r_layer;
struct layer *state_r_layer;
struct layer *input_h_layer;
struct layer *state_h_layer;
struct layer *wz;
struct layer *uz;
struct layer *wr;
struct layer *ur;
struct layer *wh;
struct layer *uh;
struct layer *uo;
struct layer *wo;
struct layer *vo;
struct layer *uf;
struct layer *wf;
struct layer *vf;
struct layer *ui;
struct layer *wi;
struct layer *vi;
struct layer *ug;
struct layer *wg;
tree *softmax_tree;
size_t workspace_size;
#ifdef GPU
int *indexes_gpu;
float *z_gpu;
float *r_gpu;
float *h_gpu;
float *stored_h_gpu;
float *temp_gpu;
float *temp2_gpu;
float *temp3_gpu;
float *dh_gpu;
float *hh_gpu;
float *prev_cell_gpu;
float *prev_state_gpu;
float *last_prev_state_gpu;
float *last_prev_cell_gpu;
float *cell_gpu;
float *f_gpu;
float *i_gpu;
float *g_gpu;
float *o_gpu;
float *c_gpu;
float *stored_c_gpu;
float *dc_gpu;
// adam
float *m_gpu;
float *v_gpu;
float *bias_m_gpu;
float *scale_m_gpu;
float *bias_v_gpu;
float *scale_v_gpu;
float * combine_gpu;
float * combine_delta_gpu;
float * forgot_state_gpu;
float * forgot_delta_gpu;
float * state_gpu;
float * state_delta_gpu;
float * gate_gpu;
float * gate_delta_gpu;
float * save_gpu;
float * save_delta_gpu;
float * concat_gpu;
float * concat_delta_gpu;
float *binary_input_gpu;
float *binary_weights_gpu;
float *bin_conv_shortcut_in_gpu;
float *bin_conv_shortcut_out_gpu;
float * mean_gpu;
float * variance_gpu;
float * rolling_mean_gpu;
float * rolling_variance_gpu;
float * variance_delta_gpu;
float * mean_delta_gpu;
float * col_image_gpu;
float * x_gpu;
float * x_norm_gpu;
float * weights_gpu;
float * weight_updates_gpu;
float * weight_change_gpu;
float * weights_gpu16;
float * weight_updates_gpu16;
float * biases_gpu;
float * bias_updates_gpu;
float * bias_change_gpu;
float * scales_gpu;
float * scale_updates_gpu;
float * scale_change_gpu;
float * output_gpu;
float * output_sigmoid_gpu;
float * loss_gpu;
float * delta_gpu;
float * rand_gpu;
float * squared_gpu;
float * norms_gpu;
#ifdef CUDNN
cudnnTensorDescriptor_t srcTensorDesc, dstTensorDesc;
cudnnTensorDescriptor_t srcTensorDesc16, dstTensorDesc16;
cudnnTensorDescriptor_t dsrcTensorDesc, ddstTensorDesc;
cudnnTensorDescriptor_t dsrcTensorDesc16, ddstTensorDesc16;
cudnnTensorDescriptor_t normTensorDesc, normDstTensorDesc, normDstTensorDescF16;
cudnnFilterDescriptor_t weightDesc, weightDesc16;
cudnnFilterDescriptor_t dweightDesc, dweightDesc16;
cudnnConvolutionDescriptor_t convDesc;
cudnnConvolutionFwdAlgo_t fw_algo, fw_algo16;
cudnnConvolutionBwdDataAlgo_t bd_algo, bd_algo16;
cudnnConvolutionBwdFilterAlgo_t bf_algo, bf_algo16;
cudnnPoolingDescriptor_t poolingDesc;
#endif // CUDNN
#endif // GPU
};