关于YOLO的TensorFlow算法,网上有很多资料,这个大神写的就非常好!
https://zhuanlan.zhihu.com/p/24916786?refer=xiaoleimlnote
下面梳理下学习过程以及过程中遇到的问题:
首先运行train.py程序后,运行网络框架,网络部分较好理解,输入是[batch_size,448,448,3],输出是[7*7*30]维向量,具体为什么7*7*30=7*7*20+7*7*2+7*7*2*4得来的,比较难理解的是求loss,在这里困住了蛮久:
loss的求解分成3部分,在输出的向量中,前面7*7*20是物体分类,这个好理解,7*7*2是判断是否有物体的confidence值,这个有点难理解,后面根据自己的理解是,因为每个格子有两个bbox,每个bbox都有它的confidence值,这这个向量的作用是判断最后在输出时,是输出哪个bbox,最后的7*7*2*4是每个bbox的坐标,x_center,y_center,w,h,这个相对来说也好理解。
因为得到的标签是7*7*25,具体顺序是7*7*1+7*7*4+7*7*20,
注意的是,在标签上,7*7*1是表示,在7*7格子中,有物体的格子为1,没有物体的格子为0
因为输出时是用到两个bbox,所以在坐标标签时,需要拓展一次,用tf.tile函数就行,另外注意的是,XML文件的坐标是左上以及右下,在制作标签时需要进行中心原点归一化以及相应的更改成坐标为x_center,y_center,w,h
在求loss时,里面有一个很重要的向量为offset,开始弄了很久没弄明白干什么用,后面弄明白,因为开始原点坐标已经归一化了,加上offset是为了把坐标归一化成整个网络,比如:假如坐标归一化成(0.5,0.6),不好表示在哪一个格子中, 如果在这基础上分别加上0→6,再除以7,就能很直观的表达中心点所在的格子坐标,如果这个中心坐标在【4,5】格子内,则最后输出的中心坐标为【4.5,5.6】,后面的对宽和高进行平方,具体原因有相关论文解释
第二个求的是计算iou,主要思想是分别求每个bbox中,预测的矩阵与实际标签的矩阵之间的关系,iou值等于预测矩阵与标签矩阵相交的面积/预测矩阵面积+标签矩阵面积,取这个值较大的bbox为输出的对象,这是计算有物体的所在的格子
class_loss=标签的7*7*1*(标签的7*7*20-预测的7*7*20),最终得到的是7*7*20的三维矩阵,然后求所有值的平方和并取平均。因为有两个bbox,所以再乘以2
object_loss=较大iou的bbox*标签的7*7*1*(预测的7*7*2-iou值),同样的求平方和的平均数,并乘以1
noobject_loss=没有物体的的检测损失,算法跟有物体的类似
coord_loss=在object上增加一个维度7*7*2*1*(预测的坐标7*7*2*4-标签坐标7*7*2*4),求平方和平均数,并乘以5
这几个loss所乘的偏置不一样,是因为重要性决定的
然后把这几个损失值相加成最终损失值,案列中用到的函数是tf.losses.add_loss以及tf.loss.get_total_loss
随后是提取图片数据以及标签数据,这里没什么难度,比较简单,最终返回的是7*7*25的标签
最后是正式训练
整个过程,有点难理解的是loss的计算。
在测试过程中,有点难理解的也是判断物体并且显示,但类似于loss的求解