-
Notifications
You must be signed in to change notification settings - Fork 28
/
readme.txt
145 lines (108 loc) · 5.87 KB
/
readme.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
+----------------------------+
ffcnn 卷积神经网络前向推理库
+----------------------------+
ffcnn 是一个 c 语言编写的卷积神经网络前向推理库
只用了 500 多行代码就实现了完整的 yolov3、yolo-fastest 网络的前向推理
不依赖于任何第三方库,在标准 c 环境下就可以编译通过,在 VC、msys2+gcc、ubuntu+gcc
等多个平台上都可以正确的编译运行
这个代码相对于 darknet、ncnn 来说,没做特殊指令集优化,但代码更加简洁易懂,可以
作为大家学习卷积神经网络的一个参考
darknet 与 yolov3 的一些总结
----------------------------
yolov3 的网络结构里面,只有卷积层、dropout 层、shortcut 层、route 层、maxpool 层、
upsample 层和 yolo 层这几种类型。因此要实现起来还是比较容易的
卷积层:
1. 要搞明白卷积的含义和计算方法
2. 卷积运算的 pad、stride 的含义
3. 每个卷积核还有一个 bias 参数,计算完每个点后需要加上这个 bias
没有归一化的情况(batch_normalize),其计算方法:
x += bias;
x = activate(x, type);
4. 要搞明白什么是分组卷积
5. 卷积运算每个输出的点,都要经过激活函数
6. 卷积层如果有归一化操作(batch_normalize),其计算方法:
x = (x - rolling_mean) / sqrt(rolling_variance + 0.00001f)
x *= scale;
x += bias;
x = activate(x, type);
其中 rolling_mean、rolling_variance、scale、bias 在 darknet 的 weights 文件中可以读取到
dropout 层:
前向推理时,这一层可以当做不存在,输入数据不做任何处理,直接传给下一层即可
shortcut 层:
把指定层的数据和当前层的数据相加,然后结果输出到下一层
route 层:
把指定的层(最多可以有 4 个)做拼接,宽高不变,channel 个数增加,然后结果输出到下一层
maxpool 层:
max 池化层,将 filter 覆盖的数据取最大值作为结果
upsample 层:
上采样层,可以理解为把图像放大,stride 指定了放大倍数,一般用最近邻法就可以了
yolo 层:
这一层主要是根据输入的 feature map 计算出 bbox
以 yolo-fastest 为例,总共有两个 yolo 层,其输入分别是 10x10x255 和 20x20x255
其中 255 表示有 255 个通道,其每个数据的含义如下:
255 = 3 * (4 + 1 + 80)
3 表示这个 grid 里面有 3 个 bbox 结果数据
每个 bbox 结果数据里面,4 个 x, y, w, h 坐标数据,1 个 object score 评分,然后是 80 个分类的评分
每个 bbox 里面在 80 个分类中找出评分最高的,作为这个 bbox 的分类,评分如果小于阈值(ignore_thresh)则丢弃
将符合要求的全部 bbox 放入一个列表保存,然后再做一个 nms 操作,就得到最终结果了
每个 bbox 的评分和 (x, y, w, h) 计算方法:
设 tx, ty, tw, th, bs 分别对应channel 0, 1, 2, 3, 4 的值(后面还有 80 个分类的评分)
评分的计算方法:score = sigmoid(bs); (80 个分类评分计算方法是一样的)
坐标计算方法:
float bbox_cx = (j + sigmod(tx)) * grid_width; (grid_width 就是网络输入层即 0 层的宽度除以格子数目,即每个格子的像素宽度)
float bbox_cy = (i + sigmod(ty)) * grid_height; (方法与 bbox_cx 一致)
float bbox_w = (float)exp(tw) * anchor_box_w; (如果有缩放系数还要乘以这个系数)
float bbox_h = (float)exp(th) * anchor_box_h; (方法与 bbox_w 一致)
bbox_cx、bbox_cy 是中心点坐标,bbox_w、bbox_h 是宽高,转换一下得到:
x1 = bbox_cx - bbox_w * 0.5f;
y1 = bbox_cy - bbox_h * 0.5f;
x2 = bbox_cx + bbox_w * 0.5f;
y2 = bbox_cy + bbox_h * 0.5f;
darknet 的 weights 文件
-----------------------
文件最前面有一个文件头:
#pragma pack(1)
typedef struct {
int32_t ver_major, ver_minor, ver_revision;
uint64_t net_seen;
} WEIGHTS_FILE_HEADER;
#pragma pack()
然后就是全部的权重数据,yolov3、yolo-fastest 的模块基本上就只有卷积层的权重,其它层是没有权重数据的。
图像和卷积核(filter)的数据都是 NCHW 格式,卷积层的权重数据存放顺序为:
n 个 bias
if (batchnorm) {
n 个 scale
n 个 rolling_mean
n 个 rolling_variance
}
n * c * h * w 个权重数据
ffcnn 的特点
------------
1. 极为简洁易懂的 c 语言代码实现
2. 核心算法仅仅 600 行
3. 不依赖于任何第三方库
4. 可以很方便的移植到各种平台
5. 推理时会自动释放不需要的 layer 减小内存占用
6. 现阶段是 make it work first 后面有时间再优化性能
7. 直接使用 darknet 的 .cfg 和 .weights 文件(不需要再转换)
ffcnn vs ncnn 性能评测
----------------------
测试环境:
1. Intel(R) Core(TM) i5-4250U CPU @ 1.30GHz 1.90GHZ, 8GB RAM
2. win7 64bit 操作系统 + msys2 + mingw32 + gcc version 10.3.0
3. ffcnn + yolo-fastest 代码:https://github.com/rockcarry/ffcnn
4. ncnn + yolo-fastest 代码:https://github.com/rockcarry/ffyolodet
5. 测试图片 test.bmp 100 次推理
测试结果:
+----------+--------------+-------------------+------------------+
| 测试项目 | ffcnn-v1.2.0 | ncnn with avx off | ncnn with avx on |
+----------+--------------+-------------------+------------------+
| 耗 时 | 14555ms | 14649 ms | 8424 ms |
+----------+--------------+-------------------+------------------+
| 内存占用 | 5MB | 41MB | 41MB |
+----------+--------------+-------------------+------------------+
| 程序体积 | 68KB | 1.2MB | 1.2MB |
+----------+--------------+-------------------+------------------+
可以看到 ffcnn 已经逼近 ncnn(不开启 avx 指令优化)的性能
rockcarry@163.com
20:22 2021/8/7