uniad模型详细介绍(一)

uniad模型

模型的backbone

这段代码配置的是一个 UniAD(Unified Tracking and Detection)模型的超参数和架构。


model(模型配置)

整个 model 字典包含了所有关于模型结构、参数以及训练设置的信息。

  • type="UniAD"

    表示模型类型是 UniAD,它是一个集成了 目标检测目标跟踪 的系统。

  • gt_iou_threshold=train_gt_iou_threshold

    这个参数用于设置 目标检测 中的 IoU 阈值,通常用来确定在训练时 ground truth (GT) 和预测框是否匹配。IoU(Intersection over Union)值越高,表示检测框和真实框的重叠程度越高。train_gt_iou_threshold 是外部传入的变量,用于动态设置这个阈值。

  • queue_length=queue_length
    queue_length 用于设置 队列长度 ,通常涉及模型的 记忆机制,例如 memory bank(记忆库)或者 batch 缓存。

  • use_grid_mask=True

    启用 grid mask,这通常用于数据增强中的遮挡操作。它可以随机将输入图像的一部分遮挡,以提高模型的鲁棒性。

  • video_test_mode=True

    设置是否启用视频测试模式。此配置通常在视频处理任务中使用,特别是当你在测试视频数据时,可能会有一些特殊的后处理需求。

  • num_query=900

    设置 查询数量 。在像 目标检测Transformer-based 模型 中,query 表示输入到模型的对象数量或检测框数量。900 可能是该模型用于检测或跟踪的最大对象数。

  • num_classes=10

    设置类别数,表示模型需要区分的目标类别数量。此处设置为 10 类。

  • pc_range=point_cloud_range

    这个参数用于设置 点云范围 ,通常用于 LiDAR 传感器数据。point_cloud_range 是外部传入的变量,定义了点云数据的空间范围。

  • pretrained=dict(img="torchvision://resnet50")

    指定了一个预训练模型。这里选择了 ResNet-50 作为图像部分的预训练模型,并从 torchvision 获取。预训练模型的使用有助于加速模型训练并提升性能。


img_backbone(图像主干网络)

img_backbone 配置图像的主干网络部分,用于从输入的图像中提取特征。

  • type="ResNet"

    使用 ResNet 作为主干网络,这是一种常见的深度卷积神经网络(CNN),特别适用于图像特征提取。

  • depth=50

    使用 ResNet-50,这个值指代 ResNet 的深度。50 表示网络有 50 层。

  • num_stages=4

    ResNet 通常由多个阶段(stages)组成,每个阶段负责不同尺度的特征提取。num_stages=4 表示 ResNet-50 有 4 个阶段。

  • out_indices=(3,)

    这个设置指定了要输出的特征层索引,3 表示输出最后一个阶段(即,ResNet-50 的第 4 个阶段)的特征图。

  • frozen_stages=1

    这个配置表示在训练过程中,ResNet 网络的前 1 个阶段是被冻结的,意味着这些层的参数在训练过程中不更新。通常用于迁移学习以减少计算量。

  • norm_cfg=dict(type="BN", requires_grad=False)

    使用 Batch Normalization (BN) 作为归一化方法,并且设置 BN 的参数不参与梯度更新。requires_grad=False 表示在训练过程中不更新 BN 参数。

  • norm_eval=True

    设置 BN 层在评估模式下保持不变,通常是在推理阶段(测试)使用。

  • style="pytorch"

    设置模型的初始化风格为 PyTorch 风格,确保预训练模型与 PyTorch 的实现兼容。


img_neck(图像 neck)

img_neck 配置了图像特征的后处理部分,通常用于对不同层的特征图进行融合或调整。

  • type="FPN"

    使用 Feature Pyramid Network (FPN),一种多尺度特征融合的架构,能够有效地捕获不同尺度的物体特征。

  • in_channels=[2048]

    输入特征图的通道数,2048 表示输入的特征图是从 ResNet-50 输出的最后一个阶段(第 4 个阶段),它的特征维度通常是 2048。

  • out_channels=_dim_

    输出特征图的通道数,_dim_ 是一个外部传入的变量,通常代表模型中某一层的特征维度。

  • start_level=0

    设置从哪个层开始进行 FPN 操作,0 表示从 ResNet 的第一个阶段(最低分辨率的特征)开始。

  • add_extra_convs="on_output"

    在输出时添加额外的卷积层。这是 FPN 的一种常见做法,用于进一步调整和融合特征。

  • num_outs=_num_levels_

    输出的层数,_num_levels_ 是外部传入的变量,表示要生成多少个尺度的输出特征图。

  • relu_before_extra_convs=True

    在添加额外卷积层之前是否应用 ReLU 激活函数。True 表示会应用。


其他设置

  • freeze_img_backbone=True

    冻结图像主干网络(ResNet-50),在训练过程中这些层的参数不会更新。这通常用于迁移学习,以减少训练的计算量。

  • freeze_img_neck=False

    不冻结图像 neck 部分,这意味着 FPN 部分的参数会在训练过程中更新。

  • freeze_bn=False

    不冻结 Batch Normalization 层,这样 BN 层的参数也会在训练中更新。

  • score_thresh=0.4

    这是 检测阈值,表示只有预测分数大于 0.4 的目标才会被视为有效目标进行后续处理。

  • filter_score_thresh=0.35

    另一个分数阈值,可能用于过滤低得分的检测结果或目标。


qim_args(Query Interaction Model 配置)

这个部分通常控制如何处理输入的 query(查询)。在 MOTR(或者类似 Transformer 模型)中,query 可能是指向量或特征集合。

  • qim_type="QIMBase"
    qim_typeQuery Interaction Model 类型的设置,"QIMBase" 可能是一个基类或预设类型。具体的实现和效果取决于你使用的框架和模型。

  • merger_dropout=0

    这个设置控制在合并不同查询的过程中是否有丢弃(dropout)。dropout=0 表示没有随机丢弃,这意味着模型将考虑所有的输入。

  • update_query_pos=True

    是否更新查询的位置嵌入(positional encoding)。True 表示查询的位置会随着模型训练过程更新,这有助于捕捉不同时间步或空间位置的信息。

  • fp_ratio=0.3
    fp_ratio 可能与 feature pooling (特征池化)或者 fine-tuning (微调)有关。0.3 表示在某个特定阶段,模型会保留30%的特征信息,进行进一步的优化。

  • random_drop=0.1

    在训练过程中随机丢弃部分输入 query,0.1 表示每次会随机丢弃10%的查询。这通常用于正则化,防止过拟合。


mem_args(Memory Bank 配置)

这个部分控制与 memory bank 相关的超参数,通常用于增强模型的记忆能力,尤其是在处理长时序或大规模数据时。

  • memory_bank_type="MemoryBank"
    memory_bank_type 决定了存储和访问记忆的方式,"MemoryBank" 可能是一个简单的存储类型,用于缓存过去的特征或查询结果。

  • memory_bank_score_thresh=0.0
    memory_bank_score_thresh 设置了一个阈值,通常用于筛选哪些记忆存储或特征需要被访问。如果某些存储的记忆得分低于这个阈值,它们可能就不会被使用。0.0 表示没有阈值限制。

  • memory_bank_len=4
    memory_bank_len 设置了记忆库的长度。4 表示记忆库最多会存储 4 个历史状态或特征(这通常是一个超参数,具体数值根据任务而定)。


模型的BEVFormerTrackHead部分

  • img.size() 的大小为 torch.Size([1, 5, 6, 3, 256, 416]),含义从左到右依次为:

    1. 1batch size(批大小) :当前实现仅支持 BS=1
    2. 5queue length / num frames(时间序列长度):一个 clip 内的帧数
    3. 6num cameras(相机数量) :NuScenes 为 6
    4. 3channels(图像通道):RGB 三通道
    5. 256height(图像高):预处理后高度
    6. 416width(图像宽):预处理后宽度

代码位置提示

  • fusionad_track.pyline 413)明确按:

    python 复制代码
    bs, len_queue, num_cams, C, H, W = imgs_queue.shape

    解包。

  • 随后会 reshape 成:

    python 复制代码
    [bs * len_queue, num_cams, C, H, W]
  • 再在 extract_img_feat 中按:

    python 复制代码
    B, N, C, H, W = img.size()

    使用。

    下面把这两句代码"按数据长什么样、每一步取到什么、为什么这样写"讲透,并用你给的实际尺寸做一个完整案例。


背景:你的输入是"时序 + 多相机"的 batch

你给的 img.size() 是:

  • img: torch.Size([1, 5, 6, 3, 256, 416])

按常见约定解释就是:

  • B=1:batch 里 1 个样本
  • T=5:时序 5 帧
  • N=6:每帧 6 个相机视角
  • C=3:RGB
  • H=256, W=416

所以 img[b, t, n] 取出来的是:第 b 个样本、第 t 帧、第 n 个相机的一张图,形状 [3, 256, 416]


1)img_single = torch.stack([img_[i] for img_ in img], dim=0)

关键点:for img_ in img 是在遍历 batch 维(第 0 维)

因为 img 是一个 Tensor,直接 for img_ in img 等价于:

python 复制代码
img_ = img[0]   # 第一个样本
# 如果 B>1,还会有 img[1], img[2]...

在你这里 B=1,所以循环只跑一次。

  • img_ 的形状:

    • 原来 img[B, T, N, C, H, W]
    • 取出一个样本后变成 [T, N, C, H, W]
    • 所以 img_.size() = [5, 6, 3, 256, 416]

然后取第 i 帧:img_[i]

  • img_[i] 是在时间维 T 上取第 i 帧
  • 形状从 [T, N, C, H, W] 变成 [N, C, H, W]

也就是:

  • img_[i].size() = [6, 3, 256, 416]

最后 stack(..., dim=0) 把 batch 维堆回来

列表里每个元素都是一个样本在第 i 帧的图像(形状 [N, C, H, W]),把它们沿 dim=0 堆起来:

  • 得到 img_single 形状 [B, N, C, H, W]

在你的例子里:

  • img_single.size() = [1, 6, 3, 256, 416]

✅ 这正好对应你观察到的:

  • img.size()[1, 5, 6, 3, 256, 416]
  • img_single.size()[1, 6, 3, 256, 416]

一句话:它把"时序 T"这一维挑出第 i 帧,变成单帧输入,但保留 batch 和多相机维。


2)img_metas_single = [copy.deepcopy(img_metas[0][i])]

img_metas 通常是"按 batch、时间"组织的元信息(每帧一个 dict),常见结构是:

  • img_metas[b][t] 是一个 dict
  • 比如包含 lidar2imgcam2imgimg_shapepad_shape、时间戳等

这句在做:

  1. img_metas[0]:取 batch 的第 0 个样本(因为当前实现默认 B=1
  2. [i]:取该样本的第 i 帧元信息
  3. deepcopy:防止后续单帧前向里改 metas(比如改 img_shapebatch_input_shapepad_shape 等)污染原来的时序 metas
  4. 外面包一层 [...]:因为下游接口一般期望 metas 是 "长度为 B 的 list",哪怕 B=1 也要是 list

为什么这段代码"隐含 B=1"?

因为 metas 只取了 img_metas[0],完全没遍历 batch。

如果你把 batch_size 改成 2,比如:

  • img.size() = [2, 5, 6, 3, 256, 416]

那这句:

python 复制代码
img_metas_single = [copy.deepcopy(img_metas[0][i])]

只会拿到第 0 个样本的 metas,第 1 个样本的 metas 丢了,下游就会错位或报错。


B>1 时应该怎么写(对应 img_single 的做法)

img_single 一样,应该对 batch 遍历:

python 复制代码
img_metas_single = [copy.deepcopy(metas_i[i]) for metas_i in img_metas]
# 其中 metas_i = img_metas[b],metas_i[i] = img_metas[b][i]

这样:

  • img_metas_single 长度就是 B
  • 每个元素都是对应样本的第 i 帧 dict
  • img_single[b] 一一对应

用你这个尺寸做一个"逐步取值"小例子(直观理解)

假设 i = 3(第 4 帧):

  • 原始:

    • img.shape = [1, 5, 6, 3, 256, 416]
  • 取样本:

    • img_ = img[0]
    • img_.shape = [5, 6, 3, 256, 416]
  • 取第 3 帧:

    • frame = img_[3]
    • frame.shape = [6, 3, 256, 416](6 个相机)
  • 堆回 batch:

    • img_single = stack([frame], dim=0)
    • img_single.shape = [1, 6, 3, 256, 416]
  • metas:

    • meta = img_metas[0][3](第 0 个样本、第 3 帧的 dict)
    • img_metas_single = [deepcopy(meta)](长度为 1 的 list)

相关推荐
康谋自动驾驶5 小时前
分享 | 如何做好全自动化ADAS 高精度标注?
自动化·自动驾驶·数据采集·数据标注·技术解析
小烤箱5 小时前
CUDA 编程完全理解系列(第一篇):GPU 的设计哲学与硬件架构基础
自动驾驶·硬件架构·cuda·并行计算·感知算法
m0_6501082410 小时前
OpenEMMA:开源多模态端到端自动驾驶框架全解析
论文阅读·自动驾驶·vla·高效推理·端到端ad·openemma
下海fallsea1 天前
避开欧美红海,深耕中东沙漠:萝卜快跑的差异化出海能走多远?
自动驾驶
m0_650108242 天前
VGGT-Long:突破千米级长 RGB 序列单目 3D 重建的极限
自动驾驶·机器人导航·vggt·3d视觉基础模型·千米级单目3d重建·通用模型·分块-对齐-闭环-全局优化
gorgeous(๑>؂<๑)2 天前
【中科院-张启超组-AAAI26】WorldRFT: 用于自动驾驶的带强化微调的潜在世界模型规划
人工智能·机器学习·自动驾驶
yuanmenghao2 天前
自动驾驶中间件iceoryx - 同步与通知机制(二)
开发语言·单片机·中间件·自动驾驶·信息与通信
yuanmenghao2 天前
自动驾驶中间件iceoryx - 同步与通知机制(一)
开发语言·网络·驱动开发·中间件·自动驾驶
yuanmenghao3 天前
CAN系列 — (6) CAN FD 带宽、CPU、中断:工程上是如何一起算的?
网络·驱动开发·单片机·mcu·自动驾驶·信息与通信