tips:
src/network.h(darknet中网络结构体:network)
typedef struct network{
int n; // 网络总层数(make_network()时赋值)
int batch; // parse_net_options()中赋值:一个batch含有的图片张数,下面还有个subdivisions参数,暂时没搞清楚有什么用处,
// 总之此处的batch*subdivision才等于网络配置文件中指定的batch值
int *seen; // 目前已经读入的图片张数(网络已经处理的图片张数)(在make_network()中动态分配内存)
float epoch;
int subdivisions; // parse_net_options()中赋值,如上batch注释
float momentum; // parse_net_options()中赋值
float decay; // parse_net_options()中赋值
layer *layers; // 存储网络所有的层,在make_network()中动态分配内存
float *output;
learning_rate_policy policy;
float learning_rate; // parse_net_options()中赋值
float gamma;
float scale;
float power;
int time_steps;
int step;
int max_batches;
float *scales;
int *steps;
int num_steps;
int burn_in;
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;
int center;
float angle;
float aspect;
float exposure;
float saturation;
float hue;
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;
#ifdef GPU
float *input_gpu;
float *truth_gpu;
float *delta_gpu;
float *output_gpu;
#endif
} network;
打印输入数据input data
src/network.c
float *network_predict(network *net, float *input)函数
float *network_predict(network *net, float *input)
{
network orig = *net;
net->input = input;
//******************************************************
FILE* fpt = fopen("input_data.txt", "w");
for (int ii = 0; ii < net->inputs; ii++){
fprintf(fpt, "%f\n", input[ii]);
}
fclose(fpt);
//*******************************************************
net->truth = 0;
net->train = 0;
net->delta = 0;
forward_network(net);
float *out = net->output;
*net = orig;
return out;
}
打印每一层输出
src/network.c
forward_network_gpu(network *netp)函数
#ifdef GPU
void forward_network_gpu(network *netp)
{
network net = *netp;
cuda_set_device(net.gpu_index);
cuda_push_array(net.input_gpu, net.input, net.inputs*net.batch);
if(net.truth){
cuda_push_array(net.truth_gpu, net.truth, net.truths*net.batch);
}
printf("%d\n",net.n);
for(int i = 0; i < net.n; ++i){
printf("%d\n",i);
net.index = i;
layer l = net.layers[i];
if(l.delta_gpu){
fill_gpu(l.outputs * l.batch, 0, l.delta_gpu, 1);
}
l.forward_gpu(l, net);
net.input_gpu = l.output_gpu;
//*****************************************************
//size_t size = l.n; //bias
//size_t size = l.nweights; //weights
size_t size = l.outputs;
float* x = (float*)malloc(size*sizeof(float));
//cuda_pull_array(l.weights_gpu, x, size);
//cuda_pull_array(l.biases_gpu, x, size);
cuda_pull_array(l.output_gpu, x, size);
char name[100]="output_", index[10];
sprintf(index, "%d.txt", i);
strcat(name, index);
FILE* txt = fopen(name, "w");
for (int ii = 0; ii < size; ii++){
fprintf(txt, "%f\n", x[ii]);
}
fclose(txt);
//******************************************************
net.input = l.output;
if(l.truth) {
net.truth_gpu = l.output_gpu;
net.truth = l.output;
}
}
pull_network_output(netp);
calc_network_cost(netp);
}
打印权重conv
src/network.c
forward_network_gpu(network *netp)函数
#ifdef GPU
void forward_network_gpu(network *netp)
{
network net = *netp;
cuda_set_device(net.gpu_index);
cuda_push_array(net.input_gpu, net.input, net.inputs*net.batch);
if(net.truth){
cuda_push_array(net.truth_gpu, net.truth, net.truths*net.batch);
}
printf("%d\n",net.n);
for(int i = 0; i < net.n; ++i){
printf("%d\n",i);
net.index = i;
layer l = net.layers[i];
if(l.delta_gpu){
fill_gpu(l.outputs * l.batch, 0, l.delta_gpu, 1);
}
l.forward_gpu(l, net);
net.input_gpu = l.output_gpu;
//*****************************************************
//size_t size = l.n; //bias
size_t size = l.nweights; //weights
//size_t size = l.outputs;
float* x = (float*)malloc(size*sizeof(float));
cuda_pull_array(l.weights_gpu, x, size);
//cuda_pull_array(l.biases_gpu, x, size);
//cuda_pull_array(l.output_gpu, x, size);
char name[100]="conv_", index[10];
sprintf(index, "%d.txt", i);
strcat(name, index);
FILE* txt = fopen(name, "w");
for (int ii = 0; ii < size; ii++){
fprintf(txt, "%f\n", x[ii]);
}
fclose(txt);
//******************************************************
net.input = l.output;
if(l.truth) {
net.truth_gpu = l.output_gpu;
net.truth = l.output;
}
}
pull_network_output(netp);
calc_network_cost(netp);
}
打印权重bias
src/network.c
forward_network_gpu(network *netp)函数
#ifdef GPU
void forward_network_gpu(network *netp)
{
network net = *netp;
cuda_set_device(net.gpu_index);
cuda_push_array(net.input_gpu, net.input, net.inputs*net.batch);
if(net.truth){
cuda_push_array(net.truth_gpu, net.truth, net.truths*net.batch);
}
printf("%d\n",net.n);
for(int i = 0; i < net.n; ++i){
printf("%d\n",i);
net.index = i;
layer l = net.layers[i];
if(l.delta_gpu){
fill_gpu(l.outputs * l.batch, 0, l.delta_gpu, 1);
}
l.forward_gpu(l, net);
net.input_gpu = l.output_gpu;
//*****************************************************
size_t size = l.n; //bias
//size_t size = l.nweights; //weights
//size_t size = l.outputs;
float* x = (float*)malloc(size*sizeof(float));
//cuda_pull_array(l.weights_gpu, x, size);
cuda_pull_array(l.biases_gpu, x, size);
//cuda_pull_array(l.output_gpu, x, size);
char name[100]="bias_", index[10];
sprintf(index, "%d.txt", i);
strcat(name, index);
FILE* txt = fopen(name, "w");
for (int ii = 0; ii < size; ii++){
fprintf(txt, "%f\n", x[ii]);
}
fclose(txt);
//******************************************************
net.input = l.output;
if(l.truth) {
net.truth_gpu = l.output_gpu;
net.truth = l.output;
}
}
pull_network_output(netp);
calc_network_cost(netp);
}
可参考链接:
http://yuenshome.space/timeline/2018-11/yolov2-region-source-code/