先介绍YOLO[转]:

第一个颠覆ross的RCNN系列,提出region-free,把检测任务直接转换为回归来做,第一次做到精度可以,且实时性很好。 
1. 直接将原图划分为SxS个grid cell,如果有物体的中心落到这个格子里那么这个格子的gt就是这个物体。 
2. 每个格子被指定的gt需要对应B个bounding box(下面简称为bbox)去回归,也就是说每个格子对应的B个bbox的gt是一样的。 
3. 每个bbox预测5个值: x, y, w, h, 置信度。(x, y)是bbox的中心在对应格子里的相对位置,范围[0,1]。(w, h)是bbox相对于全图的的长宽,范围[0,1]。x, y, w, h的4个gt值可以算出来。confidence = P(object)* iou, 它的gt值是这样指定的: 若bbox对应格子包含物体,则P(object) = 1,否则P(object) = 0。它和ssd及rcnn系列在这里有个很不同的地方,它是直接回归bbox的位置,而ssd及rcnn系列是回归的是default box/anchor的偏移量,它没有default box/anchor这个东西。 
4. 每个格子也会预测属于各个类别的置信度,也就是每个格子对应的B个box是共享这个值的,这B个box只能属于一类的,所以和第一步呼应它们的gt都是一样的。 
5. inference阶段,class-specific confidence score既包含了bounding box最终属于哪个类别的概率,又包含了bounding box位置的准确度。最后设置一个阈值与class-specific confidence score对比,过滤掉score低于阈值的boxes,然后对score高于阈值的boxes进行非极大值抑制(NMS, non-maximum suppression)后得到最终的检测框体。

YOLO使用均方和误差作为loss函数来优化模型参数,即网络输出的S*S*(B*5 + C)维向量与真实图像的对应S*S*(B*5 + C)维向量的均方和误差。如下式所示。其中,coordError、iouError和classError分别代表预测数据与标定数据之间的坐标误差、IOU误差和分类误差。 
每个格子的 loss=coordError + iouError + classError 
YOLO对上式loss的计算进行了如下修正。

    1. 位置相关误差(坐标、IOU)与分类误差对网络loss的贡献值是不同的,因此YOLO在计算loss时,使用λcoord =5修正coordError。
    2. 在计算IOU误差时,包含物体的格子与不包含物体的格子,二者的IOU误差对网络loss的贡献值是不同的。若采用相同的权值,那么不包含物体的格子的confidence值近似为0,变相放大了包含物体的格子的confidence误差在计算网络参数梯度时的影响。为解决这个问题,YOLO 使用λnoobj =0.5修正iouError。(注此处的‘包含’是指存在一个物体,它的中心坐标落入到格子内)。
    3. 对于相等的误差值,大物体误差对检测的影响应小于小物体误差对检测的影响。这是因为,相同的位置偏差占大物体的比例远小于同等偏差占小物体的比例。YOLO将物体大小的信息项(w和h)进行求平方根来改进这个问题。(注:这个方法并不能完全解决这个问题)。

YOLO的loss

进一步理解YOLO

  1. 在YOLO网络中,首先通过一组CNN提取feature maps
  2. 然后通过最后一个全连接FC层生成SxSx(5*B+C)=7x7x(5*2+20)=1470长的向量
  3. 再把1470向量reshape成SxSx(5*B+C)=7x7x30形状的多维矩阵
  4. 通过解析多维矩阵获得Detection bounding box + Confidence
  5. 最后对Detection bounding box + Confidence进行Non maximum suppression获得输出

在设置好网络,并进行初始化后,通过forward就可以获得我们需要的SxSx(5*B+C)矩阵,只不过其中数值并不是我们想要的。当经过上述YOLO Loss下的负反馈训练后,显然就可以获得我们SxSx(5*B+C)矩阵,再经过解析+NMS就可以获得输出框了。

从本质上说,Faster RCNN通过对Anchors的判别和修正获得检测框;而YOLO通过强行回归获得检测框。

3.3 passthrough操作

修改后的网络最终在13 * 13的特征图上进行预测,虽然这足以胜任大尺度物体的检测,如果用上细粒度特征可能对小尺度的物体检测有帮助。Faser R-CNN和SSD都在不同层次的特征图上产生proposal以获得多尺度的适应性。

YOLOv2使用了一种不同的方法,简单添加一个 passthrough layer,把浅层特征图(分辨率为26 * 26)连接到深层特征图。passthrough layer把高低分辨率的特征图concat,叠加相邻特征到不同通道

这个方法把26 * 26 * 512的特征图叠加成13 * 13 * 2048的特征图,与原生的深层特征图相连接(即:加深channel的conv1与conv3 concat后作为conv4的输入)。

YOLOv2的检测器使用的就是经过扩展后的的特征图,它可以使用细粒度(浅层)特征,使得模型的性能获得了1%的提升。

regorg layer分析:这里ReorgLayer层就是将26∗26∗512的张量中26∗26切割成4个13∗13,然后连接起来,使得原来的512通道变成了2048。

 #darknet.py
self.reorg = ReorgLayer(stride=2) # stride*stride times the channels of conv1s
 #reorg_layer.py
def forward(self, x):
stride = self.stride bsize, c, h, w = x.size()
out_w, out_h, out_c = int(w / stride), int(h / stride), c * (stride * stride)
out = torch.FloatTensor(bsize, out_c, out_h, out_w) if x.is_cuda:
out = out.cuda()
reorg_layer.reorg_cuda(x, out_w, out_h, out_c, bsize, stride, 0, out)
else:
reorg_layer.reorg_cpu(x, out_w, out_h, out_c, bsize, stride, 0, out) return out
 //reorg_cpu.c
int reorg_cpu(THFloatTensor *x_tensor, int w, int h, int c, int batch, int stride, int forward, THFloatTensor *out_tensor)
{
// Grab the tensor
float * x = THFloatTensor_data(x_tensor);
float * out = THFloatTensor_data(out_tensor); // https://github.com/pjreddie/darknet/blob/master/src/blas.c
int b,i,j,k;
int out_c = c/(stride*stride); for(b = ; b < batch; ++b){
//batch_size
for(k = ; k < c; ++k){
//channel
for(j = ; j < h; ++j){
//height
for(i = ; i < w; ++i){
//width
int in_index = i + w*(j + h*(k + c*b));
int c2 = k % out_c;
int offset = k / out_c;
int w2 = i*stride + offset % stride;
int h2 = j*stride + offset / stride;
int out_index = w2 + w*stride*(h2 + h*stride*(c2 + out_c*b));
if(forward) out[out_index] = x[in_index]; // 压缩channel
else out[in_index] = x[out_index]; // 扩展channel
}
}
}
} return ;
}

图片有错误,待改,输入的1,3点分布在输出的第1个feature map上,输入的2,4点分布在输出的第2个feature map上,idx2后面+w2

下图从右到左为forward计算方向,从左到右为backward求导方向

3.4 目标函数计算

 #darknet.py
def loss(self):
#可以看出,损失值也是基于预测框bbox,预测的iou,分类三个不同的误差和
return self.bbox_loss + self.iou_loss + self.cls_loss def forward(self, im_data, gt_boxes=None, gt_classes=None, dontcare=None):
conv1s = self.conv1s(im_data)
conv2 = self.conv2(conv1s)
conv3 = self.conv3(conv2)
conv1s_reorg = self.reorg(conv1s)
cat_1_3 = torch.cat([conv1s_reorg, conv3], 1)
conv4 = self.conv4(cat_1_3)
conv5 = self.conv5(conv4) # batch_size, out_channels, h, w
……
……
# tx, ty, tw, th, to -> sig(tx), sig(ty), exp(tw), exp(th), sig(to)
'''预测tx ty'''
xy_pred = F.sigmoid(conv5_reshaped[:, :, :, 0:2])
'''预测tw th '''
wh_pred = torch.exp(conv5_reshaped[:, :, :, 2:4])
bbox_pred = torch.cat([xy_pred, wh_pred], 3)
'''预测置信度to '''
iou_pred = F.sigmoid(conv5_reshaped[:, :, :, 4:5])
'''预测分类class '''
score_pred = conv5_reshaped[:, :, :, 5:].contiguous()
prob_pred = F.softmax(score_pred.view(-1, score_pred.size()[-1])).view_as(score_pred) # for training
if self.training:
bbox_pred_np = bbox_pred.data.cpu().numpy()
iou_pred_np = iou_pred.data.cpu().numpy()
_boxes, _ious, _classes, _box_mask, _iou_mask, _class_mask = self._build_target(
bbox_pred_np, gt_boxes, gt_classes, dontcare, iou_pred_np)
_boxes = net_utils.np_to_variable(_boxes)
_ious = net_utils.np_to_variable(_ious)
_classes = net_utils.np_to_variable(_classes)
box_mask = net_utils.np_to_variable(_box_mask, dtype=torch.FloatTensor)
iou_mask = net_utils.np_to_variable(_iou_mask, dtype=torch.FloatTensor)
class_mask = net_utils.np_to_variable(_class_mask, dtype=torch.FloatTensor) num_boxes = sum((len(boxes) for boxes in gt_boxes)) # _boxes[:, :, :, 2:4] = torch.log(_boxes[:, :, :, 2:4])
box_mask = box_mask.expand_as(_boxes)
#计算预测的平均bbox损失值
self.bbox_loss = nn.MSELoss(size_average=False)(bbox_pred * box_mask, _boxes * box_mask) / num_boxes
#计算预测的平均iou损失值
self.iou_loss = nn.MSELoss(size_average=False)(iou_pred * iou_mask, _ious * iou_mask) / num_boxes
#计算预测的平均分类损失值
class_mask = class_mask.expand_as(prob_pred)
self.cls_loss = nn.MSELoss(size_average=False)(prob_pred * class_mask, _classes * class_mask) / num_boxes return bbox_pred, iou_pred, prob_pred

参考自:仙守

YOLO部分:

白裳

爆米花好美啊

YOLO V2 代码分析的更多相关文章

  1. YOLO v2 损失函数源码分析

    损失函数的定义是在region_layer.c文件中,关于region层使用的参数在cfg文件的最后一个section中定义. 首先来看一看region_layer 都定义了那些属性值: layer ...

  2. Linux kernel的中断子系统之(七):GIC代码分析

    返回目录:<ARM-Linux中断系统>. 总结: 原文地址:<linux kernel的中断子系统之(七):GIC代码分析> 参考代码:http://elixir.free- ...

  3. 目标检测之YOLO V2 V3

    YOLO V2 YOLO V2是在YOLO的基础上,融合了其他一些网络结构的特性(比如:Faster R-CNN的Anchor,GooLeNet的\(1\times1\)卷积核等),进行的升级.其目的 ...

  4. yolo v2使用总结

    以下都是基于yolo v2版本的,对于现在的v3版本,可以先clone下来,再git checkout回v2版本. 玩了三四个月的yolo后发现数值相当不稳定,yolo只能用来小打小闹了. v2训练的 ...

  5. 20145208 蔡野 《网络对抗》Exp4 恶意代码分析

    20145208 蔡野 <网络对抗>Exp4 恶意代码分析 问题回答 总结一下监控一个系统通常需要监控什么.用什么来监控. 监控一个系统通常需要监控这个系统的注册表,进程,端口,服务还有文 ...

  6. Linux中断 - GIC代码分析

    一.前言 GIC(Generic Interrupt Controller)是ARM公司提供的一个通用的中断控制器,其architecture specification目前有四个版本,V1-V4(V ...

  7. 20145312《网络对抗》Exp4 恶意代码分析

    20145312<网络对抗>Exp4 恶意代码分析 问题回答 1.总结一下监控一个系统通常需要监控什么.用什么来监控. 监控一个系统通常需要监控这个系统的注册表,进程,开放端口,程序服务还 ...

  8. insmod模块加载过程代码分析1【转】

    转自:http://blog.chinaunix.net/uid-27717694-id-3966290.html 一.概述模块是作为ELF对象文件存放在文件系统中的,并通过执行insmod程序链接到 ...

  9. 深入理解mmap--内核代码分析及驱动demo示例

    mmap是一个很常用的系统调用,无论是分配内存.读写大文件.链接动态库文件,还是多进程间共享内存,都可以看到其身影.本文首先介绍了进程地址空间和mmap,然后分析了内核代码以了解其实现,最后通过一个简 ...

随机推荐

  1. MySQL数据库之auto_increment【转】

    一.概述 在数据库应用中,我们经常需要用到自动递增的唯一编号来标识记录.在MySQL中,可通过数据列的auto_increment属性来自动生成.可在建表时可用“auto_increment=n”选项 ...

  2. CORS(Cross-origin resource sharing) “跨域资源共享”

    CORS与JSONP的比较 在出现CORS标准之前, 我们还只能通过jsonp的形式去向“跨源”服务器去发送 XMLHttpRequest 请求,这种方式吃力不讨好,在请求方与接收方都需要做处理,而且 ...

  3. JUnit3 和 JUnit4的区别

    JUnit3 和 JUnit4的区别 1.JUnit 4使用org.junit.*包而JUnit 3.8使用的是junit.Framework.*;为了向后兼容,JUnit4发行版中加入了这两种包. ...

  4. Vue-动态修改数组

    需求描述: 点击删除时,仅删除当前选中的这个对象. html: <el-card shadow="never" style="position: relative; ...

  5. makefile 中添加依赖的库文件

    当库文件中包含多个头文件和c源文件时,需要执行如下步骤: 1) makefile中添加 库文件依赖, -L 后面跟库文件的路径,  -l(小写)后面跟库的名字 2)将库文件中的头文件添加到工程中去,使 ...

  6. Zabbix3.0.4监控Windows的CPU使用百分比并在CPU使用率超过90%触发报警

    Zabbix3.0.4监控Windows的CPU使用百分比 Zabbix 自带的模块没有 CPU 使用率(百分比)这个监控项,我们可以通过添加计数器的方式实现 CPU 百分比的监控. 1.在Zabbi ...

  7. ebs 12.1.1升级到12.1.3

    升级过程参考 Oracle电子商务套件版本12.1.3自述文件 (文档 ID 1534411.1) 应用启动到维护模式 adadmin 打以下patch 9239089  9239090  92390 ...

  8. pyhon 前面补充和set

    一, 主要内容. 补充一个字符串的基本操作 li = ["李嘉诚", "麻花藤", "黄海峰", "刘嘉玲"] s = ...

  9. Boostrap轮图片可以左右滑动

    记得引用Boostrap的js和css html代码: <div id="Mycarousel" class="carousel slide col-md-12&q ...

  10. VBS学习

    简介 VBS windows脚本 Microsoft visual basic script editionVBS 是visual basic的一个抽象子集,系统内置,不编译为二进制文件,(由host ...