YOLOv3中的yolo_layer.c文件
这个文件实现了YOLOv3使用的损失函数,如果你想优化损失函数部分,绕不开它的。
损失函数包含两部分:定位损失(tx,ty,tw,th)和类别损失(c,C1,C2,C3...)。l.delta是一个一维数组指针,用来存储各种损失,计算完所有的损失后,平方和这些损失得到一个浮点数值,然后存储到l.loss中。l.loss是一个指向浮点型数值的指针。
#include "yolo_layer.h"
#include "activations.h"
#include "blas.h"
#include "box.h"
#include "cuda.h"
#include "utils.h"
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
//原文地址:https://blog.youkuaiyun.com/qq_33614902/article/details/85063287
layer make_yolo_layer(int batch, int w, int h, int n, int total, int *mask, int classes)
{
int i;
layer l = {0};
l.type = YOLO;
l.n = n;//每个cell提出n个boxes
l.total = total;//anchor的个数???(不确定诶)
l.batch = batch;//每个batch中含有的图片数
l.h = h;
l.w = w;
l.c = n*(classes + 4 + 1);//3*(80+4+1)
l.out_w = l.w;
l.out_h = l.h;
l.out_c = l.c;
l.classes = classes;//训练时的物体类别总数
l.cost = calloc(1, sizeof(float));//指向float型的指针,大小为1,只能存储一个float类型的数值
l.biases = calloc(total*2, sizeof(float));//保存先验框的宽度和高度,所以乘2
if(mask) l.mask = mask;//mask和用到第几个先验框有关,取值为0-9。比如,mask_n=1,先验框的宽和高是(biases[2*mask_n],biases[2*mask_n+1])
else{
l.mask = calloc(n, sizeof(int));
for(i = 0; i < n; ++i){
l.mask[i] = i;
}
}
l.bias_updates = calloc(n*2, sizeof(float));
l.outputs = h*w*n*(classes + 4 + 1);//检测器对一张图片预测的所有参数。h*w为cell的个数,n表示每个cell对应n的pre boxes
l.inputs = l.outputs;
l.truths = 90*(4 + 1);//每张图片含有的GT参数的个数,90表示一张图片最多有90个GT
l.delta = calloc(batch*l.outputs, sizeof(float));
l.output = calloc(batch*l.outputs, sizeof(float));
for(i = 0; i < total*2; ++i){
l.biases[i] = .5;
}
l.forward = forward_yolo_layer;
l.backward = backward_yolo_layer;
#ifdef GPU
l.forward_gpu = forward_yolo_layer_gpu;
l.backward_gpu = backward_yolo_layer_gpu;
l.output_gpu = cuda_make_array(l.output, batch*l.outputs);
l.delta_gpu = cuda_make_array(l.delta, batch*l.outputs);
#endif
fprintf(stderr, "yolo\n");
srand(0);
return l;
}
void resize_yolo_layer(layer *l, int w, int h)
{
l->w = w;
l->h = h;
l->outputs = h*w*l->n*(l->classes + 4 + 1);
l->inputs = l->outputs;
l->output = realloc(l->output, l->batch*l->outputs*sizeof(float));
l->delta = realloc(l->delta, l->batch*l->outputs*sizeof(float));
#ifdef GPU
cuda_free(l->delta_gpu);
cuda_free(l->output_gpu);
l->delta_gpu = cuda_make_array(l->delta, l->batch*l->outputs);
l->output_gpu = cuda_make_array(l->output, l->batch*l->outputs);
#endif
}
// box pred = get_yolo_box(l.output, l.biases, l.mask[n], box_index, i, j, l.w, l.h, net.w, net.h, l.w*l.h);
box get_yolo_box(float *x, float *biases, int n, int index, int i, int j, int lw, int lh, int w, int h, int stride)
{
//i,j表示cell的位置(相当于公式中的cx,cy),biases是先验框的宽和高,返回的box是比例值(都除以了w,h)。具体公式见YOLOv3中2.1部分。
//l.output中存储的tx,ty是cell内的相对距离,大小为[0,1]
//这里告诉我们,我们的网络不是直接预测出来的回归框,而是预测的(tx,ty,tw,th),然后再用此公式转换。
box b