源代码GitHub地址:https://github.com/qqwweee/keras-yolo3

作者使用自己数据集实现:yolo v3-训练自己的数据(step by step)

项目结构思维导图:

 

1、yolov3最后的输出为三个特征层的输出,并没有进行一个连接,分别是13*13*255(255=3*(5+80类)),26*26*255,52*52*255三种feature map,所以可以看到输入网络中的true_box是for l in range(num_layers)得到的,其中num_layers=3表示有三个特征图的输出。

y_true = [np.zeros((m,grid_shapes[l][0],grid_shapes[l][1],len(anchor_mask[l]),5+num_classes),
        dtype='float32') for l in range(num_layers)]

所以y_true就是一个list,len(y_true)=3,其中的每一个list是我们之前所认识的那样:eg:13*13*3*(x+y+w+h+class_id+num_classes)

2、yolov3网络的每个小格子预测三个回归框,但是为什么会有9个anchore,这9个anchore通过下图可以看出来 是三个尺度上的,并且该yolo网络的最后输出是三个尺度上的输出,因此可以有3*3=9,其中3表示输出的特征层的个数,另一个3表示每一个特征层(feature map)其中每个小格子(gird)所能预测的最大的格子数(在程序中有标注,最大不能超过20个)。(并非在网络的最后将三个特征层进行了融合,而是单独的三个特征层进行输出,最终我们的box信息也会转换为该形式的,所以不是每个格子预测九个框,下图在yolov3中表示三个尺度上的)

在这里插入图片描述

3、yolo中的confidence 代表了所预测的 box 中含有 object 的置信度和这个 box 预测的有多准这两重信息,并非简单的置信度

4、yolo v1版本由于输出层为全连接层,在网络的设置中需要设置一个shape大小信息,因此在检测时,YOLO 训练模型只支持与训练图像相同的输入分辨率,但是yolo v3就支持测试的时候使用更高的分辨率的图片,因为最终的输出为卷积形式的,并且中间没有全连接层,只需要卷积核的大小不会变化,测试的时候输入图像的输出的尺寸大小和对true_box处理以后的大小相同(true_box在做处理的时候需要用到shape信息),而预训练的权重不用变也可以用,因为只有卷积那里的权重,分辨率变化只是影响了最终的输出大小(同时true_box也变了),其他没有变化。

区别于之前的补全图片的尺寸的方法,YOLOv2 每迭代几次都会改变网络参数。每 10 个 Batch,网络会随机地选择一个新的图片尺寸,由于使用了下采样参数是  32,所以不同的尺寸大小也选择为 32 的倍数 {320,352…..608},最小 320*320,最大 608*608,网络会自动改变尺寸,并继续训练的过程。

这一政策让网络在不同的输入尺寸上都能达到一个很好的预测效果,同一网络能在不同分辨率上进行检测。当输入图片尺寸比较小的时候跑的比较快,输入图片尺寸比较大的时候精度高,所以你可以在 YOLOv2 的速度和精度上进行权衡。

5、yolo v1的loss中有几点的理解

注意:

只有当某个网格中有 object 的时候才对 classification error 进行惩罚

只有当某个 box predictor 对某个 ground truth box 负责的时候,才会对 box 的 coordinate error 进行惩罚,而对哪个 ground truth box 负责就看其预测值和 ground truth box 的 IoU 是不是在那个 cell 的所有 box 中最大

如果一个网格中没有 object(一幅图中这种网格很多),那么就会将这些网格中的 box 的 confidence push 到 0,相比于较少的有 object 的网格,这种做法是 overpowering 的,这会导致网络不稳定甚至发散。对没有 object 的 box 的 confidence loss,赋予小的 loss weight,记为在 pascal VOC 训练中取 0.5,有 object 的 box 的 confidence loss 和类别的 loss 的 loss weight 正常取 1。(也就是说图像中大部分的格子中是没有目标的,所以如果设置一样的权重,那么为了使loss下降,网络训练得到的参数会使得所有的格子都倾向于为0,从而造成网络训练的部不稳定,因此将没有物体的格子对应的loss加一个权重比如0.5就会解决这个问题)

6、yolo v2(yolo9000)的训练是联合进行训练的

YOLO9000 就是使用联合训练算法训练出来的,他拥有 9000 类的分类信息(yolo9000的名字来自于此),这些分类信息学习自ImageNet分类数据集,而物体位置检测则学习自 COCO 检测数据集,联合训练算法的基本思路就是:同时在检测数据集和分类数据集上训练物体检测器(Object Detectors ),用监测数据集的数据学习物体的准确位置,用分类数据集的数据来增加分类的类别量、提升鲁棒性。

在训练的过程中,当网络遇到一个来自检测数据集的图片与标记信息,那么就把这些数据用完整的 YOLO v2 loss 功能反向传播这个图片。当网络遇到一个来自分类数据集的图片和分类标记信息(没有物体位置标记信息框,只有类别信息),只用整个结构中分类部分的 loss 功能反向传播这个图片。

7、yolov1中每个网格不管预测几个box  ,但是只有一个类别信息,看他的输出就知道了,每个网格要预测 B 个 bounding box 还要预测 C 个 categories。输出就是 S x S x (5*B+C) 的一个 tensor,如果每个格子都是单独的类别预测,那么就应该是 S x S x (5*(B+C))

8、对于选择softmax分类器还是个logistic分类器,取决于所有类别之间是否互斥。所有类别之间明显互斥用softmax分类器,所有类别之间不互斥有交叉的情况下最好用个logistic分类器。

因为使用softmax会涉及到使用全部的数据做一个加和之类操作,有一个求和符号,所以最终的每一个预测值都和其他的数据值的大小相关,因此彼此之间多少有联系,而多个logistic则不存在这个问题,是多少就是多少。

9、查看map的解释:其实就是计算每一个类别的AP,然后在求全部类别的均值就得到了map(mean ap),其中ap的计算就是P-R曲线下的面积,一看就知道面积的值和准确率()和查全率有关系,但是曲线下的面积很不好求,需要进行积分等操作,那怎么办呢,那就是近似的思想,用一个便于计算的方法来计算一个值近似等于曲线下的面积,有很多种的方法,比如11点法,和COCO的计算方法,这里是依据Confidence排序后的顺序依次计算出Precision和Recall,然后在进行计算,有时候会看到AP备注为某一IOU下的计算,这里的变量Confidence的值的计算和IOU有关(IOU*置信度=Confidence),一般是固定一个IOU值,然后计算AP。具体的计算见MAP 11points 方法的计算

具体参照这两篇博客:

https://blog.csdn.net/zdh2010xyz/article/details/54293298

https://blog.csdn.net/holmes_MX/article/details/82466537  

https://blog.csdn.net/qq_17550379/article/details/79875784

COCO数据中计算AP的方法,采用的是Confidence在[0.5 : 0.05 : 0.95]计算10次AP,然后求均值的方法计算AP

10、yolo中常常提到的frontend 和 backend 其实对应的是两个文件或者说两种说法概念,其中backend更多的指的是yolo底层网络的定义和实现,比如我在backend中定义了两种网络tiny_yolo and full_yolo两种,那么在frontend中我就可以任意的调用这两种网络,搭建我的上层网络,其次在frontend中还可以定义loss等,从而更好的封装我们的函数,使得在最终的程序会特别简洁。

为什么在有的yolo网络中会有两个权重,一个yolo_backend, 一个yolo_xx.h5 ,这是因为就像上面说的在backend中会有一个基础的网络,这个技术的网络有一个权重,然后在此基础之上还有一个网络,整个网络在进行训练,然后这整个网络的权重保存在yolo_xx.h5中,所以可以说这是为了进行迁移学习.

11、为什么会有true_boxes这个输入,可以参考这个github上的解释(small hack to allow true_boxes to be registered when Keras build the model),因为要注册该输入,但是在真正的网络中该输入没有用到,只是为了编译模型好用而已。(比如就在该yolov3项目中,也将true_boxes(y_true)作为了输入,但是并没有’真正‘加入到网络中,只是在最后的loss计算的时候用到了,将model.output与true_boxes送入loss计算函数)

12、keras网络的输入为一个tuple,系统会 自动 将第一项识别为输入,第二项识别为输出,同理,对于keras的loss也一样,系统会自动的讲网络的输出识别为y_pre,将输入y识别为y_true, 这两个参数就是loss默认的参数,当然你也可以手动的指定,这都是在默认的情况下进行的,大多数情况下都是这么使用。

 

 

好的模型解释博客

yolov3网络结构说明:

https://blog.csdn.net/qq_37541097/article/details/81214953

https://blog.csdn.net/sum_nap/article/details/80568873

https://blog.csdn.net/yangchengtest/article/details/80664415

https://blog.csdn.net/leviopku/article/details/82660381

yolov1 yolov2 yolov3之间的演变之路及对比

https://blog.csdn.net/guleileo/article/details/80581858    (介绍的非常详细,细看这个会有很多的收获)

https://www.cnblogs.com/makefile/p/YOLOv3.html  (和上一个内容类似,但是多了一些具体网络结构参数的说明)

https://www.jianshu.com/p/f87be68977cb

 

https://blog.csdn.net/leviopku/article/details/81980249    可视化工具-做记录,没接触

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐