yolo-world 源码解析(六)(2)

简介: yolo-world 源码解析(六)

yolo-world 源码解析(六)(1)https://developer.aliyun.com/article/1484140

.\YOLO-World\yolo_world\models\layers\__init__.py

# 版权声明,版权归腾讯公司所有
# 基于 CSPLayers 的 PAFPN 的基本模块
# 导入 yolo_bricks 模块中的相关类
from .yolo_bricks import (
    CSPLayerWithTwoConv,
    MaxSigmoidAttnBlock,
    MaxSigmoidCSPLayerWithTwoConv,
    ImagePoolingAttentionModule,
    )
# 导出给外部使用的类列表
__all__ = ['CSPLayerWithTwoConv',
           'MaxSigmoidAttnBlock',
           'MaxSigmoidCSPLayerWithTwoConv',
           'ImagePoolingAttentionModule']

.\YOLO-World\yolo_world\models\losses\dynamic_loss.py

# 导入必要的库
from typing import Optional
import torch
import torch.nn as nn
from torch import Tensor
from mmdet.models.losses.mse_loss import mse_loss
from mmyolo.registry import MODELS
# 注册模型类为CoVMSELoss
@MODELS.register_module()
class CoVMSELoss(nn.Module):
    def __init__(self,
                 dim: int = 0,
                 reduction: str = 'mean',
                 loss_weight: float = 1.0,
                 eps: float = 1e-6) -> None:
        super().__init__()
        # 初始化参数
        self.dim = dim
        self.reduction = reduction
        self.loss_weight = loss_weight
        self.eps = eps
    def forward(self,
                pred: Tensor,
                weight: Optional[Tensor] = None,
                avg_factor: Optional[int] = None,
                reduction_override: Optional[str] = None) -> Tensor:
        """Forward function of loss."""
        # 确保重写的减少参数在合法范围内
        assert reduction_override in (None, 'none', 'mean', 'sum')
        # 根据重写的减少参数或者默认减少参数来确定减少方式
        reduction = (
            reduction_override if reduction_override else self.reduction)
        # 计算协方差
        cov = pred.std(self.dim) / pred.mean(self.dim).clamp(min=self.eps)
        # 创建目标张量
        target = torch.zeros_like(cov)
        # 计算损失
        loss = self.loss_weight * mse_loss(
            cov, target, weight, reduction=reduction, avg_factor=avg_factor)
        return loss

.\YOLO-World\yolo_world\models\losses\__init__.py

# 版权声明,版权归腾讯公司所有
# 导入动态损失模块中的CoVMSELoss类
from .dynamic_loss import CoVMSELoss
# 导出CoVMSELoss类,供外部使用
__all__ = ['CoVMSELoss']

.\YOLO-World\yolo_world\models\necks\yolo_world_pafpn.py

# 导入必要的库
import copy
from typing import List, Union
import torch
import torch.nn as nn
from torch import Tensor
from mmdet.utils import ConfigType, OptMultiConfig
# 导入自定义的模型注册器和工具函数
from mmyolo.registry import MODELS
from mmyolo.models.utils import make_divisible, make_round
from mmyolo.models.necks.yolov8_pafpn import YOLOv8PAFPN
# 注册YOLOWorldPAFPN类为模型
@MODELS.register_module()
class YOLOWorldPAFPN(YOLOv8PAFPN):
    """Path Aggregation Network used in YOLO World
    Following YOLOv8 PAFPN, including text to image fusion
    """
    # 初始化函数,定义模型结构和参数
    def __init__(self,
                 in_channels: List[int],
                 out_channels: Union[List[int], int],
                 guide_channels: int,
                 embed_channels: List[int],
                 num_heads: List[int],
                 deepen_factor: float = 1.0,
                 widen_factor: float = 1.0,
                 num_csp_blocks: int = 3,
                 freeze_all: bool = False,
                 block_cfg: ConfigType = dict(type='CSPLayerWithTwoConv'),
                 norm_cfg: ConfigType = dict(type='BN',
                                             momentum=0.03,
                                             eps=0.001),
                 act_cfg: ConfigType = dict(type='SiLU', inplace=True),
                 init_cfg: OptMultiConfig = None) -> None:
        # 设置引导通道数、嵌入通道数和头数
        self.guide_channels = guide_channels
        self.embed_channels = embed_channels
        self.num_heads = num_heads
        self.block_cfg = block_cfg
        # 调用父类的初始化函数,传入参数
        super().__init__(in_channels=in_channels,
                         out_channels=out_channels,
                         deepen_factor=deepen_factor,
                         widen_factor=widen_factor,
                         num_csp_blocks=num_csp_blocks,
                         freeze_all=freeze_all,
                         norm_cfg=norm_cfg,
                         act_cfg=act_cfg,
                         init_cfg=init_cfg)
    # 构建自顶向下的层
    def build_top_down_layer(self, idx: int) -> nn.Module:
        """build top down layer.
        Args:
            idx (int): layer idx.
        Returns:
            nn.Module: The top down layer.
        """
        # 深拷贝块配置
        block_cfg = copy.deepcopy(self.block_cfg)
        # 更新块配置参数
        block_cfg.update(
            dict(in_channels=make_divisible(
                (self.in_channels[idx - 1] + self.in_channels[idx]),
                self.widen_factor),
                 out_channels=make_divisible(self.out_channels[idx - 1],
                                             self.widen_factor),
                 guide_channels=self.guide_channels,
                 embed_channels=make_round(self.embed_channels[idx - 1],
                                           self.widen_factor),
                 num_heads=make_round(self.num_heads[idx - 1],
                                      self.widen_factor),
                 num_blocks=make_round(self.num_csp_blocks,
                                       self.deepen_factor),
                 add_identity=False,
                 norm_cfg=self.norm_cfg,
                 act_cfg=self.act_cfg))
        # 构建模型
        return MODELS.build(block_cfg)
    # 构建底部向上的层
    def build_bottom_up_layer(self, idx: int) -> nn.Module:
        """build bottom up layer.
        Args:
            idx (int): layer idx.
        Returns:
            nn.Module: The bottom up layer.
        """
        # 深拷贝块配置
        block_cfg = copy.deepcopy(self.block_cfg)
        # 更新块配置
        block_cfg.update(
            dict(in_channels=make_divisible(
                (self.out_channels[idx] + self.out_channels[idx + 1]),
                self.widen_factor),
                 out_channels=make_divisible(self.out_channels[idx + 1],
                                             self.widen_factor),
                 guide_channels=self.guide_channels,
                 embed_channels=make_round(self.embed_channels[idx + 1],
                                           self.widen_factor),
                 num_heads=make_round(self.num_heads[idx + 1],
                                      self.widen_factor),
                 num_blocks=make_round(self.num_csp_blocks,
                                       self.deepen_factor),
                 add_identity=False,
                 norm_cfg=self.norm_cfg,
                 act_cfg=self.act_cfg))
        # 构建模型
        return MODELS.build(block_cfg)
    # 定义前向传播函数,接受多层级的图像特征和文本特征作为输入,返回元组
    def forward(self, img_feats: List[Tensor], txt_feats: Tensor) -> tuple:
        """Forward function.
        including multi-level image features, text features: BxLxD
        """
        # 断言图像特征的数量与输入通道数相同
        assert len(img_feats) == len(self.in_channels)
        
        # 减少层级
        reduce_outs = []
        for idx in range(len(self.in_channels)):
            reduce_outs.append(self.reduce_layers[idx](img_feats[idx]))
        # 自顶向下路径
        inner_outs = [reduce_outs[-1]]
        for idx in range(len(self.in_channels) - 1, 0, -1):
            feat_high = inner_outs[0]
            feat_low = reduce_outs[idx - 1]
            upsample_feat = self.upsample_layers[len(self.in_channels) - 1 - idx](feat_high)
            if self.upsample_feats_cat_first:
                top_down_layer_inputs = torch.cat([upsample_feat, feat_low], 1)
            else:
                top_down_layer_inputs = torch.cat([feat_low, upsample_feat], 1)
            inner_out = self.top_down_layers[len(self.in_channels) - 1 - idx](top_down_layer_inputs, txt_feats)
            inner_outs.insert(0, inner_out)
        # 自底向上路径
        outs = [inner_outs[0]]
        for idx in range(len(self.in_channels) - 1):
            feat_low = outs[-1]
            feat_high = inner_outs[idx + 1]
            downsample_feat = self.downsample_layers[idx](feat_low)
            out = self.bottom_up_layers[idx](torch.cat([downsample_feat, feat_high], 1), txt_feats)
            outs.append(out)
        # 输出层
        results = []
        for idx in range(len(self.in_channels)):
            results.append(self.out_layers[idx](outs[idx]))
        return tuple(results)
# 使用 @MODELS 注册 YOLOWorldDualPAFPN 类
@MODELS.register_module()
# 定义 YOLOWorldDualPAFPN 类,继承自 YOLOWorldPAFPN 类
class YOLOWorldDualPAFPN(YOLOWorldPAFPN):
    """Path Aggregation Network used in YOLO World v8."""
    # 初始化函数,接受多个参数
    def __init__(self,
                 in_channels: List[int],  # 输入通道列表
                 out_channels: Union[List[int], int],  # 输出通道列表或整数
                 guide_channels: int,  # 引导通道数
                 embed_channels: List[int],  # 嵌入通道列表
                 num_heads: List[int],  # 多头注意力机制的头数列表
                 deepen_factor: float = 1.0,  # 加深因子,默认为1.0
                 widen_factor: float = 1.0,  # 扩宽因子,默认为1.0
                 num_csp_blocks: int = 3,  # CSP块的数量,默认为3
                 freeze_all: bool = False,  # 是否冻结所有层,默认为False
                 text_enhancder: ConfigType = dict(  # 文本增强器配置
                     type='ImagePoolingAttentionModule',  # 类型为图像池化注意力模块
                     embed_channels=256,  # 嵌入通道数为256
                     num_heads=8,  # 多头注意力机制的头数为8
                     pool_size=3),  # 池化大小为3
                 block_cfg: ConfigType = dict(type='CSPLayerWithTwoConv'),  # 块配置,默认为CSPLayerWithTwoConv
                 norm_cfg: ConfigType = dict(type='BN',  # 归一化配置,默认为BN
                                             momentum=0.03,  # 动量为0.03
                                             eps=0.001),  # epsilon为0.001
                 act_cfg: ConfigType = dict(type='SiLU', inplace=True),  # 激活函数配置,默认为SiLU
                 init_cfg: OptMultiConfig = None) -> None:  # 初始化配置,默认为None,返回None
        # 调用父类的初始化函数
        super().__init__(in_channels=in_channels,
                         out_channels=out_channels,
                         guide_channels=guide_channels,
                         embed_channels=embed_channels,
                         num_heads=num_heads,
                         deepen_factor=deepen_factor,
                         widen_factor=widen_factor,
                         num_csp_blocks=num_csp_blocks,
                         freeze_all=freeze_all,
                         block_cfg=block_cfg,
                         norm_cfg=norm_cfg,
                         act_cfg=act_cfg,
                         init_cfg=init_cfg)
        # 更新文本增强器配置
        text_enhancder.update(
            dict(
                image_channels=[int(x * widen_factor) for x in out_channels],  # 图像通道数根据输出通道和扩宽因子计算
                text_channels=guide_channels,  # 文本通道数为引导通道数
                num_feats=len(out_channels),  # 特征数量为输出通道数的长度
            ))
        # 打印文本增强器配置
        print(text_enhancder)
        # 构建文本增强器模型
        self.text_enhancer = MODELS.build(text_enhancder)
    # 定义前向传播函数,接受图像特征列表和文本特征作为输入,返回元组
    def forward(self, img_feats: List[Tensor], txt_feats: Tensor) -> tuple:
        """Forward function."""
        # 断言图像特征列表的长度与输入通道数相同
        assert len(img_feats) == len(self.in_channels)
        
        # 减少层
        reduce_outs = []
        for idx in range(len(self.in_channels)):
            reduce_outs.append(self.reduce_layers[idx](img_feats[idx]))
        # 自顶向下路径
        inner_outs = [reduce_outs[-1]]
        for idx in range(len(self.in_channels) - 1, 0, -1):
            feat_high = inner_outs[0]
            feat_low = reduce_outs[idx - 1]
            upsample_feat = self.upsample_layers[len(self.in_channels) - 1 - idx](feat_high)
            if self.upsample_feats_cat_first:
                top_down_layer_inputs = torch.cat([upsample_feat, feat_low], 1)
            else:
                top_down_layer_inputs = torch.cat([feat_low, upsample_feat], 1)
            inner_out = self.top_down_layers[len(self.in_channels) - 1 - idx](top_down_layer_inputs, txt_feats)
            inner_outs.insert(0, inner_out)
        # 对文本特征进行增强
        txt_feats = self.text_enhancer(txt_feats, inner_outs)
        
        # 自底向上路径
        outs = [inner_outs[0]]
        for idx in range(len(self.in_channels) - 1):
            feat_low = outs[-1]
            feat_high = inner_outs[idx + 1]
            downsample_feat = self.downsample_layers[idx](feat_low)
            out = self.bottom_up_layers[idx](torch.cat([downsample_feat, feat_high], 1), txt_feats)
            outs.append(out)
        # 输出层
        results = []
        for idx in range(len(self.in_channels)):
            results.append(self.out_layers[idx](outs[idx]))
        return tuple(results)

.\YOLO-World\yolo_world\models\necks\__init__.py

# 版权声明,版权归腾讯公司所有
# 导入yolo_world_pafpn模块中的YOLOWorldPAFPN和YOLOWorldDualPAFPN类
from .yolo_world_pafpn import YOLOWorldPAFPN, YOLOWorldDualPAFPN
# 定义__all__列表,包含YOLOWorldPAFPN和YOLOWorldDualPAFPN类,用于模块导入时指定可导入的内容
__all__ = ['YOLOWorldPAFPN', 'YOLOWorldDualPAFPN']

.\YOLO-World\yolo_world\models\__init__.py

# 导入 Tencent 公司所有权的代码库
# 从 backbones 模块中导入所有内容
from .backbones import *  # noqa
# 从 layers 模块中导入所有内容
from .layers import *  # noqa
# 从 detectors 模块中导入所有内容
from .detectors import *  # noqa
# 从 losses 模块中导入所有内容
from .losses import *  # noqa
# 从 data_preprocessors 模块中导入所有内容
from .data_preprocessors import *  # noqa
# 从 dense_heads 模块中导入所有内容
from .dense_heads import *  # noqa
# 从 necks 模块中导入所有内容
from .necks import *  # noqa

.\YOLO-World\yolo_world\version.py

# 版权声明
# 版权所有 © 腾讯公司
# 定义版本号
__version__ = '0.1.0'
# 解析版本信息的函数
def parse_version_info(version_str):
    """Parse a version string into a tuple.
    Args:
        version_str (str): The version string.
    Returns:
        tuple[int | str]: The version info, e.g., "1.3.0" is parsed into
            (1, 3, 0), and "2.0.0rc1" is parsed into (2, 0, 0, 'rc1').
    """
    # 初始化版本信息列表
    version_info = []
    # 根据 '.' 分割版本号字符串
    for x in version_str.split('.'):
        # 如果是数字,则转换为整数
        if x.isdigit():
            version_info.append(int(x))
        # 如果包含 'rc',则分割出补丁版本号
        elif x.find('rc') != -1:
            patch_version = x.split('rc')
            version_info.append(int(patch_version[0]))
            version_info.append(f'rc{patch_version[1]}')
    # 返回版本信息元组
    return tuple(version_info)
# 调用解析版本信息函数,得到版本信息元组
version_info = parse_version_info(__version__)
# 导出的变量列表
__all__ = ['__version__', 'version_info', 'parse_version_info']

.\YOLO-World\yolo_world\__init__.py

# 导入当前目录下的 models 模块中的所有内容
from .models import *  # noqa
# 导入当前目录下的 datasets 模块中的所有内容
from .datasets import *  # noqa
# 导入当前目录下的 engine 模块中的所有内容
from .engine import *  # noqa
相关文章
|
6天前
|
移动开发 网络协议 安全
HTML5页面被运营商DNS问题及解决方案,app中h5页面源码的获取
HTML5页面被运营商DNS问题及解决方案,app中h5页面源码的获取
61 4
|
6天前
|
域名解析 网络协议 应用服务中间件
2024最新彩虹聚合DNS管理系统源码v1.3 全开源
聚合DNS管理系统可以实现在一个网站内管理多个平台的域名解析,目前已支持的域名平台有:阿里云、腾讯云、华为云、西部数码、DNSLA、CloudFlare。 本系统支持多用户,每个用户可分配不同的域名解析权限;支持API接口,支持获取域名独立DNS控制面板登录链接,方便各种IDC系统对接。
56 0
|
13天前
|
Linux 网络安全 Windows
网络安全笔记-day8,DHCP部署_dhcp搭建部署,源码解析
网络安全笔记-day8,DHCP部署_dhcp搭建部署,源码解析
|
14天前
HuggingFace Tranformers 源码解析(4)
HuggingFace Tranformers 源码解析
80 0
|
14天前
HuggingFace Tranformers 源码解析(3)
HuggingFace Tranformers 源码解析
68 0
|
14天前
|
开发工具 git
HuggingFace Tranformers 源码解析(2)
HuggingFace Tranformers 源码解析
35 0
|
14天前
|
并行计算
HuggingFace Tranformers 源码解析(1)
HuggingFace Tranformers 源码解析
32 0
|
15天前
PandasTA 源码解析(二十三)
PandasTA 源码解析(二十三)
47 0
|
15天前
PandasTA 源码解析(二十二)(3)
PandasTA 源码解析(二十二)
41 0
|
15天前
PandasTA 源码解析(二十二)(2)
PandasTA 源码解析(二十二)
46 2

推荐镜像

更多