YOLO就是You Only Look Once的缩写,一看就很快对吧…
网络结构借鉴了GoogleNet(也就是之前说的Inception)中的NIN部分,他这里直说到了1*1卷积接3*3卷积, 但是如果只借鉴这一部分,那跟普通的卷积层区别其实不是很大(我猜可能是因为之前的普通卷积一般都是3*3接3*3或者5*5接5*5,一般都是保持不变或者卷积核越来越小),但是这里的1*1卷积接3*3卷积与以往的不同, 但是网络结构中并没有真正用NIN…
最终卷积网络出来的结果是S*S(S=7)的feature map,一个像素点就对应着原图的64*64的范围,对于这个范围每个bounding boxes(B=2),需要给出他属于哪一类(总共有C=20类),一个bounding boxes有四个位置参数,那么总共就有 S ⋅ S ⋅ ( B ⋅ 4 + C ) S \cdot S \cdot (B \cdot 4 + C) S⋅S⋅(B⋅4+C)
但是论文中却是 S ⋅ S ⋅ ( B ⋅ 5 + C ) S \cdot S \cdot (B \cdot 5 + C) S⋅S⋅(B⋅5+C)那多出来的这一个B又是啥呢?
前面Anchor部分: YOLO-v1的anchor不需要先预测是前景还是背景(也就是没有预测是不是obj那个步骤) 那在训练的时候总会有他不是obj的负例样本啊,那很明显他不属于某一类,坐标也无从谈起啊,那咋整涅?
于是作者采用了一个confidence的理念
c o n f i d e n c e = P r ( o b j e c t ) ∗ I O U p r e d t r u t h confidence = Pr(object) * IOU_{pred}{truth} confidence=Pr(object)∗IOUpredtruth
要注意的是,这个confidence在正向传播的时候不是先预测一个 P r ( o b j e c t ) Pr(object) Pr(object)再与GT的IOU相乘得到的,这个confidence就是一个隐藏层,是我们想让网络学到的,按照直觉confidence肯定是越大越好; 但是在构造训练集的confidence的label时候,就是按照这个公式构造的,也就是对于7*7*2个bounding boxes,那么只有GT就是1; 或者这样理解,confidence其实就是我们要求网络计算的一个指示变量,当这个指示变量接近1的时候,就认为这个框框住的是某一个物体, 当confidence接近0的时候,就认为这个框框住的不是物体;在这种情况下,负例样本也可以让网络学到东西,学到的东西就是这个指示变量;
Loss主要分为三部分
这里的(w,y,w,h)都是 [ 0 , 1 ] [0,1] [0,1]之间的值,因为每个(w,y,w,h)都是来自于某一个特定的Anchor,以该Anchor的左上角为原点,右下角为(1,1)的一个坐标系来构建的(w,y,w,h); 那为啥要这样做呢,直接用绝对坐标不是更省事吗,gt数据集还不用处理了…
以我的观点: 因为YOLO中所有都是回归问题,回归问题的解空间是 [ − ∞ , ∞ ] [-\infty,\infty] [−∞,∞],一旦采用了绝对坐标,那么就很难收敛,因为与坐标信息一起出去的还有分类信息,只在一个隐藏层特别是一个FC中很难做到一部分大一部分小;
那为什么是[0,1]而不是其他的[4,5]之类的呢?
因为分类的probability是[0,1],所以也用了[0,1]就保证了是在同一个维度上;所以一切东西弄到一个范式里面是有好处的…
这里的w,h的loss上面带了个根号,是为了大幅度地调小框,小幅度地调大框。 w越大,相对应的loss,应该更小,或者说小框的调整幅度在中心点差距相同时,调的幅度更大;如下图所示,相同的中心点差距,大框的IOU更大,而小框的IOU为0
理解这个confidence Loss的关键是要将Loss解耦,要知道Loss的哪一部分是网络给出的,那一部分是label的值,那一部分是即考虑Label又考虑网络的; 这一段论文中没有详细说,是看源码才能知道的…
S , B S,B S,B对应feature map的size、bbox数量,带有帽子的 ? ^ \hat{?} ?^的都是网络中得到的, ( x , y , w , h ) (x,y,w,h) (x,y,w,h)以及class都是数据给出的,这没啥问题; 重点是这个 C C C,他是考虑了 ( x ^ , y ^ , w ^ , h ^ ) (\hat{x},\hat{y},\hat{w},\hat{h}) (x^,y^,w^,h^)计算出预测框与gt的IOU,再乘上label中这个Anchor是否对应了obj而得到的; 所以这个 C C C是一个耦合的变量;
以下是我上github上找的一个实现,写的不简洁,但是注释很清楚,不是矩阵运算,更容易看懂
这里的分类Loss也是用回归的方法做的,loss函数就是MSE,与一般的交叉熵比起来肯定没那么优秀啦…
注意
还有一个值得注意的,就是那些 1 i , j o b j 1^{obj}_{i,j} 1i,jobj也是label值,网络中没有这一项输出,只能是label; 还有一个同样重要的,Faster R-CNN是先NMS筛框,而YOLO-v1则是先算loss,最终预测的时候才用NMS筛框…
最后就是Loss前面的系数了,这其实就是炼丹了,也没啥好说的,讲一下思想就行
因为都是MSE loss,所以得到的loss其实应该是差不多的,那么想要更重视那些,更不重视那些,就可以通过系数来设置
不过整体看下来,YOLO还是很简洁,很简单粗暴的,这样的网络改进空间大,而且代码也好写…