037、目标检测-SSD实现

news2024/11/17 15:35:12

之——简单实现

目录

之——简单实现

杂谈

正文

1.类别预测层

2.边界框预测

3.多尺度输出联结做预测(提高预测效率)

4.多尺度实现

5.基本网络块

6.完整模型


杂谈

        原理查看:037、目标检测-算法速览-CSDN博客


正文

1.类别预测层

         类别预测的实现,锚框类别数num_classes+1背景:

        该图层使用填充为1的3×3的卷积层。此卷积层的输入和输出的宽度和高度保持不变,只是改变了通道数: 

import torch
import torchvision
from torch import nn
from torch.nn import functional as F
from d2l import torch as d2l


def cls_predictor(num_inputs, num_anchors, num_classes):
    return nn.Conv2d(num_inputs, num_anchors * (num_classes + 1),
                     kernel_size=3, padding=1)

2.边界框预测

        把边界框也看做一个预测问题,要预测的值就是两个坐标四个值,所以输出通道为4*num_anchors:

def bbox_predictor(num_inputs, num_anchors):
    return nn.Conv2d(num_inputs, num_anchors * 4, kernel_size=3, padding=1)


3.多尺度输出联结做预测(提高预测效率)

        单发多框检测使用多尺度特征图来生成锚框并预测其类别和偏移量。 在不同的尺度下,特征图的形状或以同一单元为中心的锚框的数量可能会有所不同。 因此,不同尺度下预测输出的形状可能会有所不同。

def forward(x, block):
    return block(x)

Y1 = forward(torch.zeros((2, 8, 20, 20)), cls_predictor(8, 5, 10))
Y2 = forward(torch.zeros((2, 16, 10, 10)), cls_predictor(16, 3, 10))
Y1.shape, Y2.shape

        通道维包含中心相同的锚框的预测结果。我们首先将通道维移到最后一维。 因为不同尺度下批量大小仍保持不变,我们可以将预测结果转成二维的(批量大小,高×宽×通道数)的格式,以方便之后在维度1上的连结 :

def flatten_pred(pred):
    return torch.flatten(pred.permute(0, 2, 3, 1), start_dim=1)

def concat_preds(preds):
    return torch.cat([flatten_pred(p) for p in preds], dim=1)

         


4.多尺度实现

        为了在多个尺度下检测目标,我们在下面定义了高和宽减半块down_sample_blk,该模块将输入特征图的高度和宽度减半。

def down_sample_blk(in_channels, out_channels):
    blk = []
    for _ in range(2):
        blk.append(nn.Conv2d(in_channels, out_channels,
                             kernel_size=3, padding=1))
        blk.append(nn.BatchNorm2d(out_channels))
        blk.append(nn.ReLU())
        in_channels = out_channels
    blk.append(nn.MaxPool2d(2))
    return nn.Sequential(*blk)

        跟当时VGG的实现极其类似,效果:

forward(torch.zeros((2, 3, 20, 20)), down_sample_blk(3, 10)).shape


5.基本网络块

        基本网络块用于从输入图像中抽取特征。 为了计算简洁,我们构造了一个小的基础网络,该网络串联3个高和宽减半块,并逐步将通道数翻倍。 给定输入图像的形状为256×256,此基本网络块输出的特征图形状为32×32:

def base_net():
    blk = []
    num_filters = [3, 16, 32, 64]
    for i in range(len(num_filters) - 1):
        blk.append(down_sample_blk(num_filters[i], num_filters[i+1]))
    return nn.Sequential(*blk)

forward(torch.zeros((2, 3, 256, 256)), base_net()).shape

6.完整模型

        完整的单发多框检测模型由五个模块组成。每个块生成的特征图既用于生成锚框,又用于预测这些锚框的类别和偏移量。在这五个模块中,第一个是基本网络块,第二个到第四个是高和宽减半块,最后一个模块使用全局最大池化将高度和宽度都降到1

def get_blk(i):
    if i == 0:
        blk = base_net()
    elif i == 1:
        blk = down_sample_blk(64, 128)
    elif i == 4:
        blk = nn.AdaptiveMaxPool2d((1,1))
    else:
        blk = down_sample_blk(128, 128)
    return blk

        每个块的前向传播:为每个块定义前向传播。与图像分类任务不同,此处的输出包括:CNN特征图Y;在当前尺度下根据Y生成的锚框;预测的这些锚框的类别和偏移量(基于Y):

def blk_forward(X, blk, size, ratio, cls_predictor, bbox_predictor):
    Y = blk(X)
    anchors = d2l.multibox_prior(Y, sizes=size, ratios=ratio)
    cls_preds = cls_predictor(Y)
    bbox_preds = bbox_predictor(Y)
    return (Y, anchors, cls_preds, bbox_preds)

        一个较接近顶部的多尺度特征块是用于检测较大目标的,因此需要生成更大的锚框。 在上面的前向传播中,在每个多尺度特征块上,我们通过调用的multibox_prior函数的sizes参数传递两个比例值的列表。

sizes = [[0.2, 0.272], [0.37, 0.447], [0.54, 0.619], [0.71, 0.79],
         [0.88, 0.961]]
ratios = [[1, 2, 0.5]] * 5
num_anchors = len(sizes[0]) + len(ratios[0]) - 1

        汇总:

class TinySSD(nn.Module):
    def __init__(self, num_classes, **kwargs):
        super(TinySSD, self).__init__(**kwargs)
        self.num_classes = num_classes
        idx_to_in_channels = [64, 128, 128, 128, 128]
        for i in range(5):
            # 即赋值语句self.blk_i=get_blk(i)
            setattr(self, f'blk_{i}', get_blk(i))
            setattr(self, f'cls_{i}', cls_predictor(idx_to_in_channels[i],
                                                    num_anchors, num_classes))
            setattr(self, f'bbox_{i}', bbox_predictor(idx_to_in_channels[i],
                                                      num_anchors))

    def forward(self, X):
        anchors, cls_preds, bbox_preds = [None] * 5, [None] * 5, [None] * 5
        for i in range(5):
            # getattr(self,'blk_%d'%i)即访问self.blk_i
            X, anchors[i], cls_preds[i], bbox_preds[i] = blk_forward(
                X, getattr(self, f'blk_{i}'), sizes[i], ratios[i],
                getattr(self, f'cls_{i}'), getattr(self, f'bbox_{i}'))
        anchors = torch.cat(anchors, dim=1)
        cls_preds = concat_preds(cls_preds)
        cls_preds = cls_preds.reshape(
            cls_preds.shape[0], -1, self.num_classes + 1)
        bbox_preds = concat_preds(bbox_preds)
        return anchors, cls_preds, bbox_preds

        训练:

batch_size = 32
train_iter, _ = d2l.load_data_bananas(batch_size)


device, net = d2l.try_gpu(), TinySSD(num_classes=1)
trainer = torch.optim.SGD(net.parameters(), lr=0.2, weight_decay=5e-4)

#损失函数和评价函数
cls_loss = nn.CrossEntropyLoss(reduction='none')
bbox_loss = nn.L1Loss(reduction='none')

def calc_loss(cls_preds, cls_labels, bbox_preds, bbox_labels, bbox_masks):
    batch_size, num_classes = cls_preds.shape[0], cls_preds.shape[2]
    cls = cls_loss(cls_preds.reshape(-1, num_classes),
                   cls_labels.reshape(-1)).reshape(batch_size, -1).mean(dim=1)
    bbox = bbox_loss(bbox_preds * bbox_masks,
                     bbox_labels * bbox_masks).mean(dim=1)
    return cls + bbox

def cls_eval(cls_preds, cls_labels):
    # 由于类别预测结果放在最后一维,argmax需要指定最后一维。
    return float((cls_preds.argmax(dim=-1).type(
        cls_labels.dtype) == cls_labels).sum())

def bbox_eval(bbox_preds, bbox_labels, bbox_masks):
    return float((torch.abs((bbox_labels - bbox_preds) * bbox_masks)).sum())





#训练
num_epochs, timer = 20, d2l.Timer()
animator = d2l.Animator(xlabel='epoch', xlim=[1, num_epochs],
                        legend=['class error', 'bbox mae'])
net = net.to(device)
for epoch in range(num_epochs):
    # 训练精确度的和,训练精确度的和中的示例数
    # 绝对误差的和,绝对误差的和中的示例数
    metric = d2l.Accumulator(4)
    net.train()
    for features, target in train_iter:
        timer.start()
        trainer.zero_grad()
        X, Y = features.to(device), target.to(device)
        # 生成多尺度的锚框,为每个锚框预测类别和偏移量
        anchors, cls_preds, bbox_preds = net(X)
        # 为每个锚框标注类别和偏移量
        bbox_labels, bbox_masks, cls_labels = d2l.multibox_target(anchors, Y)
        # 根据类别和偏移量的预测和标注值计算损失函数
        l = calc_loss(cls_preds, cls_labels, bbox_preds, bbox_labels,
                      bbox_masks)
        l.mean().backward()
        trainer.step()
        metric.add(cls_eval(cls_preds, cls_labels), cls_labels.numel(),
                   bbox_eval(bbox_preds, bbox_labels, bbox_masks),
                   bbox_labels.numel())
    cls_err, bbox_mae = 1 - metric[0] / metric[1], metric[2] / metric[3]
    animator.add(epoch + 1, (cls_err, bbox_mae))
print(f'class err {cls_err:.2e}, bbox mae {bbox_mae:.2e}')
print(f'{len(train_iter.dataset) / timer.stop():.1f} examples/sec on '
      f'{str(device)}')

         结果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1226701.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【力扣面试经典150题】(链表)K 个一组翻转链表

题目描述 力扣原文链接 给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。 k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。 你不能只…

“释放视频潜力,批量放大视频尺寸,高效提升视频质量“

在视频制作和编辑的过程中,我们经常需要调整视频的尺寸。然而,一个一个地手动调整不仅耗时,还容易出错。为了解决这个问题,现在有一款全新的视频批量剪辑工具,可以帮助你批量将视频尺寸放大,提升工作效率。…

Argo Rollouts结合Service进行Blue-Green部署

删除03 部署04 rootk8s-master01:~/learning-jenkins-cicd/09-argocd-and-rollout/rollout-demos# kubectl delete -f 03-rollouts-with-prometheus-analysis.yaml rootk8s-master01:~/learning-jenkins-cicd/09-argocd-and-rollout/rollout-demos# kubectl apply -f 04-rol…

C++多线程编程(3):接收线程处理函数的返回值

文章首发于我的个人博客:欢迎大佬们来逛逛 文章目录 处理带返回值的函数asyncpackaged_taskpromise 处理带返回值的函数 有三种方法: asyncpackaged_taskpromise async 第一种方法是使用 async 函数。 步骤: 使用 async 创建线程处理函…

pom.xml格式化快捷键

在软件开发和编程领域,"格式化"通常指的是将代码按照一定的规范和风格进行排列,以提高代码的可读性和维护性。格式化代码有助于使代码结构清晰、统一,并符合特定的编码规范。 格式化可以包括以下方面: 缩进&#xff1a…

HR应用在线人才测评,给企业招聘带来的好处

一、什么是人才测评? 人才测评是指运用一系列的科学方法,对人的基本素质,专业能力,心理健康,性格进行选拔,评价及发展人才的一种科学方法。近十多年,它被广泛运用于国有大型企业的人才招聘和人…

策略模式在数据接收和发送场景的应用(升级版)

1.背景 在数据接收和发送场景打算使用了 if else 进行判断: if("A".equals(system)){ASystem.sync("向A同步数据"); } if("B".equals(system)){BSystem.sync("向B同步数据"); } ... 非常麻烦,需求多了很臃肿&…

AI对开发者职业的影响,保持领先的7 个行动指南

在不断发展的技术领域,人工智能(AI)已经成为一股变革性的力量,重塑了行业,重新定义了我们解决问题的方式。对于开发人员来说,学习AI的决定不仅仅是为了保持相关性,而是在他们的职业生涯中开启一个新的可能性维度。 1.…

Scalable Exact Inference in Multi-Output Gaussian Processes

Orthogonal Instantaneous Linear Mixing Model TY are m-dimensional summaries,ILMM means ‘Instantaneous Linear Mixing Model’,OILMM means ‘Orthogonal Instantaneous Linear Mixing Model’ 辅助信息 作者未提供代码

【接口测试】最细Fiddle抓包辅助接口实战,抓包全过程总结...

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 1、为什么需要抓包…

Python开源项目周排行 2023年第38周

#2023年第38周2023年11月19日1easybc用于解析分组加密算法的输入 [EasyDC] 程序,然后根据差分密码分析对分组加密算法进行安全分析。它支持以下功能: EasyBC 的解释器。 基于 SMT 的方法,用于确定各种密码操作的分支数。 S-box 中的差分传播建…

C++多线程编程(1):线程的创建方式

文章首发于我的个人博客:欢迎大佬们来逛逛 文章目录 进行与线程C中如何实现多线程创建线程的多种方式无参函数lambda表达式常成员函数not常成员引用函数智能指针仿函数类的普通成员函数综合测试 进行与线程 多线程是指多个线程并发执行的过程。 进程与线程的关系&…

WIFI版本云音响设置教程腾讯云平台版本

文章目录 WIFI版本云音响设置教程腾讯云平台版本一、申请设备三元素1.腾讯云物联网平台2.创建产品3.设置产品参数4.添加设备5.获取三元素 二、设置设备三元素1.打开MQTTConfigTools2.计算MQTT参数3.使用windows电脑的WIFI连接到设备热点4.设置参数 三、腾讯云物联网套件协议使用…

Linux基础全整理 从入门到放弃,一些想说的话

阅读目录 断更后一些想说的话用户useraddpasswdpasswd文件详解 chageusermoduserdelshadow 文件格式切换用户 用户组groupaddgroup文件格式groupmodgroupdel登陆远程机器 磁盘RAIDraid0(安装系统)raid1(存放数据)raid 5&#xff0…

盘点54个Python实用工具源码Python爱好者不容错过

盘点54个Python实用工具源码Python爱好者不容错过 学习知识费力气,收集整理更不易。 知识付费甚欢喜,为咱码农谋福利。 链接:https://pan.baidu.com/s/1OXyEh-Yy3JI90jvn6d6wRw?pwd8888 提取码:8888 项目名称 7z辅助破解工…

基于冠状病毒群体免疫算法优化概率神经网络PNN的分类预测 - 附代码

基于冠状病毒群体免疫算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于冠状病毒群体免疫算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于冠状病毒群体免疫优化的PNN网络5.测试结果6.参考文献7.Matlab代码 …

漂亮的pyqt6皮肤 PyOneDark_Qt_Widgets_Modern_GUIPublic

大家先看看界面图,真的很漂亮: github地址:GitHub - Wanderson-Magalhaes/PyOneDark_Qt_Widgets_Modern_GUI 作者还录了教程: TUTORIALS: Tutorial 01: https://youtu.be/QQGlTGYCMg0 Tutorial 02: https://youtu.be/LwKre2proDk…

Halcon (4):如何开始自学

文章目录 文章专栏前言Halcon文档Halcon基础案例文档英语阅读建议 结论 文章专栏 Halcon开发 前言 在我完成上一篇代码,halcon基础窗口事件写完了之后,我已经基本掌握了如何写一个简单的halcon程序。后面我学习新的知识的时候感觉遇到了瓶颈。因为网上没…

【C++】:模板进阶

朋友们、伙计们,我们又见面了,本期来给大家解读一下有关C模板进阶的知识点,如果看完之后对你有一定的启发,那么请留下你的三连,祝大家心想事成! C 语 言 专 栏:C语言:从入门到精通 数…

『亚马逊云科技产品测评』活动征文|借助AWS EC2搭建服务器群组运维系统Zabbix+spug

授权声明:本篇文章授权活动官方亚马逊云科技文章转发、改写权,包括不限于在 Developer Centre, 知乎,自媒体平台,第三方开发者媒体等亚马逊云科技官方渠道。 本文基于以下软硬件工具: aws ec2 frp-0.52.3 zabbix 6…