关于手撸YoloV3代码的可以看一下b站一个up主:深度学习麋了鹿
这里主要讲的是YoloV3中正负样本的生成以及我个人的理解。
1.正负样本生成的原理
1.1正样本的选择
首先先计算$gt$的中心落在哪个$grid$上,总共有3个特征层以及3个$anchor$总共生成9个先验框,选出与$gt$的$IOU$最大的那个先验框做为正样本。
1.2负样本的选择
计算各个先验框和所有的目标$gt$之间的$IOU$,如果某先验框和图像中所有物体最大的IOU都小于阈值(一般0.5),那么就认为该先验框不含目标,记作负样本,其置信度应当为0
1.3其他样本
对于剩下$IOU$大于阈值但不是与$gt$的$IOU$最大的那部分,这句话可能有点绕,可以这样简单理解,这个班上只要第一名作为学习的榜样,分数低于60分的大家作为反面教材,剩下大于60分但又不是第一名的那些人大家就不用管他了。
2.代码部分的讲解
这里贴一下麋鹿的手撸代码这部分就是$label$的生成,我个人也是按照他的视频讲解来写的
1 | labels={} |
1 | w,h=img.size |
这部分主要将中心点和宽高转移到对应尺寸上,比如当你图像的$size$是$(3.,3)$的时候你的中心点是$(2,2)$,当你reisze成$(9,9)$的时候,你的中心点应该转换成$(5,5)$
1 | labels[feature_size]=np.zeros(shape=(feature_size,feature_size,3,5+CLASS_NUM)) |
个人理解首先每个$grid$里面都应该对应一个宽高中心的置信度类别,所以最后的一个维度是:5+CLASS_NUM,然后3对应的是RGB三个通道,feature_size就是对应我们将图像分成几个部分。
1 | _x,x_index=math.modf(cx*feature_size/DATA_WIDTH) |
这个部分是将中心点转换到对应的grid中并且获得他的偏移量拿下面这个例子来说,假设图像的size是39*39的$gt$的中心为$(20,20)$那么此时中心点坐标其实转换到了$(1,1)$再加上$(7,7)$的偏移。

1 | iou=min(area,ANTORS_AREA[feature_size][i])/max(area,ANTORS_AREA[feature_size][i]) |
他这里的$IOU$的计算有点问题,我之后会一期关于各种IOU的讲解。
1 | p_w, p_h = w / antor[0], h / antor[1] |
这里的主要计算的是$gt$的宽高和$anchor$宽高的比值,注意这里损失函数的时候宽高做了$\log$处理是为了防止过宽或者过高影响网络。
1 | labels[feature_size][int(y_index),int(x_index),i]=np.array([iou,_x,_y,np.log(p_w),np.log(p_h),*one_hot(CLASS_NUM,int(cls))]) |
这部分主要是吧刚刚算出来正样本加入进去用之前得到的$x,y$的中心格位置,或者你这边直接归一化也可以。
这里讲一句对于正负样本不均匀的理解,举个例子就像小时候父母告诉我们做这个不好,做那个不好,实际上需要怎么做的好有时候他们并不会告诉我,导致我们只知道这样做是不好的,但是不知道怎么往好的方面发展。