参考:
./darknet detector train cfg/cup-obj.data cfg/cup-yolov3.cfg darknet53.conv.74
error: Assertion `0' failed.
办法:将.cfg文件中的batch值设置得更小一点
./src/parser.c:360: parse_region: Assertion `l.outputs == params.inputs' failed.
办法:是由于粗心将.cfg文件中的与[yolo]层对应的classes值相对应的按照公式计算出来的filters=(classes+1)*3得到的某些[convolutional]层中的filters值输错了。
要把.txt标记文件与图片数据集放在同一个文件夹里,否则训练指令无法执行。
检测指令:经验:测试时最好使用detect指令而不是与它一样作用的detector test指令
./darknet detect cfg/cup-yolov3.cfg backup/cup-yolov3_500.weights example1/TestData/少女风水杯_2.jpg
摘抄: 刚train结束后的bug,就是coco数据的background类,yolov3默认是81分类啦,我在刚开始project.names只按照annotations中的class name写了,漏掉了背景类,于是出现了标签错乱的问题,detect的结果都是跟正确的label错1位,于是修改了project.name
,把第一行默认为background,做成了81行的class name的签,就能对应上结果了。
输入终端测试命令后,在终端上显示出这样的输出内容:
layer filters size input output
0 conv 32 3 x 3 / 1 608 x 608 x 3 -> 608 x 608 x 32 0.639 BFLOPs
1 conv 64 3 x 3 / 2 608 x 608 x 32 -> 304 x 304 x 64 3.407 BFLOPs
2 conv 32 1 x 1 / 1 304 x 304 x 64 -> 304 x 304 x 32 0.379 BFLOPs
……
104 conv 256 3 x 3 / 1 76 x 76 x 128 -> 76 x 76 x 256 3.407 BFLOPs
105 conv 18 1 x 1 / 1 76 x 76 x 256 -> 76 x 76 x 18 0.053 BFLOPs
106 yolo
Loading weights from darknet53.conv.74...Done!
Learning Rate: 0.001, Momentum: 0.9, Decay: 0.0005
补充:
注意对比,后来执行权重文件backup/cup-yolov3_200.weights也是输出,如下:
Loading weights from backup/cup-yolov3_200.weights...Done!
Learning Rate: 0.001, Momentum: 0.9, Decay: 0.0005
补充完成
Resizing
352
Loaded: 0.000025 seconds
Region 82 Avg IOU: 0.618194, Class: 0.000000, Obj: 0.827718, No Obj: 0.559633, .5R: 0.500000, .75R: 0.500000, count: 2
Region 94 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.497142, .5R: -nan, .75R: -nan, count: 0
Region 106 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.412502, .5R: -nan, .75R: -nan, count: 0
Region 82 Avg IOU: 0.256536, Class: 0.000000, Obj: 0.750111, No Obj: 0.563169, .5R: 0.000000, .75R: 0.000000, count: 1
Region 94 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.498241, .5R: -nan, .75R: -nan, count: 0
Region 106 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.413971, .5R: -nan, .75R: -nan, count: 0
Region 82 Avg IOU: 0.173034, Class: 0.000000, Obj: 0.907149, No Obj: 0.558328, .5R: 0.000000, .75R: 0.000000, count: 1
Region 94 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.496366, .5R: -nan, .75R: -nan, count: 0
Region 106 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.415022, .5R: -nan, .75R: -nan, count: 0
Region 82 Avg IOU: 0.526406, Class: 0.000000, Obj: 0.839134, No Obj: 0.555887, .5R: 1.000000, .75R: 0.000000, count: 1
Region 94 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.497250, .5R: -nan, .75R: -nan, count: 0
Region 106 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.414199, .5R: -nan, .75R: -nan, count: 0
Region 82 Avg IOU: 0.271038, Class: 0.000000, Obj: 0.435728, No Obj: 0.562631, .5R: 0.000000, .75R: 0.000000, count: 2
Region 94 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.496236, .5R: -nan, .75R: -nan, count: 0
Region 106 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.412586, .5R: -nan, .75R: -nan, count: 0
1: 586.982361, 586.982361 avg, 0.000000 rate, 0.267253 seconds, 5 images
……
解析:
175: 11.040030, 27.602013 avg, 0.000001 rate, 0.343914 seconds, 875 images
Loaded: 0.000030 seconds
我的输出log表示:第175个batch,总loss是11.040030,平均loss是27.602013,学习率是0.000001,当前batch计算时间是0.343914秒,第875个batchsize。
Region 82 Avg IOU: 0.526406, Class: 0.000000, Obj: 0.839134, No Obj: 0.555887, .5R: 1.000000, .75R: 0.000000, count: 1
2: 590.584229, 587.342529 avg, 0.000000 rate, 0.294364 seconds, 10 images
Loaded: 0.000029 seconds
Resizing 352
./darknet detector train cfg/cup-obj.data cfg/cup-yolov3.cfg darknet53.conv.74 2>1 | tee cup-train.txt
./darknet detector train cfg/cup-obj.data cfg/cup-yolov3.cfg backup/cup-yolov3_100.weights
在这个权重文件上继续训练后又会得到一个新的更加好的权重文件backup/cup-yolov3_200.weights.
摘抄:“经过大约一个小时的训练后,达到了1000次迭代,平均损失(误差)为0.082204。”
下面的输出log中,第一列是表示是第几个batch。第二列表示总的loss。第三列表示平均loss。第四列表示学习率。第五列是当前batch的计算时间,第六列是第几张图片。
在每个batch的输出log之前,都有resize语句,是由于.cfg文件中,random为1时会启用Multi-Scale Training,随机使用不同尺寸的图片进行训练,所以会有resize语句。若random=0则每次训练大小与输入大小一致。
对比:我的输出log中可以看到,每一次bacth迭代都是5张图片5张图片的。在训练时设置了batch=8,subdivisions=5。
平均误差的变化情况为:
平均误差值由第1次batch值由586到第12次batch值变成709,对应:初始学习率为0.000000
到第30次batch值变成1260,对应学习率0.000000
到第31次batch值开始下降,变成1243,对应学习率0.000000
到第50次batch值变成924,对应学习率0.000000
到第110次batch值变成332,对应学习率0.000000
到第217次batch值变成6,对应学习率0.000002
分析在cup-yolov3_400.weights权重文件基础上训练了8分钟后的输出log情况:
到第768次batch值变成1.399962,对应学习率0.000348(到这一步batch时其实学习率已经过高了)
训练到平均误差降为6,到了第227次batch的时间大约5分钟。
训练了几乎1个小时后,迭代到了第7000多个batch,此时的平均loss值都变成了nan。
通过对比训练了1个小时的输出log和之前只训练了7分钟的输出log可以看出,后面的学习率提升了很多倍,所以可能是学习率过大导致不收敛的情况出现。
这次训练了1个小时后,在backup文件夹中,之前训练的时长很短的两次训练结束后分别产生了一个权重文件,第一次是cup-yolov3_100.weights,第二次是cup-yolov3_200.weights,但是这次训练时长很长的一次训练结束后(注意每次训练都是在上次产生的权重文件的基础上训练的)新增了7个权重文件,分别是:cup-yolov3_300.weights、cup-yolov3_400.weights、cup-yolov3_500.weights、cup-yolov3_600.weights、cup-yolov3_700.weights、cup-yolov3_800.weights、cup-yolov3_900.weights。
当训练到第900个batch时就会产生backup//cup-yolov3_900.weights
基于网上下载的权重文件训练5分钟的结果
1: 586.982361, 586.982361 avg, 0.000000 rate, 0.267253 seconds, 5 images
2: 590.584229, 587.342529 avg, 0.000000 rate, 0.294364 seconds, 10 images
12: 1228.810791, 709.375916 avg, 0.000000 rate, 0.492510 seconds, 60 images
30: 1395.137939, 1260.228516 avg, 0.000000 rate, 0.594338 seconds, 150 images
31: 1092.498535, 1243.455566 avg, 0.000000 rate, 0.398419 seconds, 155 images
50: 804.217285, 924.948730 avg, 0.000000 rate, 0.379187 seconds, 250 images
110: 229.943451, 332.805756 avg, 0.000000 rate, 0.300960 seconds, 550 images
217: 7.226011, 6.953908 avg, 0.000002 rate, 0.383689 seconds, 1085 images
219: 4.467210, 7.112023 avg, 0.000002 rate, 0.383818 seconds, 1095 images
220: 5.249475, 6.925768 avg, 0.000002 rate, 0.383752 seconds, 1100 images
224: 9.429196, 7.301046 avg, 0.000003 rate, 0.609718 seconds, 1120 images
225: 4.749487, 7.045890 avg, 0.000003 rate, 0.606195 seconds, 1125 images
227: 4.945302, 6.823396 avg, 0.000003 rate, 0.606311 seconds, 1135 images
训练大约1个小时的结果如下
7131: -nan, -nan avg, 0.001000 rate, 0.250000 seconds, 35655 images
7440: -nan, -nan avg, 0.001000 rate, 0.381908 seconds, 37200 images
在cup-yolov3_400.weights权重文件基础上训练了8分钟后的输出log情况:
768: 0.556964, 1.399962 avg, 0.000348 rate, 0.384204 seconds, 3840 images
836: 46.330509, 6.593365 avg, 0.000488 rate, 0.423186 seconds, 4180 images
889: 195.407013, 21.678837 avg, 0.000625 rate, 0.424788 seconds, 4445 images
900: 2.271802, 8.671995 avg, 0.000656 rate, 0.713107 seconds, 4500 images
Saving weights to backup//cup-yolov3.backup
Saving weights to backup//cup-yolov3_900.weights
从这里可以观察得到,当训练到第900个batch时就会产生backup//cup-yolov3_900.weights
950: 5263.906738, 718.365906 avg, 0.000815 rate, 0.615427 seconds, 4750 images
951: 13056.240234, 1952.153320 avg, 0.000818 rate, 0.535834 seconds, 4755 images
1000: 0.708008, 296.364410 avg, 0.001000 rate, 0.515960 seconds, 5000 images
Saving weights to backup//cup-yolov3.backup
从这里可以看出当迭代到第1000个batch时,不会再产生权重文件了。不知道为什么这里没有产生backup//cup-yolov3_1000.weights,但是说不会再产生权重文件的结论是错误的,后面是会继续有的,因为在其他地方有看到backup//cup-yolov3_2000.weights这样的权重文件。
1096: 70446.734375, 13425.520508 avg, 0.001000 rate, 0.344823 seconds, 5480 images
1108: 1170175005885535879168.000000, 117017504106990796800.000000 avg, 0.001000 rate, 0.339283 seconds, 5540 images
从第1109次batch开始,平均loss值开始变成nan
1109: -nan, -nan avg, 0.001000 rate, 0.337159 seconds, 5545 images
1110: nan, -nan avg, 0.001000 rate, 0.336276 seconds, 5550 images
在cup-yolov3_200.weights权重文件基础上训练了3分钟后的输出log情况:
243: 4.018680, 5.119147 avg, 0.000003 rate, 0.459128 seconds, 1215 images
360: 1.780453, 2.842503 avg, 0.000017 rate, 0.705736 seconds, 1800 images
在cup-yolov3_400.weights权重文件基础上训练了4分钟后的输出log情况:
468: 2.294378, 2.397950 avg, 0.000048 rate, 0.727073 seconds, 2340 images
531: 3.047993, 2.990965 avg, 0.000080 rate, 0.570293 seconds, 2655 images
687: 1.421806, 1.678364 avg, 0.000223 rate, 0.721503 seconds, 3435 images
699: 1.553484, 2.162127 avg, 0.000239 rate, 0.643578 seconds, 3495 images
703: 0.616968, 1.823786 avg, 0.000244 rate, 0.620547 seconds, 3515 images
752: 0.968440, 1.543288 avg, 0.000320 rate, 0.334344 seconds, 3760 images
798: 26.327856, 4.645860 avg, 0.000406 rate, 0.604878 seconds, 3990 images
853: 0.747405, 1.933562 avg, 0.000529 rate, 0.703774 seconds, 4265 images
870: 1.108501, 1.441449 avg, 0.000573 rate, 0.460056 seconds, 4350 images
908: 1.532592, 8.039704 avg, 0.000680 rate, 0.459946 seconds, 4540 images
927: 5.739350, 13.067078 avg, 0.000738 rate, 0.416476 seconds, 4635 images
929: 810.616150, 92.059631 avg, 0.000745 rate, 0.420621 seconds, 4645 images
像上面贴出来的输出log一样,最后loss变成nan。
总结:
基于上面所有情况下运行得到的输出log,发现最小的平均loss值为1.4附近波动。
第217次bacth时,总loss为7.2, 平均loss为6.9,学习率为0.000002。
第768次bacth时,总loss为0.5, 平均loss为1.39, 学习率为0.000348。
第752次batch时,总loss为0.9, 平均loss为1.5, 学习率为0.000320。
第870次batch时,总loss为1.1, 平均loss为1.4,学习率为 0.000573。
第929次batch时,总loss为810,平均loss为92, 学习率为0.000745。
参考:参考
解决办法:
解决办法:
现象:
每次在固定的迭代次数段,loss都会突然变成nan,导致acc骤降,慢慢变成0。脏数据的出现导致logits计算出了0,0传给log(x|x=0)值趋近于无穷,即nan。
解决办法:
设置batch_size=1,shuffle=False,一步一步将sample定位到所有可能的脏数据,然后删掉。这个过程中,就重复一直定位一直删除,直到不出现nan。
总结:
现实的数据是非常脏的,所以在实际工作中,数据预处理就占到工作的80%.
在迭代的100轮以内,出现nan,一般是学习率过高,需要降低学习率,可以不断降低学习率,直到不出现nan为止,一般说低于现有学习率1-10倍即可。
若当前网络是类似RNN的循环神经网络的话,出现nan可能是梯度爆炸的原因,一个有效犯法是增加gradient clipping(梯度截断)来解决。
可能用0做了除数
可能0或者负数做了自然对数。
需要计算Loss的数组越界。尤其是当自定义了一个新网络时,是很容易出现这个问题。
在某些涉及指数运算,可能最后算的值为inf(无穷),比如不做其他处理的softmax中分子分母需要计算exp(x),值过大的话,可能最后值为inf,出现Nan,所以需要确认使用的softmax在计算exp(x)时做了相关处理,比如减去最大值等等。
tensorflow中训练出现nan的问题: 深度学习对于网络的训练是参数更新的过程,需要注意的一种情况就是输入数据未做归一化的时候,如果前向传播已经是[0,0,0,1,0,0,0,0]这种形式,而真实结果是[1,0,0,0,0,0,0,0],此时得到的结论不具有概率性,是错误的估计值,此时反向传播会使得权重和偏置值变得无穷大,导致数据溢出,就出现nan的问题。
解决办法:
(1)对输入数据归一化处理,例如将输入的图片数据除以255将其转化为0-1之间的数据。
(2)对于层数较多的情况,每层都做batch_normalization。
(3)对设置weights权重采用tf.truncated_normal(0,0.01,[3,3,1,64]生成,同时值的均值为0,方差要小一些。
(4)激活函数可以使用tanh
(5)减小学习率
在标记数据的时候,一要注意被标记物体要完整,二是要注意在标记数据的时候框的大小尽量符合被检测物体的大小,尽量不要框到多余的物体,这样噪点会更大。
之前的训练集因为混杂了网上下载的各种图片还有摄像头拍摄的图片,而且数据量也小,所以就修改为全部用摄像头拍摄了两个物体,一个是水瓶,一个是乳液。共1000张数据,里面存在重复的图片。下面是修改训练集之后的训练结果:
1: 1227.480957, 1227.480957 avg, 0.000000 rate, 0.243873 seconds, 4 images
501: 2.108885, 2.108885 avg, 0.000063 rate, 0.246405 seconds, 2004 images
615: 3.421903, 1.555070 avg, 0.000143 rate, 0.172071 seconds, 2460 images
718: 0.850832, 0.992338 avg, 0.000266 rate, 0.294531 seconds, 2872 images
772: 27.615116, 3.862367 avg, 0.000355 rate, 0.199183 seconds, 3088 images
863: 0.562656, 0.971841 avg, 0.000555 rate, 0.310661 seconds, 3452 images
969: 44.149776, 7.621551 avg, 0.000882 rate, 0.202318 seconds, 3876 images
1814: 0.428668, 0.491803 avg, 0.000010 rate, 0.544996 seconds, 7256 images
4000: 0.483848, 0.527806 avg, 0.000010 rate, 0.504831 seconds, 16000 images
9000: 0.409073, 0.413204 avg, 0.000010 rate, 0.519575 seconds, 36000 images
12000: 0.220595, 0.333596 avg, 0.000010 rate, 0.508379 seconds, 48000 images
13000: 0.383652, 0.394776 avg, 0.000010 rate, 0.506586 seconds, 52000 images
14000: 0.431621, 0.338908 avg, 0.000010 rate, 0.532735 seconds, 56000 images
15000: 0.498119, 0.361371 avg, 0.000010 rate, 0.522756 seconds, 60000 images
16000: 0.333839, 0.284221 avg, 0.000010 rate, 0.507750 seconds, 64000 images
17000: 0.234287, 0.273595 avg, 0.000010 rate, 0.537022 seconds, 68000 images
18000: 0.295689, 0.313349 avg, 0.000010 rate, 0.511710 seconds, 72000 images
19000: 0.305686, 0.278494 avg, 0.000010 rate, 0.507369 seconds, 76000 images
20000: 0.151630, 0.290826 avg, 0.000010 rate, 0.507186 seconds, 80000 images
21000: 0.273733, 0.270584 avg, 0.000010 rate, 0.507230 seconds, 84000 images
22000: 0.133326, 0.265308 avg, 0.000010 rate, 0.507203 seconds, 88000 images
23000: 0.292121, 0.261696 avg, 0.000010 rate, 0.545719 seconds, 92000 images
24000: 0.223262, 0.205484 avg, 0.000010 rate, 0.537998 seconds, 96000 images
25000: 0.188407, 0.217402 avg, 0.000010 rate, 0.574772 seconds, 100000 images
26000: 0.346192, 0.252096 avg, 0.000010 rate, 0.524121 seconds, 104000 images
27000: 0.287275, 0.225132 avg, 0.000010 rate, 0.509380 seconds, 108000 images
30000: 0.204683, 0.231666 avg, 0.000010 rate, 0.519882 seconds, 120000 images
49350: 0.108591, 0.105451 avg, 0.000010 rate, 0.434735 seconds, 197400 images
50000: 0.130271, 0.179324 avg, 0.000010 rate, 0.508445 seconds, 200000 images
59975: 0.085559, 0.156788 avg, 0.000010 rate, 0.519048 seconds, 239900 images
60000: 0.116182, 0.179747 avg, 0.000010 rate, 0.563186 seconds, 240000 images
80000: 0.157307, 0.157761 avg, 0.000100 rate, 0.515238 seconds, 320000 images
100000: 0.118885, 0.084560 avg, 0.000100 rate, 0.518509 seconds, 400000 images
110000: 0.173661, 0.106153 avg, 0.000100 rate, 0.509563 seconds, 440000 images
119944: 0.086295, 0.067115 avg, 0.000100 rate, 0.517343 seconds, 479776 images
120000: 0.021340, 0.100389 avg, 0.000100 rate, 0.511548 seconds, 480000 images
129976: 0.030070, 0.063398 avg, 0.000100 rate, 0.509948 seconds, 519904 images
130000: 0.056544, 0.096625 avg, 0.000100 rate, 0.508922 seconds, 520000 images
139964: 0.026662, 0.059001 avg, 0.000100 rate, 0.507803 seconds, 559856 images
140000: 0.201191, 0.096713 avg, 0.000100 rate, 0.508453 seconds, 560000 images
150000: 0.085332, 0.096602 avg, 0.000100 rate, 0.507115 seconds, 600000 images
选择160000这个权重文件来测试
160000: 0.044543, 0.070178 avg, 0.000100 rate, 0.508458 seconds, 640000 images
从第160000个batch到第170000个batch大概用了两小时。
169966: 0.021125, 0.062861 avg, 0.000100 rate, 0.507765 seconds, 679864 images
170000: 0.055982, 0.082330 avg, 0.000100 rate, 0.507035 seconds, 680000 images
从第170000个batch到第180000个batch大概用了一个半小时。
180000: 0.153854, 0.078253 avg, 0.000100 rate, 0.509002 seconds, 720000 images
186824: 0.150794, 0.063261 avg, 0.000100 rate, 0.509802 seconds, 747296 images
总结训练时输出log的规律:
在cfg文件里设置的:batch=4 subdivisions=2
1. 6条region这样的语句之后出现一条检测batch的各个参数输出log语句
Region 82 Avg IOU: 0.644588, Class: 0.284318, Obj: 0.057900, No Obj: 0.000914, .5R: 1.000000, .75R: 0.000000, count: 2
2. 10次batch迭代之后重新resize图片一次
修改了训练集之后利用训练得到的160000权重文件测试单张图片的结果。
cfg文件里设置classes=1
example1/TestData/750.jpg: Predicted in 0.059699 seconds.
person: 90%
在测试时,要把cfg文件里面关于test的取消注释,而且test的batch和subdivisions设置为1.
./darknet detector test cfg/voc.data cfg/yolo-voc.cfg ./svt/backup/yolo-voc_final.weights
./darknet detector valid cfg/cup-obj.data cfg/cup-yolov3.cfg backup/yolo-voc_final.weights
这条终端测试指令是使用的yolo网络自带的valid函数接口来测试大量图片,把检测结果保存在txt文件中。测试完成后,在results文件夹下打开文本,里面的书写格式是voc格式。其中每一行代表:图片名字、这一类框的置信度、坐标信息。
然后可以使用py-faster-rcnn下的voc_eval.py计算mAP。
把py-faster-rcnn/lib/datasets/voc_eval.py拷贝到darknet根目录。
下载地址:https://github.com/rbgirshick/py-faster-rcnn/blob/master/lib/datasets/voc_eval.py
新建自己的compute_mAP.py文件。如下:
输出在stderr里,重定向时要注意。
RPs/Img、IOU、Recall都是到当前测试图片的均值。
detector.c中对目录处理有错误,可以参照validate_detector对validate_detector_recall最开始几行的处理进行修改。
修改完成detector.c文件之后要先在darknet下make一下,再运行检测指令即这里的recall指令
./darknet detector recall cfg/cup-obj.data cfg/cup-yolov3.cfg backup/yolo-voc_final.weights(这个命令需修改dectector.c文件)
在终端输入这条recall测试指令之后,在终端上会显示
enter you image path
此时要输入的就是在cfg文件中valid参数对应的那个值,也就是存储所有测试集图片路径的那个txt文本。
执行完毕后,所有的测试图片都会保存在out文件夹下,我是把out文件夹创建在example1文件夹下,网上程序把out文件夹创建在darknet/data/out下。
例如,如下是输出日志的一部分:
44579: 0.257759, 0.196168 avg, 0.000010 rate, 0.178815 seconds, 178316 images
Loaded: 0.000055 seconds
Region 82 Avg IOU: 0.761178, Class: 0.998803, Obj: 0.870125, No Obj: 0.003177, .5R: 1.000000, .75R: 0.500000, count: 2
Region 94 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.000084, .5R: -nan, .75R: -nan, count: 0
Region 106 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.000000, .5R: -nan, .75R: -nan, count: 0
Region 82 Avg IOU: 0.728754, Class: 0.999666, Obj: 0.973296, No Obj: 0.003884, .5R: 1.000000, .75R: 0.000000, count: 1
Region 94 Avg IOU: 0.659824, Class: 0.957042, Obj: 0.314952, No Obj: 0.000288, .5R: 1.000000, .75R: 0.000000, count: 1
Region 106 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.000000, .5R: -nan, .75R: -nan, count: 0
44580: 0.178447, 0.194396 avg, 0.000010 rate, 0.176078 seconds, 178320 images
在cfd文件中设置batch=4,subdivision=2。所以在训练输出中, 训练迭代包含了 2 组, 每组又包含了 2 张图片.
如下,这样一行的信息是由example/detector.c中的部分代码实现的
44580: 0.178447, 0.194396 avg, 0.000010 rate, 0.176078 seconds, 178320 images
这条输出语句表示第44580个batch,总loss是 0.178447,平均loss是0.194396,一般这个数值低于0.06就可以停止训练,如果达不到这个值也可以,只要是迭代了挺多次,返现loss值趋于平稳也可以停止训练。学习率是0.000010,当前这个bacth训练花费时间0.176078 seconds,截止目前,训练的总图片数目是178320。
实现的部分关键代码如下
...
if (avg_loss < 0) avg_loss = loss;
avg_loss = avg_loss*.9 + loss*.1;
i = get_current_batch(net);
printf("%ld: %f, %f avg, %f rate, %lf seconds, %d images\n",
get_current_batch(net),
loss,
avg_loss,
get_current_rate(net),
what_time_is_it_now()-time,
i*imgs);
...
IOU Intersection over Union 交并集之比
上面粘贴出来的输出log的另外一部分如下:
Region 82 Avg IOU: 0.761178, Class: 0.998803, Obj: 0.870125, No Obj: 0.003177, .5R: 1.000000, .75R: 0.500000, count: 2
Region 94 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.000084, .5R: -nan, .75R: -nan, count: 0
Region 106 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.000000, .5R: -nan, .75R: -nan, count: 0
Region 82 Avg IOU: 0.728754, Class: 0.999666, Obj: 0.973296, No Obj: 0.003884, .5R: 1.000000, .75R: 0.000000, count: 1
Region 94 Avg IOU: 0.659824, Class: 0.957042, Obj: 0.314952, No Obj: 0.000288, .5R: 1.000000, .75R: 0.000000, count: 1
Region 106 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.000000, .5R: -nan, .75R: -nan, count: 0
输出信息的数目是: subdivisions * ngpus * 3即2 * 1 * 3=6,如上正好是6条region语句。
上面这六条语句表示的是三个不同的尺度上(重复的两组)82/94/106上预测到的不同大小的框的参数。
82 卷积层为最大的预测尺度, 使用较大的 mask, 但是可以预测出较小的物体;
94 卷积层为中间的预测尺度, 使用中等的 mask;
106卷积层为最小的预测尺度, 使用较小的 mask, 可以预测出较大的物体.
上述输出信息的各个参数含义是(主要观察某一个尺度上的参数), 下面就 Region 82 分析:
Region 82 Avg IOU: 0.761178, Class: 0.998803, Obj: 0.870125, No Obj: 0.003177, .5R: 1.000000, .75R: 0.500000, count: 2
Region Avg IOU:0.761178: 表示在当前 subdivision 内的图片的平均 IOU, 代表预测的矩形框和真实目标的交集与并集之比, 这里是 76.1%, 这个模型此时已经达到了很高的训练精度;
Class: 0.998803: 标注物体分类的正确率, 期望该值趋近于1;
Obj: 0.870125: 越接近 1 越好;
No Obj: 0.003177: 期望该值越来越小, 但不为零;
.5R: 1.000000: 是在 recall/count 中定义的, 是当前模型在所有 subdivision 图片中检测出的正样本与实际的正样本的比值。在本例中, 全部的正样本被正确的检测到。
count: 2: 所有当前 subdivision 图片(本例中一共 2张)中包含正样本的图片的数量。 在输出 log 中的其他行中。(在 subdivision 中含有不包含在检测对象 classes 中的图片)
实现代码在src/region_layer.c中,部分重要的实现部分如下:
*(l.cost) = pow(mag_array(l.delta, l.outputs * l.batch), 2);
printf("Region %d Avg IOU: %f, Class: %f, \
Obj: %f, No Obj: %f, \
.5R: %f, .75R: %f, count: %d\n",
net.index, avg_iou/count, avg_cat/class_count,
avg_obj/count, avg_anyobj/(l.w*l.h*l.n*l.batch),
recall/count, recall75/count, count);
参数:batch, subdivisions,max_batches
每batch个样本代表完成一次权重参数更新。max_batches是最大权重更新次数,完成max_batches次权重更新后停止训练。
参数:width, height, channel
输入图像的分辨率和通道数。width,height须设置成32的倍数。
梯度下降法相关的参数有:momentum, decay,以及学习率系列参数。
momentum是动量梯度下降法的动量参数,默认为0.9。decay是权重衰减正则项,每一次学习的过程中,将学习后的参数按照固定比例进行降低,防止过拟合,默认值0.0005。
学习率相关的参数包括:learning_rate,burn_in,policy,以及每种policy对应的参数。
learning_rate是权值更新的基础变化率,默认值0.001。在训练过程中,一般根据训练轮数动态更新学习率。在迭代次数小于burn_in时,学习率有一种更新策略。**大于burn_in时,**才采用policy的更新策略。policy包括:constant, steps, exp, poly, step, sig, random。
例如:
steps=40000,45000
scales=.1,.1
表示迭代到40000次时,学习率在learning_rate的基础上衰减10倍,45000次迭代时,学习率又会在前一个学习率的基础上衰减十倍。
数据增强参数包括:hue,saturation,exposure,分别对应HSV三个颜色通道的调整参数
数据增强会以50%的概率左右翻转图像(flip)。YOLOv3的目标检测未采用角度旋转数据增强angle。数据增强参数jitter定义在[yolo]层部分。
参数:anchors,mask,num
anchors定义了anchor的宽高,以像素为单位。只有mask索引到的anchors才会在当前yolo层中被使用。如果不设置anchors,默认是0.5。num=anchors数量。
例如
mask = 0, 1, 2
anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326
mask数量是3,anchors数量是9,即num=9。mask定义第0,1,2个anchors在当前yolo层中被使用,其宽高分别是[10,13],[16,30],[33,23]。mask数量也是每个grid预测的boundingbox数。
每一个yolo层前的最后一个卷积层的filters=(mask数量)*(classes+4+1)。
参数:ignore_thresh,truth_thresh
ignore_thresh与truth_thresh是loss 的相关参数。YOLOv3的loss函数包括 分类误差、定位误差、loss obj(是否格子中存在物体) 三个部分。每一个grid有多个预测框(其数量即为mask的数量),其中与ground truth的IOU最大的预测框,当其IOU小于ignore_thresh的时候,即作为负样本参与 loss obj 的计算,否则,不参与 loss obj计算(不作为正样本)。而且,如果这个IOU大于truth_thresh,则作为样本参与 分类误差和 定位误差的计算。ignore_thresh一般选取0.5-0.7之间的一个值,默认为0.5。truth_thresh默认为1。
另外,对于每一个ground truth,其中心位置对应的grid上,与ground truth之间IOU最大的预测框,参与定位误差、分类误差、loss obj 的计算。
参数:random
random是多尺度训练使能参数。如果为1,那么每次10次迭代的图片大小在[320,608]区间内随机选择,步长为32。如果为0,图像尺寸为net定义的高宽。这也就可以解释在输出log中每10个bacth之后出现一条resize语句。
参数:jitter
jitter是随机crop的参数。jitter=.3,就是在宽高缩放1±0.3范围内进行crop
参数:max
每幅图像中使用的ground truth最大数量。
Region 82 Avg IOU: 0.816567, Class: 0.995740, Obj: 0.862174, No Obj: 0.003723, .5R: 1.000000, .75R: 0.500000, count: 2
53418: 0.076606, 0.108589 avg, 0.000010 rate, 0.201794 seconds, 213672 images
Region 82 Avg IOU: 0.936451, Class: 0.999735, Obj: 0.992904, No Obj: 0.002856, .5R: 1.000000, .75R: 1.000000, count: 2
53441: 0.052049, 0.125829 avg, 0.000010 rate, 0.160049 seconds, 213764 images
Loaded: 0.000029 seconds
^C
syy@syy1996:~/software/darknet$
上图:example1/TestData/625.jpg: Predicted in 0.059876 seconds.
Emulsion: 78%
WaterBottle: 58%
上图:example1/TestData/650.jpg: Predicted in 0.060006 seconds.
example1/TestData/675.jpg: Predicted in 0.060090 seconds.
WaterBottle: 95%
example1/TestData/700.jpg: Predicted in 0.061012 seconds.
Emulsion: 77%
WaterBottle: 89%
上图:example1/TestData/725.jpg: Predicted in 0.060916 seconds.
WaterBottle: 83%
上图:example1/TestData/750.jpg: Predicted in 0.060256 seconds.
WaterBottle: 96%