先介绍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. CString/string 区别及其转化

    CString/string 区别及其转化 利用MFC进行编程时,我们从对话框中利用GetWindowText得到的字符串是CString类型,CString是属于MFC的类.而一些标准C/C++库函 ...

  2. cocosCreater开发时遇到的问题

    生成vscode任务后无法编译: ctrl +p  -> 输入task compile 编译任务时提示 :由于使用任务版本 0.1.0,以下工作区文件夹将被忽略 这是cocos默认生成的code ...

  3. 1、git基础介绍及远程/本地仓库、分支

    1. Git基础介绍 基于Git进行开发时,首先需要将远程仓库代码clone到本地,即为本地仓库.后续大部分时间都是基于本地仓库上的分支进行编码,最后将本地仓库的代码合入远程仓库. 1.1. 远程仓库 ...

  4. JSON.stringify与JSON.parse

      JSON.stringify(value [, replacer] [, space]) 用于将 对象 --> JSON 字符串. value:对象.数组.类 replacer: 数组时:v ...

  5. 判断鼠标进入容器的方向小Demo

    参考资料: 贤心博客:http://sentsin.com/web/112.html, Math.atan2(y,x) 解释 :http://www.w3school.com.cn/jsref/jsr ...

  6. 前端-----JavaScript 初识基础

    JavaScript的组成 JavaScript基础分为三个部分: ECMAScript:JavaScript的语法标准.包括变量.表达式.运算符.函数.if语句.for语句等. DOM:操作网页上的 ...

  7. 【原创】运维基础之Ansible(2)离线安装

    1 在一个能访问远程repo的服务器上执行,下载ansible及相关依赖的rpm包 # mkdir ansible# yum install --downloadonly --downloaddir= ...

  8. Spring Cloud构建微服务架构(五)服务网关

    通过之前几篇Spring Cloud中几个核心组件的介绍,我们已经可以构建一个简略的(不够完善)微服务架构了.比如下图所示: 我们使用Spring Cloud Netflix中的Eureka实现了服务 ...

  9. mtu简单说明

    总结:本地的mtu值==网络设备的mtu值是最优的,一般本地和网络设备的默认值都是1500(字节),没什么特殊需求,尽量不要修改 一.什么是 MTU 值   1 从字面上来说,MTU 是英文 Maxi ...

  10. 并发性能的隐形杀手之伪共享(false sharing)

    在并发编程过程中,我们大部分的焦点都放在如何控制共享变量的访问控制上(代码层面),但是很少人会关注系统硬件及 JVM 底层相关的影响因素.前段时间学习了一个牛X的高性能异步处理框架 Disruptor ...