YOLO算法的调整与优化

来源:互联网 发布:python教程书籍下载 编辑:程序博客网 时间:2024/04/28 17:18

一. 代码篇

1.1 引入const引用形参改善代码效率

举个栗子:
在convolutional_layer.c文件的convolutional_out_height函数中:

/***  根据输入图像的高度(h),两边补0的个数(pad),卷积核尺寸(size)以及跨度(stride)计算输出的特征图的高度**  输入:l    卷积层,包含该卷积层的所有参数,实际这里没有必要输入整个l,因为只需要到其中的四个参数而已**  输出:int类型,输出图像的高度**  说明:这个函数的实现应该可以进一步改善一下,虽然这个函数只是在最初构建网络时调用一次,之后就不调用了,不怎么影响性能,**       但输入整个l实在不妥(l比较大,按值传递复制过程比较冗长),要么就只输入用到的四个参数,要么传入l的指针,**       并且不需要返回值了,直接在函数内部为l.out_h赋值*/int convolutional_out_height(convolutional_layer l)

若改成:

int convolutional_out_height(const convolutional_layer &l)
是否更加合理?

1.2 指针释放空间后最好做置0处理

举个栗子:
在文件layer.c中的void free_layer(layer l)函数中

void free_layer(layer l){...    if (l.indexes)        free(l.indexes);    **l.indexes = NULL;**    if (l.rand)           free(l.rand);    **l.rand = NULL;**    if (l.cost)           free(l.cost);    **l.cost = NULL;**    if (l.biases)         free(l.biases);    **l.biases = NULL;**    if (l.weights)        free(l.weights);    **l.weights = NULL;**...}

1.3 使用strncmp而不是strcmp

举个栗子:

/*  return (strcmp(s->type, "[net]") == 0        || strcmp(s->type, "[network]") == 0);*/   return (strncmp(s->type, "[net]", strlen("[net]")) == 0        || strncmp(s->type, "[network]", strlen("[network]")) == 0);

二. 算法加速篇

2.1 引入定点数的优化

关于定点数的理论知识,可以参考我的博客:

定点数与浮点数

具体的定点数转换公式如下:
一般,取q=12

/* The basic operations performed on two numbers a and b of fixed point qformat returning the answer in q format */#define FADD(a, b)     ((a) + (b))#define FSUB(a, b)     ((a) - (b))//#define FMUL(a, b, q)  (((a)*(b))>>(q))#define FMUL(a, b, q)  ((long)((a)*(b))>>(q))#define FDIV(a, b, q)  (((a)<<(q))/(b))/* The basic operation where a is of fixed point q format and b isan integer */#define FADDI(a, b, q)  ((a) + ((b)<<(q)))#define FSUBI(a, b, q) ((a) - ((b)<<(q)))#define FMULI(a, b)    ((a)*(b))#define FDIVI(a, b)    ((a)/(b))/* convert a from q1 format to q2 format */#define FCONV(a, q1, q2)  (((q2) > (q1)) ? (a)<<((q2)-(q1)) : (a)>>((q1) - (q2)))/* the general operation between a in q1 format and b in q2 formatreturning the result in q3 format */#define FADDG(a, b, q1, q2, q3)  (FCONV(a, q1, q3) + FCONV(b, q2, q3))#define FSUBG(a, b, q1, q2, q3)  (FCONV(a, q1, q3) - FCONV(b, q2, q3))#define FMULG(a, b, q1, q2, q3)   FCONV((a)*(b), (q1)+(q2), q3)#define FDIVG(a, b, q1, q2, q3)  (FCONV(a, q1, (q2) + (q3))/(b))/* convert to and from floating point */#define TOFIX(d, q)  ((int) ( (d)*(double) (1<<(q)) ))#define TOFLT(a, q)  (  (double)(a) / (double)(1<<(q)) )

2.2 在参数矩阵中引入稀疏矩阵的存储方式

参考博客:稀疏矩阵存储格式总结+存储效率对比:COO,CSR,DIA,ELL,HYB

Coordinate(COO)



这是最简单的一种格式,每一个元素需要用一个三元组来表示,分别是(行号,列号,数值),对应上图右边的一列。这种方式简单,但是记录单信息多(行列),每个三元组自己可以定位,因此空间不是最优。

Compressed Sparse Row (CSR)



CSR是比较标准的一种,也需要三类数据来表达:数值,列号,以及行偏移。CSR不是三元组,而是整体的编码方式。数值和列号与COO一致,表示一个元素以及其列号,行偏移表示某一行的第一个元素在values里面的起始偏移位置。如上图中,第一行元素1是0偏移,第二行元素2是2偏移,第三行元素5是4偏移,第4行元素6是7偏移。在行偏移的最后补上矩阵总的元素个数,本例中是9。

CSC是和CSR相对应的一种方式,即按列压缩的意思。

ELLPACK (ELL)



用两个和原始矩阵相同行数的矩阵来存:第一个矩阵存的是列号,第二个矩阵存的是数值,行号就不存了,用自身所在的行来表示;这两个矩阵每一行都是从头开始放,如果没有元素了就用个标志比如*结束。上图中间矩阵有误,第三行应该是 0 2 3。

注:这样如果某一行很多元素,那么后面两个矩阵就会很胖,其他行结尾*很多,浪费。可以存成数组,比如上面两个矩阵就是:

0 1 * 1 2 * 0 2 3 * 1 3 *

1 7 * 2 8 * 5 3 9 * 6 4 *

但是这样要取一行就比较不方便了

Diagonal (DIA)



对角线存储法,按对角线方式存,列代表对角线,行代表行。省略全零的对角线。(从左下往右上开始:第一个对角线是零忽略,第二个对角线是5,6,第三个对角线是零忽略,第四个对角线是1,2,3,4,第五个对角线是7,8,9,第六第七个对角线忽略)。

这里行对应行,所以5和6是分别在第三行第四行的,前面补上无效元素*。如果对角线中间有0,存的时候也需要补0,所以如果原始矩阵就是一个对角性很好的矩阵那压缩率会非常高,比如下图,但是如果是随机的那效率会非常糟糕。

Hybrid (HYB) ELL + COO



为了解决ELL中提到的,如果某一行特别多,造成其他行的浪费,那么把这些多出来的元素(比如第三行的9,其他每一行最大都是2个元素)用COO单独存储。

typedef struct _unified_matrix     UM;typedef struct _unified_matrix  _dense_matrix;typedef _dense_matrix DM;typedef struct _unified_matrix  _compressed_sparse_matrix;typedef _compressed_sparse_matrix CSPM;typedef struct _sparse_matrix     SPM;typedef enum   FORMAT          FORMAT;typedef enum FORMAT {    DENSE,    CSR,    CSC};typedef struct  _unified_matrix{    FORMAT format;    int rows;    int cols;    int bits_val;    int num_vals;    unsigned short *vals;    unsigned  short *weight_powers;    short int *weight_masks;    int *row_offsets;    int *col_offsets;    int *starts;    int bits_intv;    int num_intvs;    unsigned short *intvs;};typedef struct _sparse_matrix {    FORMAT format;    int rows;    int cols;    int *row_offsets;    int *col_offsets;    int num_vals;    float *vals;    int *INTvals;   //Mark    int *offsets;    unsigned char *powers;  //Mark};
原创粉丝点击