熟女俱乐部五十路二区av,又爽又黄禁片视频1000免费,国产卡一卡二卡三无线乱码新区,中文无码一区二区不卡αv,中文在线中文a

"); //-->

博客專欄

EEPW首頁 > 博客 > 地平線靜態(tài)目標(biāo)檢測(cè) MapTR 參考算法 - V2.0

地平線靜態(tài)目標(biāo)檢測(cè) MapTR 參考算法 - V2.0

發(fā)布人:地平線開發(fā)者 時(shí)間:2025-06-28 來源:工程師 發(fā)布文章

該示例為參考算法,僅作為在征程 6 上模型部署的設(shè)計(jì)參考,非量產(chǎn)算法

一、簡(jiǎn)介

高清地圖是自動(dòng)駕駛系統(tǒng)的重要組件,提供精確的駕駛環(huán)境信息和道路語義信息。傳統(tǒng)離線地圖構(gòu)建方法成本高,維護(hù)復(fù)雜,使得依賴車載傳感器的實(shí)時(shí)感知建圖成為新趨勢(shì)。早期實(shí)時(shí)建圖方法存在局限性,如處理復(fù)雜地圖元素的能力不足、缺乏實(shí)例級(jí)信息等,在實(shí)時(shí)性和后處理

復(fù)雜度上存在挑戰(zhàn)。

為了解決這些問題,基于 Transformer 的 MapTR 模型被提出,它采用端到端結(jié)構(gòu),僅使用圖像數(shù)據(jù)就能實(shí)現(xiàn)高精度建圖,同時(shí)保證實(shí)時(shí)性和魯棒性。MapTRv2 在此基礎(chǔ)上增加了新特性,進(jìn)一步提升了建圖精度和性能。

地平線面向智駕場(chǎng)景推出的征程 6 系列(征程 6)芯片,在提供強(qiáng)大算力的同時(shí)帶來了極致的性價(jià)比,征程 6 芯片對(duì)于 Transformer 模型的高效支持助力了 MapTR 系列模型的端側(cè)部署。本文將詳細(xì)介紹地平線算法工具鏈在征程 6 芯片部署 MapTR 系列模型所做的優(yōu)化以及模型端側(cè)的表現(xiàn)。

二、性能精度指標(biāo)

模型配置:

image.png

性能精度表現(xiàn):

image.png


    三、公版模型介紹

    3.1 MapTR

    image.png

    MapTR 模型的默認(rèn)輸入是車載攝像頭采集到的 6 張相同分辨率的環(huán)視圖像,使用 nuScenes 數(shù)據(jù)集,同時(shí)也支持拓展為多模態(tài)輸入例如雷達(dá)點(diǎn)云。模型輸出是矢量化的地圖元素信息,其中地圖元素為人行橫道、車道分隔線和道路邊界 3 種。模型主體采用 encoder-decoder 的端到端結(jié)構(gòu):


      3.2 MapTRv2

      image.png

      MapTRv2 在 MapTR 的基礎(chǔ)上增加了新的特性:


        四、地平線部署說明

        地平線參考算法使用流程請(qǐng)參考征程 6 參考算法使用指南;對(duì)應(yīng)高效模型設(shè)計(jì)建議請(qǐng)參考《征程 6 平臺(tái)算法設(shè)計(jì)建議》

        MapTROE 模型引入了 SD map 的前融合結(jié)構(gòu),與圖像視角轉(zhuǎn)換后的 bev feature 進(jìn)行融合,再通過優(yōu)化后的 MapTR head 生成矢量化的地圖元素。整體結(jié)構(gòu)如下:

        image.png

        因此 maptroe_henet_tinym_bevformer_nuscenes 模型相比之前版本新增了如下優(yōu)化點(diǎn):

          maptroe_henet_tinym_bevformer_nuscenes 模型對(duì)應(yīng)的代碼路徑:

          image.png

          4.1 性能優(yōu)化

          4.1.1 Backbone

          MapTROE 采用基于征程 6 芯片的高效輕量化 Backbone HENet_TinyM(Hybrid Efficient Network, Tiny for J6M),HENet 能更好地利用征程 6 系列芯片的算力,在模型精度和性能上更具優(yōu)勢(shì)。HENet_TinyM 采用了純 CNN 架構(gòu),總體分為四個(gè) stage,每個(gè) stage 會(huì)進(jìn)行一次 2 倍下采樣,具體結(jié)構(gòu)配置如下:

          # henet-tinym
          depth = [4, 3, 8, 6]
          block_cls = ["GroupDWCB", "GroupDWCB", "AltDWCB", "DWCB"]
          width = [64, 128, 192, 384]
          attention_block_num = [0, 0, 0, 0]
          mlp_ratios, mlp_ratio_attn = [2, 2, 2, 3], 2
          act_layer = ["nn.GELU", "nn.GELU", "nn.GELU", "nn.GELU"]
          use_layer_scale = [True, True, True, True]
          extra_act = [False, False, False, False]
          final_expand_channel, feature_mix_channel = 0, 1024
          down_cls = ["S2DDown", "S2DDown", "S2DDown", "None"]
          patch_embed = "origin"

          4.1.2 Neck

          Neck 部分采用了地平線內(nèi)部實(shí)現(xiàn)的 FPN,相比公版 FPN 實(shí)現(xiàn),在征程 6 平臺(tái)上性能更加友好。

          4.1.3 View Transformer

          地平線參考算法版本將基于 LSS 的視角轉(zhuǎn)換方式替換為深度優(yōu)化后 Bevformer 的 View Transformer 部分。

            # 公版模型
            class MapTRPerceptionTransformer(BaseModule):
                ...
                def attn_bev_encode(...):
                    ...
                    if prev_bev is not None:
                        if prev_bev.shape[1] == bev_h * bev_w:
                            prev_bev = prev_bev.permute(1, 0, 2)
                        if self.rotate_prev_bev:
                            for i in range(bs):
                                # num_prev_bev = prev_bev.size(1)
                                rotation_angle = kwargs['img_metas'][i]['can_bus'][-1]
                                tmp_prev_bev = prev_bev[:, i].reshape(
                                    bev_h, bev_w, -1).permute(2, 0, 1)
                                tmp_prev_bev = rotate(tmp_prev_bev, rotation_angle,
                                                      center=self.rotate_center)
                                tmp_prev_bev = tmp_prev_bev.permute(1, 2, 0).reshape(
                                    bev_h * bev_w, 1, -1)
                                prev_bev[:, i] = tmp_prev_bev[:, 0]
                    
                    # add can bus signals
                    can_bus = bev_queries.new_tensor(
                        [each['can_bus'] for each in kwargs['img_metas']])  # [:, :]
                    can_bus = self.can_bus_mlp(can_bus[:, :self.len_can_bus])[None, :, :]
                    bev_queries = bev_queries + can_bus * self.use_can_bus
                    ...
            
            # 地平線參考算法
            class BevFormerViewTransformer(nn.Module):
                ...
                def __init__(...):
                    ...
                    self.prev_frame_info = {
                        "prev_bev": None,
                        "scene_token": None,
                        "ego2global": None,
                    }
                    ...
                def get_prev_bev(...):
                    if idx == self.queue_length - 1 and self.queue_length != 1:
                        prev_bev = torch.zeros(
                            (bs, self.bev_h * self.bev_w, self.embed_dims),
                            dtype=torch.float32,
                            device=device,
                        )
                        ...
                    else:
                        prev_bev = self.prev_frame_info["prev_bev"]
                        if prev_bev is None:
                            prev_bev = torch.zeros(
                                (bs, self.bev_h * self.bev_w, self.embed_dims),
                                dtype=torch.float32,
                                device=device,
                            ) # 對(duì)應(yīng)改動(dòng)2.a
                            ...
                def bev_encoder(...):
                    ...
                    tmp_prev_bev = prev_bev.reshape(
                        bs, self.bev_h, self.bev_w, self.embed_dims
                    ).permute(0, 3, 1, 2)
                    prev_bev = F.grid_sample(
                        tmp_prev_bev, norm_coords, "bilinear", "zeros", True
                    ) # 對(duì)應(yīng)改動(dòng)2.b
                    ...
            class SingleBevFormerViewTransformer(BevFormerViewTransformer):
                ...
                def get_bev_embed(...):
                    ...
                    bev_query = self.bev_embedding.weight
                    bev_query = bev_query.unsqueeze(1).repeat(1, bs, 1) # 對(duì)應(yīng)改動(dòng)2.c
                    ...

            d. 取消了公版的 TemporalSelfAttention,改為 HorizonMSDeformableAttention,保持精度的同時(shí)提升速度;

            # 公版模型Config
            model = dict(
                ...
                pts_bbox_head=dict(
                    type='MapTRHead',
                    ...
                    transformer=dict(
                        type='MapTRPerceptionTransformer',
                        ...
                        encoder=dict(
                            type='BEVFormerEncoder',
                            ...
                            transformerlayers=dict(
                                type='BEVFormerLayer',
                                attn_cfgs=[
                                    dict(
                                        type='TemporalSelfAttention',
                                        embed_dims=_dim_,
                                        num_levels=1),
                                        ...
                                ]
                            )
                        )
                    )
                )
            )
            
            # 地平線參考算法Config
            model = dict(
                ...
                view_transformer=dict(
                    type="SingleBevFormerViewTransformer",
                    ...
                    encoder=dict(
                        type="SingleBEVFormerEncoder",
                        ...
                        encoder_layer=dict(
                            type="SingleBEVFormerEncoderLayer",
                            ...
                            selfattention=dict(
                                type="HorizonMSDeformableAttention", # 對(duì)應(yīng)改動(dòng)2.d
                                ...
                            ),
                        )
                    )
                )
            )

            e. 支持公版 Bevformer 中的 bev_mask,并將涉及到的 gather/scatter 操作,用 gridsample 等價(jià)替換,提高模型速度。

            # 地平線參考算法Config
            view_transformer=dict(
                type="SingleBevFormerViewTransformer",
                ...
                max_camoverlap_num=2, # 對(duì)應(yīng)根據(jù)bev_mask進(jìn)行稀疏映射,提高運(yùn)行效率,對(duì)應(yīng)改動(dòng)2.e
                virtual_bev_h=int(0.4 * bev_h_),
                virtual_bev_w=bev_w_,
                ...
            )

            4.1.4 Head

            公版 MapTR 使用分層 query 機(jī)制,定義一組 instance queries 和由所有 instance 共享的 point queries,每個(gè)地圖元素對(duì)應(yīng)一組分層 query(一個(gè) instance query 和共享的 point queries 廣播相加得到),在 decoder layer 中分別使用 self-attention 和 cross-attention 來更新分層 query。

            MapTROE 的改進(jìn)則是為每個(gè)地圖元素分配一個(gè) instance query(無直接 point query),每個(gè) query 用于編碼語義信息和地理位置信息,decoder 階段和公版 MapTR 一樣,分別進(jìn)行 multi-head self-attention 和 deformable cross-attention,最后每個(gè) instance query 通過 MLP 網(wǎng)絡(luò)生成類別信息和元素內(nèi)的點(diǎn)集坐標(biāo),相比公版預(yù)測(cè)分層 query,改進(jìn)后直接預(yù)測(cè) instance query 帶來的計(jì)算量更少,極大地提高了模型在端側(cè)的運(yùn)行性能。同時(shí)借鑒 StreamMapNet,使用多點(diǎn)注意力方法來適應(yīng)高度不規(guī)則的地圖元素,擴(kuò)大感知范圍。代碼見/usr/local/lib/python3.10/dist-packages/hat/models/task_modules/maptr/instance_decoder.py: class MapInstanceDetectorHead(nn.Module)

            4.1.5 多點(diǎn)注意力

            image.png 傳統(tǒng)的可變形注意力為每個(gè) query 分配一個(gè)參考點(diǎn),多點(diǎn)注意力則使用前一層預(yù)測(cè)的地圖元素的多個(gè)點(diǎn)作為當(dāng)前層 query 的參考點(diǎn),具體計(jì)算方式是在點(diǎn)維度上擴(kuò)展了一層求和,將一個(gè)點(diǎn)變成多個(gè)點(diǎn),分別計(jì)算 deformable attention。回歸的時(shí)候并非預(yù)測(cè) offsets,而是直接預(yù)測(cè)地圖元素點(diǎn)的坐標(biāo)位置。

            4.1.6Attention

            模型中用到的 attention 操作均使用地平線提供的算子,相比 PyTorch 提供的公版算子,地平線 attention 算子在保持算子邏輯等價(jià)的同時(shí)在效率上進(jìn)行了優(yōu)化

            from hat.models.task_modules.bevformer.attention import (
                HorizonMSDeformableAttention,
                HorizonMSDeformableAttention3D,
                HorizonSpatialCrossAttention,
                ...
            )

            4.2 精度優(yōu)化

            4.2.1 浮點(diǎn)精度

            MapTROE 模型引入 SD Map 前融合,與圖像轉(zhuǎn)換后的 bev feature 進(jìn)行融合,以提高在線地圖的生成質(zhì)量。模塊結(jié)構(gòu)如下圖所示:

            image.png

            4.2.1.1 SD Map 特征提取

            SD Map 從 OpenStreetMap(OSM)中獲取,通過由 GPS 提供的車輛位姿,查詢車輛當(dāng)前位姿附近的 SD Map,然后將 SD Map 轉(zhuǎn)換到自車坐標(biāo)系下,與 NuScenes 中的數(shù)據(jù)標(biāo)注坐標(biāo)系保持一致。SD Map 會(huì)從車道中心骨架線 Polyline 的形式轉(zhuǎn)化為柵格結(jié)構(gòu),大小和 BEV 特征相同,經(jīng)過 CNN 變成特征圖,對(duì)應(yīng) SD Map 的先驗(yàn)信息。

            4.2.1.2 SD Map 特征融合

            柵格化后的 SD Map 和實(shí)際場(chǎng)景可能會(huì)出現(xiàn)錯(cuò)位、不對(duì)齊的情況,這種錯(cuò)位導(dǎo)致直接 Concatenate BEV 特征和 SD Map 特征的效果并不好,為了解決這個(gè)問題,引入了特征融合模塊,通過網(wǎng)絡(luò)學(xué)習(xí)來決定最適合的對(duì)齊方式,可以有效地利用 SD Map 先驗(yàn)提升 BEV 特征的效果。關(guān)于特征融合模塊,分別實(shí)驗(yàn)了交叉注意力與 CNN 網(wǎng)絡(luò),通過精度與性能的平衡,最后選擇了 CNN 網(wǎng)絡(luò)模塊。

            4.3 量化精度

              # Config文件
              cali_qconfig_setter = (default_calibration_qconfig_setter,)
              qat_qconfig_setter = (default_qat_fixed_act_qconfig_setter,)

              2.浮點(diǎn)階段采用更大的 weight decay 訓(xùn)練,使浮點(diǎn)數(shù)據(jù)分布范圍更小,浮點(diǎn)模型參數(shù)更有利于量化

              # Config文件
              float_trainer = dict(
                  ...
                  optimizer=dict(
                      ...
                      weight_decay=0.1, # 相比maptrv2_resnet50_bevformer_nuscenes增大了10倍
                  ),
                  ...
              )

              3.QAT 訓(xùn)練采用固定較小的 learning rate 來 fine-tune,這里固定也即取消 LrUpdater Callback 的使用,配置如下:

              # Config文件
              qat_lr = 1e-9

              4.取消了公版模型 MapTRHead 中對(duì)于量化不友好的 inverse_sigmoid 操作;此外 MapTROE 對(duì) Head 的優(yōu)化無需再引入 reg_branches 輸出和 reference 相加后再 sigmoid 的操作:

              # 公版模型
              class MapTRHead(DETRHead):
                  ...
                  def forward(...):
                      ...
                      for lvl in range(hs.shape[0]):
                          if lvl == 0:
                              # import pdb;pdb.set_trace()
                              reference = init_reference
                          else:
                              reference = inter_references[lvl - 1]
                          reference = inverse_sigmoid(reference)
                          ...
                          tmp = self.reg_branches[lvl](...)
                          tmp[..., 0:2] += reference[..., 0:2]
                          tmp = tmp.sigmoid() # cx,cy,w,h
                          
              # 地平線參考算法
              class MapInstanceDetectorHead(nn.Module):
                  ...
                  def get_outputs(...):
                      ...
                      for lvl in range(len(outputs_classes)):
                          tmp = reference_out[lvl].float()
              
                          outputs_coord, outputs_pts_coord = self.transform_box(tmp)
                          outputs_class = outputs_classes[lvl].float()
              
                          outputs_classes_one2one.append(
                              outputs_class[:, 0 : self.num_vec_one2one]
                          )
                          outputs_coords_one2one.append(
                              outputs_coord[:, 0 : self.num_vec_one2one]
                          )
                          outputs_pts_coords_one2one.append(
                              outputs_pts_coord[:, 0 : self.num_vec_one2one]
                          )
              
                          outputs_classes_one2many.append(
                              outputs_class[:, self.num_vec_one2one :]
                          )
                          outputs_coords_one2many.append(
                              outputs_coord[:, self.num_vec_one2one :]
                          )
                          outputs_pts_coords_one2many.append(
                              outputs_pts_coord[:, self.num_vec_one2one :]
                          )
                  ...        
                  def forward(...):
                      outputs = self.bev_decoder(...)
                      if self.is_deploy:
                          return outputs
                      ...
                      outputs = self.get_outputs(...)
                      ...
                      return self._post_process(data, outputs)

              5.Attention 結(jié)構(gòu)優(yōu)化,通過數(shù)值融合方法,將部分?jǐn)?shù)值運(yùn)算提前進(jìn)行融合,減少整體的量化操作,提高模型的量化友好度

              4.4 其他優(yōu)化

              4.4.1 設(shè)計(jì)優(yōu)化

                五、總結(jié)與建議

                5.1 部署建議

                  5.2 總結(jié)

                  本文通過對(duì) MapTR 進(jìn)行地平線量化部署的優(yōu)化,使得模型在征程 6 計(jì)算平臺(tái)上用較低的量化精度損失,最優(yōu)獲得征程 6M 單核 93.77 FPS 的部署性能。同時(shí),MapTR 系列的部署經(jīng)驗(yàn)可以推廣到其他相似結(jié)構(gòu)或相似使用場(chǎng)景模型的部署中。

                  對(duì)于地平線 MapTR 參考算法模型,結(jié)合 Sparse Bev 等的優(yōu)化方向仍在探索和實(shí)踐中,Stay Tuned!

                  六、附錄


                    *博客內(nèi)容為網(wǎng)友個(gè)人發(fā)布,僅代表博主個(gè)人觀點(diǎn),如有侵權(quán)請(qǐng)聯(lián)系工作人員刪除。



                    相關(guān)推薦

                    技術(shù)專區(qū)

                    關(guān)閉