2023-简单点-yolox-pytorch代码解析(二)-nets/yolo.py

news2024/9/21 14:30:23

yolox-pytorch:nets/yolo.py

  • yolox网络结构
  • yolox-pytorch目录
  • 今天解析注释nets/yolo.py

yolox网络结构

这里是引用

yolox-pytorch目录

在这里插入图片描述

nets目录
在这里插入图片描述

今天解析注释nets/yolo.py


import torch
import torch.nn as nn

from .darknet import BaseConv, CSPDarknet, CSPLayer, DWConv

###################################################################################
class YOLOXHead(nn.Module):  
    def __init__(self, num_classes, width = 1.0, in_channels = [256, 512, 1024], act = "silu", depthwise = False,):  
        super().__init__()  # 调用父类的初始化方法  
  
        # 根据depthwise的值选择卷积类型,如果是深度可分离卷积,则使用DWConv,否则使用BaseConv  
        Conv            = DWConv if depthwise else BaseConv  
  
        # 初始化存储不同部分预测结果的列表  
        self.cls_convs  = nn.ModuleList()  # 分类卷积层  
        self.reg_convs  = nn.ModuleList()  # 回归卷积层  
        self.cls_preds  = nn.ModuleList()  # 分类预测层  
        self.reg_preds  = nn.ModuleList()  # 回归预测层  
        self.obj_preds  = nn.ModuleList()  # 目标存在性预测层  
        self.stems      = nn.ModuleList()  # stem卷积层,用于调整输入通道数  
  
        # 遍历每一个输入通道数  
        for i in range(len(in_channels)):  
            # stem卷积层,用于将输入通道数调整为指定的输出通道数  
            self.stems.append(BaseConv(in_channels = int(in_channels[i] * width), out_channels = int(256 * width), ksize = 1, stride = 1, act = act))  
  
            # 分类卷积层,包括两个卷积操作  
            self.cls_convs.append(nn.Sequential(*[  
                Conv(in_channels = int(256 * width), out_channels = int(256 * width), ksize = 3, stride = 1, act = act),   
                Conv(in_channels = int(256 * width), out_channels = int(256 * width), ksize = 3, stride = 1, act = act),   
            ]))  
            # 分类预测层,输出通道数为num_classes,表示每个像素位置可能的类别数量  
            self.cls_preds.append(  
                nn.Conv2d(in_channels = int(256 * width), out_channels = num_classes, kernel_size = 1, stride = 1, padding = 0)  
            )  
  
            # 回归卷积层,包括两个卷积操作  
            self.reg_convs.append(nn.Sequential(*[  
                Conv(in_channels = int(256 * width), out_channels = int(256 * width), ksize = 3, stride = 1, act = act),   
                Conv(in_channels = int(256 * width), out_channels = int(256 * width), ksize = 3, stride = 1, act = act)  
            ]))  
            # 回归预测层,输出通道数为4,表示每个目标的边框位置信息(x, y, w, h)  
            self.reg_preds.append(  
                nn.Conv2d(in_channels = int(256 * width), out_channels = 4, kernel_size = 1, stride = 1, padding = 0)  
            )  
            # 目标存在性预测层,输出通道数为1,表示每个像素位置是否有目标存在  
            self.obj_preds.append(  
                nn.Conv2d(in_channels = int(256 * width), out_channels = 1, kernel_size = 1, stride = 1, padding = 0)  
            )
	  def forward(self, inputs):
	        #---------------------------------------------------#
	        #   inputs输入
	        #   P3_out  80, 80, 256
	        #   P4_out  40, 40, 512
	        #   P5_out  20, 20, 1024
	        #---------------------------------------------------#
	        outputs = []
	        for k, x in enumerate(inputs):
	            #---------------------------------------------------#
	            #   利用1x1卷积进行通道整合
	            #---------------------------------------------------#
	            x       = self.stems[k](x)
	            #---------------------------------------------------#
	            #   利用两个卷积标准化激活函数来进行特征提取
	            #---------------------------------------------------#
	            cls_feat    = self.cls_convs[k](x)
	            #---------------------------------------------------#
	            #   判断特征点所属的种类
	            #   80, 80, num_classes
	            #   40, 40, num_classes
	            #   20, 20, num_classes
	            #---------------------------------------------------#
	            cls_output  = self.cls_preds[k](cls_feat)
	
	            #---------------------------------------------------#
	            #   利用两个卷积标准化激活函数来进行特征提取
	            #---------------------------------------------------#
	            reg_feat    = self.reg_convs[k](x)
	            #---------------------------------------------------#
	            #   特征点的回归系数
	            #   reg_pred 80, 80, 4
	            #   reg_pred 40, 40, 4
	            #   reg_pred 20, 20, 4
	            #---------------------------------------------------#
	            reg_output  = self.reg_preds[k](reg_feat)
	            #---------------------------------------------------#
	            #   判断特征点是否有对应的物体
	            #   obj_pred 80, 80, 1
	            #   obj_pred 40, 40, 1
	            #   obj_pred 20, 20, 1
	            #---------------------------------------------------#
	            obj_output  = self.obj_preds[k](reg_feat)
				# 将回归、目标存在性和分类的输出在第二个维度上进行拼接  
				output = torch.cat([reg_output, obj_output, cls_output], 1)  
				# 将拼接后的输出添加到outputs列表中  
				outputs.append(output)  
				# 返回包含所有尺度或所有层预测结果的outputs列表  
	           
	        return outputs


###################################################################################

# 导入PyTorch的nn模块  
class YOLOPAFPN(nn.Module):  
    def __init__(self, depth = 1.0, width = 1.0, in_features = ("dark3", "dark4", "dark5"), in_channels = [256, 512, 1024], depthwise = False, act = "silu"):  
        super().__init__()  # 调用父类nn.Module的初始化方法  
          
        # 根据depthwise的值选择卷积方式,如果是True则使用DWConv,否则使用BaseConv  
        Conv                = DWConv if depthwise else BaseConv  
          
        # 创建CSPDarknet作为backbone网络,其参数由外部传入  
        self.backbone       = CSPDarknet(depth, width, depthwise = depthwise, act = act)  
          
        # 存储输入特征层的名称  
        self.in_features    = in_features  
  
        # 定义上采样层,用于将特征图放大一倍  
        self.upsample       = nn.Upsample(scale_factor=2, mode="nearest")  
  
        # 以下部分是定义不同的卷积层和CSPLayer,用于特征提取和融合  
        # 注释中的数字表示特征图的尺寸和通道数,例如20, 20, 1024表示宽高为20,通道数为1024的特征图  
        #-------------------------------------------#  
        #   20, 20, 1024 -> 20, 20, 512  
        #-------------------------------------------#  
        self.lateral_conv0  = BaseConv(int(in_channels[2] * width), int(in_channels[1] * width), 1, 1, act=act)  
      
        #-------------------------------------------#  
        #   40, 40, 1024 -> 40, 40, 512  
        #-------------------------------------------#  
        self.C3_p4 = CSPLayer(  
            int(2 * in_channels[1] * width),  
            int(in_channels[1] * width),  
            round(3 * depth),  
            False,  
            depthwise = depthwise,  
            act = act,  
        )    
  
        #-------------------------------------------#  
        #   40, 40, 512 -> 40, 40, 256  
        #-------------------------------------------#  
        self.reduce_conv1   = BaseConv(int(in_channels[1] * width), int(in_channels[0] * width), 1, 1, act=act)  
  
        #-------------------------------------------#  
        #   80, 80, 512 -> 80, 80, 256  
        #-------------------------------------------#  
        self.C3_p3 = CSPLayer(  
            int(2 * in_channels[0] * width),  
            int(in_channels[0] * width),  
            round(3 * depth),  
            False,  
            depthwise = depthwise,  
            act = act,  
        )  
  
        #-------------------------------------------#  
        #   80, 80, 256 -> 40, 40, 256  
        #-------------------------------------------#  
        # 这里是一个卷积操作,但代码被注释掉了,所以没有实际执行任何操作
        # 定义一个卷积层,输入和输出的通道数都是in_channels[0] * width,卷积核大小为3,步长为2,激活函数为act  
		self.bu_conv2       = Conv(int(in_channels[0] * width), int(in_channels[0] * width), 3, 2, act=act)  
		  
		# 注释说明:该卷积层将特征图的尺寸从40x40变为20x20,通道数从256变为512  
		#-------------------------------------------#  
		#   40, 40, 256 -> 40, 40, 512  
		#-------------------------------------------#  
		  
		# 定义一个CSPLayer,输入通道数为2 * in_channels[0] * width,输出通道数为in_channels[1] * width,其他参数由外部传入  
		self.C3_n3 = CSPLayer(  
		    int(2 * in_channels[0] * width),  
		    int(in_channels[1] * width),  
		    round(3 * depth),  
		    False,  
		    depthwise = depthwise,  
		    act = act,  
		)  
		  
		# 定义另一个卷积层,输入和输出的通道数都是in_channels[1] * width,卷积核大小为3,步长为2,激活函数为act  
		self.bu_conv1       = Conv(int(in_channels[1] * width), int(in_channels[1] * width), 3, 2, act=act)  
		  
		# 注释说明:该卷积层将特征图的尺寸从40x40变为20x20,通道数从512变为1024  
		#-------------------------------------------#  
		#   40, 40, 512 -> 20, 20, 512  
		#-------------------------------------------#  
		  
		# 定义另一个CSPLayer,输入通道数为2 * in_channels[1] * width,输出通道数为in_channels[2] * width,其他参数由外部传入  
		self.C3_n4 = CSPLayer(  
		    int(2 * in_channels[1] * width),  
		    int(in_channels[2] * width),  
		    round(3 * depth),  
		    False,  
		    depthwise = depthwise,  
		    act = act,  
		)
   def forward(self, input):
        out_features            = self.backbone.forward(input)
        [feat1, feat2, feat3]   = [out_features[f] for f in self.in_features]

        #-------------------------------------------#
        #   20, 20, 1024 -> 20, 20, 512
        #-------------------------------------------#
        P5          = self.lateral_conv0(feat3)
        #-------------------------------------------#
        #  20, 20, 512 -> 40, 40, 512
        #-------------------------------------------#
        P5_upsample = self.upsample(P5)
        #-------------------------------------------#
        #  40, 40, 512 + 40, 40, 512 -> 40, 40, 1024
        #-------------------------------------------#
        P5_upsample = torch.cat([P5_upsample, feat2], 1)
        #-------------------------------------------#
        #   40, 40, 1024 -> 40, 40, 512
        #-------------------------------------------#
        P5_upsample = self.C3_p4(P5_upsample)

        #-------------------------------------------#
        #   40, 40, 512 -> 40, 40, 256
        #-------------------------------------------#
        P4          = self.reduce_conv1(P5_upsample) 
        #-------------------------------------------#
        #   40, 40, 256 -> 80, 80, 256
        #-------------------------------------------#
        P4_upsample = self.upsample(P4) 
        #-------------------------------------------#
        #   80, 80, 256 + 80, 80, 256 -> 80, 80, 512
        #-------------------------------------------#
        P4_upsample = torch.cat([P4_upsample, feat1], 1) 
        #-------------------------------------------#
        #   80, 80, 512 -> 80, 80, 256
        #-------------------------------------------#
        P3_out      = self.C3_p3(P4_upsample)  

        #-------------------------------------------#
        #   80, 80, 256 -> 40, 40, 256
        #-------------------------------------------#
        P3_downsample   = self.bu_conv2(P3_out) 
        #-------------------------------------------#
        #   40, 40, 256 + 40, 40, 256 -> 40, 40, 512
        #-------------------------------------------#
        P3_downsample   = torch.cat([P3_downsample, P4], 1) 
        #-------------------------------------------#
        #   40, 40, 256 -> 40, 40, 512
        #-------------------------------------------#
        P4_out          = self.C3_n3(P3_downsample) 

        #-------------------------------------------#
        #   40, 40, 512 -> 20, 20, 512
        #-------------------------------------------#
        P4_downsample   = self.bu_conv1(P4_out)
        #-------------------------------------------#
        #   20, 20, 512 + 20, 20, 512 -> 20, 20, 1024
        #-------------------------------------------#
        P4_downsample   = torch.cat([P4_downsample, P5], 1)
        #-------------------------------------------#
        #   20, 20, 1024 -> 20, 20, 1024
        #-------------------------------------------#
        P5_out          = self.C3_n4(P4_downsample)

        return (P3_out, P4_out, P5_out)

###################################################################################
# 定义了一个名为YoloBody的类,它继承了nn.Module,是PyTorch中的一个神经网络模型。  
class YoloBody(nn.Module):  
    # 初始化函数,当创建YoloBody类的实例时会被调用。  
    def __init__(self, num_classes, phi):  
        # 调用父类nn.Module的初始化函数。  
        super().__init__()  
          
        # 定义了两个字典,分别存储了不同phi值对应的深度和宽度系数。  
        depth_dict = {'nano': 0.33, 'tiny': 0.33, 's' : 0.33, 'm' : 0.67, 'l' : 1.00, 'x' : 1.33,}  
        width_dict = {'nano': 0.25, 'tiny': 0.375, 's' : 0.50, 'm' : 0.75, 'l' : 1.00, 'x' : 1.25,}  
          
        # 根据输入的phi值,从字典中获取对应的深度和宽度系数。  
        depth, width = depth_dict[phi], width_dict[phi]  
          
        # 判断phi值是否为'nano',如果是,则depthwise为True,否则为False。  
        depthwise = True if phi == 'nano' else False   
  
        # 创建YOLOPAFPN的实例作为backbone,参数包括depth、width和depthwise。  
        self.backbone = YOLOPAFPN(depth, width, depthwise=depthwise)  
          
        # 创建YOLOXHead的实例作为head,参数包括num_classes、width和depthwise。  
        self.head = YOLOXHead(num_classes, width, depthwise=depthwise)  
  
    # 定义前向传播函数。  
    def forward(self, x):  
        # 将输入x传递给backbone,得到fpn_outs。  
        fpn_outs = self.backbone.forward(x)  
          
        # 将fpn_outs传递给head,得到outputs。  
        outputs = self.head.forward(fpn_outs)  
          
        # 返回outputs。  
        return outputs



###################################################################################



###################################################################################

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

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

相关文章

各种与梅洛相关的葡萄酒知识

梅洛葡萄是可以通过其松散的大浆果串来识别的,与赤霞珠葡萄相比,这种颜色的蓝色/黑色调更少,皮肤更薄,单宁更少。与赤霞珠相比,梅洛葡萄的糖含量往往更高,苹果酸含量较低。梅洛在寒冷的土壤中茁壮成长&…

【云原生系列】Kubernetes知识点

目录 概念 基础架构 单master节点 多master节点 组件 Master节点核心组件 其他组件 请求发送流程 插件 核心资源 调度资源 Pod 创建pod组件间调用流程 pod生命周期: 初始化容器 镜像拉取策略 重启策略 钩子函数 探针 探针的实现方式 DownwardAP…

【Qt基础之QPalette实例电子时钟】

# 简介 借助`QLCDNumber`实现电子时钟,可以随意拖拽到桌面任意位置,鼠标右键进行关闭,用于实践`QPalette`类、`QTimer`的使用以及`mousePressEvent`\`mouseMoveEvent`\`mouseDoubleClickEvent`事件处理函数的使用。可在此基础上扩展其他应用,参看Qt帮助手册。 # QPalette …

画中画视频剪辑:批量制作画中画,提升视频制作技能

在视频制作过程中,画中画是一种常见的视觉效果,它能够使多个视频片段在同一画面中展示,增加信息的丰富度和视觉的吸引力。这种效果通常用于增加信息的丰富度,如在新闻节目中,同时展示主持人和采访对象的画面。画中画也…

windows下使用iperf3

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、使用步骤1.下载2.解压3.测试1.作为服务器使用2.作为客户端使用 总结 前言 windows使用iperf3和linux是一样的,而且可以相互操作。 一、使用步骤…

Java最难的语法<泛型>

时间过得很快,我们马上就进入了,Java最难语法的学习,加油吧! 1.包装类 想要学好泛型就要了解包装类。 在Java中,由于基本类型不是继承自Object,为了在泛型代码中可以支持基本类型,Java给每个…

Python入门06布尔值

目录 1 什么是布尔值2 怎么生成布尔值3 在控制程序中使用布尔值4 数据过滤、排序和其他高级操作总结 1 什么是布尔值 首先我们要学习一下布尔值的定义,布尔值是一种数据类型,它只有两个可能的值:True(真)或 False&…

scikit-opt几种数值模拟退火的代码示例,和参数详解,以及基础模拟退火的原理代码示例

python基础模拟退火原理示例 模拟退火的特性决定了一般可以用于算法的调参,相比较遗传算法来说,普遍更快一些,但是也更容易陷入局部最优。相对来说,遗传算法的更新解机制是在最每一个局部最优解附近盘旋游荡,则更容易…

View绘制

onDraw 绘制 canvas 画布 paint 画笔 坐标系 x y x 0 y 0 则屏幕左上角 y从上往下值增加 像素转换 dp2px 画线line drawLine 圆circle drawCircle drawPath: 在onSizeChanged 时候初始化 addCircle 添加圆 CW顺时针 CCW 逆时针 CW CCW填充规则不同 填充规则: 默认 …

NX二次开发UF_MTX2_vec_multiply_t 函数介绍

文章作者:里海 来源网站:https://blog.csdn.net/WangPaiFeiXingYuan UF_MTX2_vec_multiply_t Defined in: uf_mtx.h void UF_MTX2_vec_multiply_t(const double vec [ 2 ] , const double mtx [ 4 ] , double vec_product [ 2 ] ) overview 概述 Ret…

邮政快递物流查询,将指定某天签收的单号筛选出来

批量查询邮政快递单号的物流信息,将指定某天签收的单号筛选出来。 所需工具: 一个【快递批量查询高手】软件 邮政快递单号若干 操作步骤: 步骤1:运行【快递批量查询高手】软件,并登录 步骤2:点击主界面左…

python-nmap库使用教程(Nmap网络扫描器的Python接口)(功能:主机发现、端口扫描、操作系统识别等)

文章目录 Python-nmap库使用教程前置条件引入python-nmap创建Nmap扫描实例执行简单的主机发现(nmap -sn)示例,我有一台主机配置为不响应 ICMP 请求,但使用nmap -sn,仍然能够探测到设备: 端口扫描扫描特定端…

线性回归 调试方法

调试方法 特征缩放 对于某些不具有比较性的样本特征 x i x_i xi​ (比如对其他的x来说 x i x_i xi​ 相当大或者相当小),梯度下降的过程可能会非常漫长,并且可能来回波动才能最后收敛到全局的最小值。 在这样的情况下&#xff…

SAP BW层级结构小结属性数据源+专家例程实现层级结构增强加载

作者 idan lian 如需转载备注出处 BW信息对象-层级结构 RSH1 维护信息对象层级 这里的文本描述对应T表中的描述,文本数据源加载之后有数据 信息对象层级H表 以上描述都是根据自我理解翻译的,非官方翻译 层级标识:自动生成,其实…

CCF CSP认证 历年题目自练Day50

题目 试题编号: 201809-3 试题名称: 元素选择器 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 题目分析(个人理解) 还是先理解题意,关于html的部分,可以按照样例画出…

2000-2021年各省人口密度数据

2000-2021年各省人口密度数据 1、时间:2000-2021年 2、指标:地区、年份、年末常住总人口(万人)、面积(平方千米)、人口密度(人/平方千米) 3、来源:各省年鉴、统计年鉴、各省统计局…

Redis面试题-缓存穿透,缓存击穿和缓存雪崩

目录 缓存穿透 面试官:什么是缓存穿透 ? 怎么解决 ? 面试官:你能介绍一下布隆过滤器吗? 缓存击穿 面试官:什么是缓存击穿 ? 怎么解决 ? 缓存雪崩 面试官:什么是缓存雪崩 ? 怎么解决 ? 缓存穿透 面试官&a…

笔记二十六、React中路由懒加载的扩展使用

26.1 在路由中配置懒加载 lazy routes/index.jsx 代码 import {Navigate} from "react-router-dom"; import Home from "../components/Home"; import About from "../components/About"; // import Classify from "../components/Home/c…

Vue3 刷新后,pinia存储的数据丢失怎么解决

这个问题有两种解决办法: 一是使用pinia的持久化存储一是使用vue的依赖注入 刷新后,通过pinia存储的vue store数据丢失,实际上是因为Vue原组件卸载、新组件重新挂载导致的,vue store是挂载在组件上的,当刷新导致组件…

处理机调度与作业调度

处理机调度 一个批处理型作业,从进入系统并驻留在外存的后备队列上开始,直至作业运行完毕,可能要经历如下的三级调度 高级调度 也称为作业调度、长程调度、接纳调度。调度对象是作业 主要功能: 挑选若干作业进入内存 为作业创建…