当前位置: 首页 > news >正文

网站建设文编高端企业门户网站建设费用

网站建设文编,高端企业门户网站建设费用,wordpress只显示文字,动漫设计和动漫制作技术哪个更好经典目标检测YOLO系列(二)YOLOV2的复现(1)总体网络架构及前向推理过程 和之前实现的YOLOv1一样#xff0c;根据《YOLO目标检测》(ISBN:9787115627094)一书#xff0c;在不脱离YOLOv2的大部分核心理念的前提下#xff0c;重构一款较新的YOLOv2检测器#xff0c;来对YOLOV2有…经典目标检测YOLO系列(二)YOLOV2的复现(1)总体网络架构及前向推理过程 和之前实现的YOLOv1一样根据《YOLO目标检测》(ISBN:9787115627094)一书在不脱离YOLOv2的大部分核心理念的前提下重构一款较新的YOLOv2检测器来对YOLOV2有更加深刻的认识。 书中源码连接: RT-ODLab: YOLO Tutorial 对比原始YOLOV2网络主要改进点如下 添加了后续YOLO中使用的neck即SPPF模块 使用普遍用在RetinaNet、FCOS、YOLOX等通用目标检测网络中的解耦检测头Decoupled head 修改损失函数分类分支替换为BCE loss回归分支替换为GIou loss。 由基于边界框的正样本匹配策略改为基于先验框的正样本匹配策略。 对比之前实现的YOLOV1网络主要改进点 主干网络由ResNet18改为DarkNet19 添加先验框机制 正样本匹配策略改为基于先验框的正样本匹配策略 YOLOv2代码和之前实现的YOLOv1相比修改之处不多建议先看之前实现的YOLOv1的相关文章。 1、YOLOv2网络架构 1.1 DarkNet19主干网络 使用原版YOLOv2中提出的DarkNet19作为主干网络(backbone)。不同于分类网络我们去掉网络中的平均池化层以及分类层。DarkNet19网络的下采样倍数为32一张图片(416×416×3)经过主干网络得到13×13×1024的特征图。根据官方的做法DarkNet19需要现在ImageNet数据集上进行预训练。不过作者提供了DarkNet19在ImageNet数据集上的预训练权重因此我们只需要直接加载即可。这里我们不去实现原版YOLOv2中的passthrough层仅仅输出一个尺度即c5层。 # RT-ODLab/models/detectors/yolov2/yolov2_backbone.pyimport torch import torch.nn as nnmodel_urls {darknet19: https://github.com/yjh0410/image_classification_pytorch/releases/download/weight/darknet19.pth, }__all__ [DarkNet19]# --------------------- Basic Module ----------------------- class Conv_BN_LeakyReLU(nn.Module):def __init__(self, in_channels, out_channels, ksize, padding0, stride1, dilation1):super(Conv_BN_LeakyReLU, self).__init__()self.convs nn.Sequential(nn.Conv2d(in_channels, out_channels, ksize, paddingpadding, stridestride, dilationdilation),nn.BatchNorm2d(out_channels),nn.LeakyReLU(0.1, inplaceTrue))def forward(self, x):return self.convs(x)# --------------------- DarkNet-19 ----------------------- class DarkNet19(nn.Module):def __init__(self):super(DarkNet19, self).__init__()# backbone network : DarkNet-19# output : stride 2, c 32self.conv_1 nn.Sequential(Conv_BN_LeakyReLU(3, 32, 3, 1),nn.MaxPool2d((2,2), 2),)# output : stride 4, c 64self.conv_2 nn.Sequential(Conv_BN_LeakyReLU(32, 64, 3, 1),nn.MaxPool2d((2,2), 2))# output : stride 8, c 128self.conv_3 nn.Sequential(Conv_BN_LeakyReLU(64, 128, 3, 1),Conv_BN_LeakyReLU(128, 64, 1),Conv_BN_LeakyReLU(64, 128, 3, 1),nn.MaxPool2d((2,2), 2))# output : stride 8, c 256self.conv_4 nn.Sequential(Conv_BN_LeakyReLU(128, 256, 3, 1),Conv_BN_LeakyReLU(256, 128, 1),Conv_BN_LeakyReLU(128, 256, 3, 1),)# output : stride 16, c 512self.maxpool_4 nn.MaxPool2d((2, 2), 2)self.conv_5 nn.Sequential(Conv_BN_LeakyReLU(256, 512, 3, 1),Conv_BN_LeakyReLU(512, 256, 1),Conv_BN_LeakyReLU(256, 512, 3, 1),Conv_BN_LeakyReLU(512, 256, 1),Conv_BN_LeakyReLU(256, 512, 3, 1),)# output : stride 32, c 1024self.maxpool_5 nn.MaxPool2d((2, 2), 2)self.conv_6 nn.Sequential(Conv_BN_LeakyReLU(512, 1024, 3, 1),Conv_BN_LeakyReLU(1024, 512, 1),Conv_BN_LeakyReLU(512, 1024, 3, 1),Conv_BN_LeakyReLU(1024, 512, 1),Conv_BN_LeakyReLU(512, 1024, 3, 1))def forward(self, x):c1 self.conv_1(x) # c1c2 self.conv_2(c1) # c2c3 self.conv_3(c2) # c3c3 self.conv_4(c3) # c3c4 self.conv_5(self.maxpool_4(c3)) # c4c5 self.conv_6(self.maxpool_5(c4)) # c5return c5# --------------------- Fsnctions ----------------------- def build_backbone(model_namedarknet19, pretrainedFalse):if model_name darknet19:# modelmodel DarkNet19()feat_dim 1024# load weightif pretrained:print(Loading pretrained weight ...)url model_urls[darknet19]# checkpoint state dictcheckpoint_state_dict torch.hub.load_state_dict_from_url(urlurl, map_locationcpu, check_hashTrue)# model state dictmodel_state_dict model.state_dict()# checkfor k in list(checkpoint_state_dict.keys()):if k in model_state_dict:shape_model tuple(model_state_dict[k].shape)shape_checkpoint tuple(checkpoint_state_dict[k].shape)if shape_model ! shape_checkpoint:checkpoint_state_dict.pop(k)else:checkpoint_state_dict.pop(k)print(k)model.load_state_dict(checkpoint_state_dict)return model, feat_dimif __name__ __main__:import timemodel, feat_dim build_backbone(pretrainedTrue)x torch.randn(1, 3, 416, 416)t0 time.time()for layer in model.children():x layer(x)print(layer.__class__.__name__, output shape:, x.shape)# y model(x)t1 time.time()print(Time: , t1 - t0)1.2 添加neck 和之前实现的YOLOv1一致选择YOLOV5版本中所用的SPPF模块。代码在RT-ODLab/models/detectors/yolov2/yolov2_neck.py文件中不在赘述。 1.3 Detection Head网络 和之前实现的YOLOv1一致即使用解耦检测头Decoupled head。代码在RT-ODLab/models/detectors/yolov2/yolov1_head.py文件中不在赘述。 1.4 预测层 如下图由于预测层多了先验框因此预测层的输出通道的数量略有变化。 ## 预测层# 与YoloV1相比YoloV2每个网格会预测5个框(VOC数据集)因此需×5self.obj_pred nn.Conv2d(head_dim, 1 * self.num_anchors, kernel_size1)self.cls_pred nn.Conv2d(head_dim, num_classes * self.num_anchors, kernel_size1)self.reg_pred nn.Conv2d(head_dim, 4 * self.num_anchors, kernel_size1)1.5 改进YOLOv2的详细网络图 与之前实现的YOLOv1相比主干网络由ResNet18变为DarkNet19每个网格预测5个anchor box其他方面一致。与原版的YOLOv2相比做了更加符合当下的设计理念的修改包括添加Neck模块、修改检测头等但是没有引入passthrough层。尽管和原版的YOLOv2有所差别但内核思想是一致的均是在YOLOv1的单级检测架构上引入了先验框。 # RT-ODLab/models/detectors/yolov2/yolov2.pyimport torch import torch.nn as nn import numpy as npfrom utils.misc import multiclass_nmsfrom .yolov2_backbone import build_backbone from .yolov2_neck import build_neck from .yolov2_head import build_head# YOLOv2 class YOLOv2(nn.Module):def __init__(self,cfg,device,num_classes20,conf_thresh0.01,nms_thresh0.5,topk100,trainableFalse,deployFalse,nms_class_agnosticFalse):super(YOLOv2, self).__init__()# ------------------- Basic parameters -------------------self.cfg cfg # 模型配置文件self.device device # cuda或者是cpuself.num_classes num_classes # 类别的数量self.trainable trainable # 训练的标记self.conf_thresh conf_thresh # 得分阈值self.nms_thresh nms_thresh # NMS阈值self.topk topk # topkself.stride 32 # 网络的最大步长self.deploy deployself.nms_class_agnostic nms_class_agnostic# ------------------- Anchor box -------------------self.anchor_size torch.as_tensor(cfg[anchor_size]).float().view(-1, 2) # [A, 2]self.num_anchors self.anchor_size.shape[0]# ------------------- Network Structure -------------------## 主干网络self.backbone, feat_dim build_backbone(cfg[backbone], trainablecfg[pretrained])## 颈部网络self.neck build_neck(cfg, feat_dim, out_dim512)head_dim self.neck.out_dim## 检测头self.head build_head(cfg, head_dim, head_dim, num_classes)## 预测层# 与YoloV1相比YoloV2每个网格会预测5个框(VOC数据集)因此需×5self.obj_pred nn.Conv2d(head_dim, 1 * self.num_anchors, kernel_size1)self.cls_pred nn.Conv2d(head_dim, num_classes * self.num_anchors, kernel_size1)self.reg_pred nn.Conv2d(head_dim, 4 * self.num_anchors, kernel_size1)if self.trainable:self.init_bias()def init_bias(self):# init biasinit_prob 0.01bias_value -torch.log(torch.tensor((1. - init_prob) / init_prob))nn.init.constant_(self.obj_pred.bias, bias_value)nn.init.constant_(self.cls_pred.bias, bias_value)def generate_anchors(self, fmp_size):passdef decode_boxes(self, anchors, reg_pred):passdef postprocess(self, obj_pred, cls_pred, reg_pred, anchors):后处理代码包括topk操作、阈值筛选和非极大值抑制passtorch.no_grad()def inference(self, x):bs x.shape[0]# 主干网络feat self.backbone(x)# 颈部网络feat self.neck(feat)# 检测头cls_feat, reg_feat self.head(feat)# 预测层obj_pred self.obj_pred(reg_feat)cls_pred self.cls_pred(cls_feat)reg_pred self.reg_pred(reg_feat)fmp_size obj_pred.shape[-2:]# anchors: [M, 2]anchors self.generate_anchors(fmp_size)# 对 pred 的size做一些view调整便于后续的处理# [B, A*C, H, W] - [B, H, W, A*C] - [B, H*W*A, C]obj_pred obj_pred.permute(0, 2, 3, 1).contiguous().view(bs, -1, 1) # [1, 84513×13×5, 1]cls_pred cls_pred.permute(0, 2, 3, 1).contiguous().view(bs, -1, self.num_classes)reg_pred reg_pred.permute(0, 2, 3, 1).contiguous().view(bs, -1, 4)# 测试时默认batch是1# 因此我们不需要用batch这个维度用[0]将其取走。obj_pred obj_pred[0] # [H*W*A, 1]cls_pred cls_pred[0] # [H*W*A, NC]reg_pred reg_pred[0] # [H*W*A, 4]if self.deploy:scores torch.sqrt(obj_pred.sigmoid() * cls_pred.sigmoid())bboxes self.decode_boxes(anchors, reg_pred)# [n_anchors_all, 4 C]outputs torch.cat([bboxes, scores], dim-1)return outputselse:# post processbboxes, scores, labels self.postprocess(obj_pred, cls_pred, reg_pred, anchors)return bboxes, scores, labelsdef forward(self, x):if not self.trainable:return self.inference(x)else:bs x.shape[0]# 主干网络feat self.backbone(x)# 颈部网络feat self.neck(feat)# 检测头cls_feat, reg_feat self.head(feat)# 预测层obj_pred self.obj_pred(reg_feat)cls_pred self.cls_pred(cls_feat)reg_pred self.reg_pred(reg_feat)fmp_size obj_pred.shape[-2:]# A就是Anchor的数量VOC数据集上设置为5# anchors: [M, 2], M H*W*Aanchors self.generate_anchors(fmp_size)# 对 pred 的size做一些view调整便于后续的处理# [B, A*C, H, W] - [B, H, W, A*C] - [B, H*W*A, C]obj_pred obj_pred.permute(0, 2, 3, 1).contiguous().view(bs, -1, 1)cls_pred cls_pred.permute(0, 2, 3, 1).contiguous().view(bs, -1, self.num_classes)reg_pred reg_pred.permute(0, 2, 3, 1).contiguous().view(bs, -1, 4)# decode bboxbox_pred self.decode_boxes(anchors, reg_pred)# 网络输出outputs {pred_obj: obj_pred, # (Tensor) [B, M, 1]pred_cls: cls_pred, # (Tensor) [B, M, C]pred_box: box_pred, # (Tensor) [B, M, 4]stride: self.stride, # (Int)fmp_size: fmp_size # (List) [fmp_h, fmp_w]} return outputs2、YOLOV2的前向推理 在1.5代码中还遗留几个问题 如何从边界框偏移量reg_pred解耦出边界框坐标box_pred如何实现后处理操作如何计算训练阶段的损失 2.1 解耦边界框坐标 2.1.1 先验框矩阵的生成 YOLOv2网络配置参数如下我们从中能看到anchor_size变量。这是基于kmeans聚类在COCO数据集上聚类出的先验框由于COCO数据集更大、图片更加丰富因此我们将这几个先验框用在VOC数据集上。 # RT-ODLab/config/model_config/yolov2_config.py # YOLOv2 Configyolov2_cfg {# inputtrans_type: ssd,multi_scale: [0.5, 1.5],# modelbackbone: darknet19,pretrained: True,stride: 32, # P5max_stride: 32,# neckneck: sppf,expand_ratio: 0.5,pooling_size: 5,neck_act: lrelu,neck_norm: BN,neck_depthwise: False,# headhead: decoupled_head,head_act: lrelu,head_norm: BN,num_cls_head: 2,num_reg_head: 2,head_depthwise: False,anchor_size: [[17, 25],[55, 75],[92, 206],[202, 21],[289, 311]], # 416# matcheriou_thresh: 0.5,# loss weightloss_obj_weight: 1.0,loss_cls_weight: 1.0,loss_box_weight: 5.0,# training configurationtrainer_type: yolov8, }回想一下在之前实现的YOLOv1中我们通过构造矩阵G得到了每一个网格(grid_xgrid_y)的坐标。 由于我们在YOLOv2中引入了先验框因此我们不仅需要每一个网格(grid_xgrid_y)的坐标还要包含先验框(5个)的尺寸信息。 先验框矩阵生成代码如下 # RT-ODLab/models/detectors/yolov2/yolov2.pydef generate_anchors(self, fmp_size):fmp_size: (List) [H, W]默认缩放后的图像为416×416那么经过32倍下采样后fmp_size为13×13# 1、特征图的宽和高fmp_w, fmp_h fmp_size# 2、生成网格的x坐标和y坐标anchor_y, anchor_x torch.meshgrid([torch.arange(fmp_h), torch.arange(fmp_w)])# 3、将xy两部分的坐标拼接起来shape为[H, W, 2]# 再转换下, shape变为[HW, 2]anchor_xy torch.stack([anchor_x, anchor_y], dim-1).float().view(-1, 2)# 4、引入了anchor box机制每个网格包含A个anchor因此每个(grid_x, grid_y)的坐标需要复制A(Anchor nums)份# 相当于 每个网格左上角的坐标点复制5份 作为5个不同宽高anchor box的中心点# [HW, 2] - [HW, A, 2] - [M, 2]anchor_xy anchor_xy.unsqueeze(1).repeat(1, self.num_anchors, 1)anchor_xy anchor_xy.view(-1, 2).to(self.device)# 5、将kmeans聚类得出的5组anchor box的宽高复制13×13份# [A, 2] - [1, A, 2] - [HW, A, 2] - [M, 2]anchor_wh self.anchor_size.unsqueeze(0).repeat(fmp_h*fmp_w, 1, 1)anchor_wh anchor_wh.view(-1, 2).to(self.device)# 6、将中心点和宽高cat起来得到的shape为[M, 4]# 其中M13×13×5 表示feature map为13×13每个网格有5组anchor box# 4代表anchor box的位置(x_center, y_center, w, h)# 需要注意:# x_center, y_center是feature map上的坐标位置需要×stride 才能得到缩放后原始图像上的中心点# w, h是针对缩放后原始图像anchors torch.cat([anchor_xy, anchor_wh], dim-1)return anchors2.1.2 解耦边界框 生成先验框矩阵后我们就能通过边界框偏移量reg_pred解耦出边界框坐标box_pred》。计算预测边界框的中心点坐标与之前计算YOLOv1是一致的但是计算宽高发生了变化。这是因为YOLOv2中我们引入了先验框而且我们先验框的尺寸设定是相对于resize后图像大小因此不需要乘stride。 def decode_boxes(self, anchors, reg_pred):1、依据预测值reg_pred(t_x,t_y,t_w,t_h)结算出边界框中心点坐标c_x, c_y和宽高b_w, b_hc_x ( grid_x sigmoid(t_x) ) × stridec_y ( grid_y sigmoid(t_y) ) × strideb_w p_w × exp(t_w)b_h p_h × exp(t_h)其中 grid_x,grid_y,p_w,p_h为先验框的结果即anchors结果2、转换为常用的x1y1x2y2形式。注意预测的宽高不是相对于feature map的而是相对于resize后图像大小因此不需要×stride# 1、计算预测边界框的中心点坐标和宽高pred_ctr (anchors[..., :2] torch.sigmoid(reg_pred[..., :2])) * self.stridepred_wh anchors[..., 2:] * torch.exp(reg_pred[..., 2:]) # 不需要×stride# 2、将所有bbox的中心点坐标和宽高换算成x1y1x2y2形式pred_x1y1 pred_ctr - pred_wh * 0.5pred_x2y2 pred_ctr pred_wh * 0.5pred_box torch.cat([pred_x1y1, pred_x2y2], dim-1)return pred_box2.2 后处理操作 之前YOLOv1的后处理操作仅仅包含了阈值筛选和非极大值抑制NMS这里由于引入了先验框因此我们后处理的框的数量由之前的13×13变成了13×13×5(845)个。这845个框不都是高质量的因此我们先做一个topk依据得分从高到低取前k个。对于COCO数据集来说一张图片的目标数量不超过100因此一般只需要设定topk100。这里作者为了提高测试的mAP默认设置topk1000。topk操作后继续进行阈值筛选和非极大值抑制。 # RT-ODLab/models/detectors/yolov2/yolov2.pydef postprocess(self, obj_pred, cls_pred, reg_pred, anchors):后处理代码包括topk操作、阈值筛选和非极大值抑制1、topk操作在coco数据集中检测对象的数量一半不会超过100因此先选择得分最高的k个边界框这里为了取得更高的mAP取k1000在实际的场景中不需要把k值取这么大2、滤掉低得分边界框的score低于给定的阈值的预测边界框3、滤掉那些针对同一目标的冗余检测。Input:obj_pred: (Tensor) [H*W*A, 1]cls_pred: (Tensor) [H*W*A, C]reg_pred: (Tensor) [H*W*A, 4]anchors: (Tensor) [H*W*A, 4]其中H*W*A 13×13×5 845# (H x W x A x C,)# 13×13×5×20 16900scores torch.sqrt(obj_pred.sigmoid() * cls_pred.sigmoid()).flatten()# 1、topk操作# Keep top k top scoring indices only.num_topk min(self.topk, reg_pred.size(0))# torch.sort is actually faster than .topk (at least on GPUs)predicted_prob, topk_idxs scores.sort(descendingTrue)topk_scores predicted_prob[:num_topk]topk_idxs topk_idxs[:num_topk]# 2、滤掉低得分边界框的score低于给定的阈值的预测边界框# filter out the proposals with low confidence scorekeep_idxs topk_scores self.conf_threshscores topk_scores[keep_idxs]topk_idxs topk_idxs[keep_idxs]# 获取flatten之前topk_scores所在的idx以及相应的labelanchor_idxs torch.div(topk_idxs, self.num_classes, rounding_modefloor) # 获取labels topk_idxs % self.num_classesreg_pred reg_pred[anchor_idxs]anchors anchors[anchor_idxs]# 解算边界框, 并归一化边界框: [H*W*A, 4]bboxes self.decode_boxes(anchors, reg_pred)# to cpu numpyscores scores.cpu().numpy()labels labels.cpu().numpy()bboxes bboxes.cpu().numpy()# 3、滤掉那些针对同一目标的冗余检测。# nmsscores, labels, bboxes multiclass_nms(scores, labels, bboxes, self.nms_thresh, self.num_classes, self.nms_class_agnostic)return bboxes, scores, labels接下来就到了正样本的匹配和损失函数计算了。 原版YOLOv2会先解耦出边界框计算边界框和目标框的IoU只有IoU最大的才被标记为正样本用来计算置信度损失、类别损失以及边界框位置损失其他预测的边界框均为负样本仅仅计算置信度损失。这样先验框没有为正样本匹配带来直接影响仅仅被用于解算边界框的坐标。既然先验框有边界框的先验尺寸信息那么它可以直接参与正样本的匹配因此我们接下来采用当下更加常用的策略来发挥先验框在标签匹配中的作用即基于先验框的正样本匹配策略。
http://www.zqtcl.cn/news/432502/

相关文章:

  • 太原专业网站建设杭州网络推广专员
  • 广西专业建网站橙米网站建设
  • 百度做的网站能优化吗html网站系统
  • php素材网站源码免费下载网站维护的内容有哪些
  • 打鱼跟电子游戏网站怎么做佛山微网站开发哪家好
  • 知名的网站建设网站在工信部备案
  • 网站首页的快照更新慢爆wordpress密码
  • dw做网站背景图片设置铺平微博通 wordpress
  • 勉县网站建设电商网站要素
  • 重庆旅游seo整站优化网站制作的一般步骤是什么
  • 网站建设评估体系p2p网站建设框架
  • .net 快速网站开发东莞网站建设公司哪家好
  • 东莞个人网站设计潍坊专业人员继续教育
  • 网站建设如何创业建设招标网官网
  • 公司没有销售网站怎么做业务怎么做微信推送 网站
  • 商城网站模版郴州网页定制
  • 电子商务网站建设步骤海外广告投放渠道
  • 网站用花生壳nas做存储十堰市网站建设
  • 用html5做手机网站抖音平台建站工具
  • 在线课程网站开发的研究意义网站开发需要哪些知识
  • 深圳网站优化怎么做手工艺品外贸出口公司网站建设方案
  • 从网站优化之角度出发做网站策划wordpress邀请码插件
  • 大学营销型网站建设实训课程o2o的四种营销模式
  • 咋做网站代码背景图宁远网站建设
  • 有哪些可以做网站的企业网站想换个风格怎么做
  • 怎么在百度搜索自己的网站在电脑上建设个人网站
  • wordpress网站菜单固定电商未来发展趋势前景
  • 五合一网站建设费用python 做网站 用哪个框架好
  • 波莱网站开发动态域名可以做网站吗
  • 网站建设 赣icp 南昌面馆装修设计