八. 實戰:CUDA-BEVFusion部署分析-分析BEVFusion中各個ONNX

目錄

    • 前言
    • 0. 簡述
    • 1. camera.backbone.onnx(fp16)
    • 2. camera.backbone.onnx(int8)
    • 3. camera.vtransform.onnx(fp16)
    • 4. fuser.onnx(fp16)
    • 5. fuser.onnx(int8)
    • 6. lidar.backbone.xyz.onnx
    • 7. head.bbox.onnx(fp16)
    • 總結
    • 下載鏈接
    • 參考

前言

自動駕駛之心推出的《CUDA與TensorRT部署實戰課程》,鏈接。記錄下個人學習筆記,僅供自己參考

本次課程我們來學習下課程第八章——實戰:CUDA-BEVFusion部署分析,一起來分析 BEVFusion 中各個 ONNX

課程大綱可以看下面的思維導圖

在這里插入圖片描述

0. 簡述

本小節目標:分析 CUDA-BEVFusion 中各個 onnx 的輸入輸出,以及網絡架構

這節給大家講解第八章節第 7 小節,分析 BEVFusion 中的各個 onnx,這里我們拿 CUDA-BEVFusion 中導出好的 onnx 先看一看,一共有 5 個 onnx,對比看看 FP16 和 INT8 的 onnx 有什么區別,分析每個 onnx 的輸入輸出是什么以及它們之間是怎么連接的

1. camera.backbone.onnx(fp16)

我們先看 camera.backbone 部分,backbone 提供了兩個,一個是 resnet 另一個是 swin transformer,我們這里以 resnet50 為例來講解,我們主要看下輸入輸出就好了,主干部分是 resnet50 的結構,大家已經非常熟悉了

camera backbone 部分 fp16 的情況下需要看的東西并不是很多,需要注意的是 input 有兩個,一個是 camera,一個是 LiDAR 到 camera 的 1ch depth map,output 也是有兩個,一個是 camera feature(32ch),一個是 depth feature(118ch)

camera.backbone 的第一個輸入是環視相機圖像,以 nuscenes 數據集為例,相機個數為 6,高度為 256,寬度為 704,所以第一個輸入的維度就是 1x6x3x256x704,如下圖所示:

在這里插入圖片描述

input1:camera
image(RGB)6 camera,3*256*704

通過變換矩陣將點云投影到相機上,這就是 camera.backbone 的第二個輸入即 depth map,如下圖所示:

在這里插入圖片描述

input2:camera depth image
(1ch)6 camera,1*256*704

對于輸出也有兩個,大家可以回顧下上節課講解的 BEVPool,它的輸入就對應于這里的輸出,如下圖所示。一個是 camera_feature,維度是 6x32x88x80,分別代表著 NxHxWxC,另一個是 camera_depth_weights 即 depth 的概率圖,維度是 6x118x32x88 分別代表著 NxDxHxW,這里的 D 表示對每一個特征像素 D 個 depth 的概率分布,圖中 D 是 118,說明我們為圖片上每個像素點估計 118 個深度值,之后對 118 個深度值做一個 softmax 看哪個點出現的可能性最大,這就是 camear backbone 的輸出,它和普通的圖像特征提取網絡如 resnet 有所不同,多了一個深度概率分支

在這里插入圖片描述

output:
camera feature:80chdepth feature:118ch

2. camera.backbone.onnx(int8)

接著我們再來看下 camera.backbone 的 INT8 的 onnx,camera backbone 部分如果是 int8 的話,我們可以看到在每一個 conv 前面都添加了 Q/DQ 節點,如下圖所示,每一個 Q/DQ 節點都有對應的 scale 和 zero_shift,我們可以知道這一部分是經過 QAT 學習的,其余的沒有變化(有關 QAT 學習如何添加這些 Q/DQ 節點有時間的話后面會介紹)

在這里插入圖片描述

input1:camera
image(RGB)6 camera,3*256*704

可以看到每一個 Conv 前面都加了 Q/DQ 節點,每個 Conv 節點都有兩個輸入,一個是 activation value,一個是 weight,兩個輸入都需要加 Q/DQ,其實 Q/DQ 添加的過程并不是很復雜,通過 NVIDIA 提供的 pytorch_quantization 量化工具即可完成,這個我們在 TensorRT量化實戰課YOLOv7量化:YOLOv7-PTQ量化(一) 中有提到過,大家感興趣的可以看下

在這里插入圖片描述

我們之前有講過 TensorRT 里面對輸入對 activation value 是 per-tensor 的量化粒度,每一個 tensor 只有一個 scale,這個大家可以從上圖中看出來,y_scale 和 y_zero_point 都只有一個值,也就是 6x3x256x704 這整個 tensor 共用這一個 scale 和 zero_point

在這里插入圖片描述

對于 weight 而言是 per-channel 的量化粒度,也就是說每個通道共享一個 scale 和 zero_point,這個我們從上圖中也能看出來,可以看到 weight 的 Q 節點的 scale 有 64 個,對應的是 Conv 節點的 64 個通道

在這里插入圖片描述

同時 zero_point 也是 64 個,只不過全為 0,如上圖所示,那為什么都是 0 呢?這個我們在第五章節的時候也講過,NVIDIA 將量化分為對稱量化和非對稱量化,NVIDIA 官方說如果要做非對稱量化在部署階段計算量比較大,也不好融合,所以 NVIDIA 在做量化時統一采用的是對稱量化,因此 zero_point 就是 0 了

在這里插入圖片描述

output:
camera feature:80chdepth feature:118ch

我們可以看其實并不是所有的節點都做了 INT8 量化,輸出部分像 softmax、Transpose 就沒有做 INT8 了,如上圖所示

以上就是 camera.backbone 的 INT8 的 onnx 的整個結構了,值得注意的是在 resnet50int8/build 文件夾下有各種層的信息以及輸出的日志文件,我們一起來看下,

在這里插入圖片描述

camera.backbone.json

camera.backbone.json 文件中我們可以看到每個 layer 都有關于 INT8 量化的一些描述,我們重點來看下 camera.backbone.log,來看下層融合之后的精度

在這里插入圖片描述

camera.backbone.log

我們可以看到 log 里面每個層每個節點的融合信息以及它們的精度的變化,大家可以打開簡單看下

3. camera.vtransform.onnx(fp16)

我們看完 camera.backbone 之后我們來看 camera.vtransform,camera vtransform 的部分只有 fp16 的 onnx,需要看的東西并不是很多,需要注意的是,這個 vtransform 是針對 backbone 中輸出進行的,三個 conv 將 360x360 大小的 input feature 進行特征學習 downsample 到 180x180

值得注意的是這里跨越了 BEVPool 這個部分,也就是說 camera.backbone 的兩個輸出經過 BEVPool 投影到 BEV 空間之后的輸出才是作為 camera.vtransform 的輸入

在這里插入圖片描述

output:
80*360*360->80*180*180

4. fuser.onnx(fp16)

我們繼續看,下一個是 fuser,fuser.onnx 的 fp16 模型比較簡單,相比于 BEVFormer 來說 BEVFusion 的融合部分整體上只有 convolution 而沒有像 BEVFormer 的 attention(spatial,temporal)。并且整體上相比于 backbone 而言,模型的深度也很淺,并且只有一個 BN,所有的 kernel 都是 3x3

在這里插入圖片描述

input:
投影在 BEV 空間的 feature mapcamera 是 80ch,lidar 是 256ch估計是因為點云是 sparse 的,所以需要更大的 channel size

輸入一個是 camera 一個是 lidar,camera 這邊是 BEVPool 處理過投影到 BEV 上的 camera feature,維度是 1x80x180x180,lidar 這邊是經過 SCN 網絡提取后的 lidar feature,維度是 1x256x180x180

在這里插入圖片描述

output:
通過多個 conv 將 camera feature 和 lidar feature 融合最終得到 180x180 Grid size 的 BEV 特征,ch 大小是 512

輸出是融合后的 BEV 特征,維度是 1x512x180x180

5. fuser.onnx(int8)

fuser.onnx 的 int8 模型會稍微復雜一點,跟 camera.backbone(int8) 一樣,每一個 conv 前都有 Q/DQ 節點,所有這里的 fuser 也是經過 QAT 進行學習到的,這里的權重已經能夠在某種程度上適應 fp32->int8 的量化誤差了

在這里插入圖片描述

input:
投影在 BEV 空間的 feature mapcamera 是 80ch,lidar 是 256ch估計是因為點云是 sparse 的,所以需要更大的 channel size

在這里插入圖片描述

output:
通過多個 conv 將 camera feature 和 lidar feature 融合最終得到 180x180 Grid size 的 BEV 特征,ch 大小是 512

6. lidar.backbone.xyz.onnx

我們再來看下 lidar.backbone.xyz.onnx 也就是點云特征提取網絡的 onnx,這個其實就是 CenterPoint 的 SCN 架構直接導出的 ONNX

值得注意的是 lidar.backbone.xyz 的 onnx 比較特殊,因為這里使用的是自定義 onnx 節點,有兩個自定義節點:

  • SparseConvolution
  • ScatterDense

所以在推理的時候會根據自定義 onnx 節點里的信息和輸入 tensor 的信息進行推理

在這里插入圖片描述

input:點云 tensor

在這里插入圖片描述

output:
BEV-Grid:256*180*180

在這里插入圖片描述

輸入是經過處理后的點云 tensor 維度是 1x5,輸出是 lidar feature 維度是 1x256x180x180,這個會輸入到 fuser 模塊與 camera 部分做融合得到融合后的 BEV 特征

自定義 SparseConvolution 節點里面包含了許多信息,如上圖所示,這些信息將會在推理階段用到,包括 activation,kernel_size,padding,rulebook,stride 等等

7. head.bbox.onnx(fp16)

最后我們看 head,head.bbox 部分是 fp16 推理的,使用 fuser 后的 512x180x180 的 feature map 進行前向推理,這里的 forward 過程的 onnx 詳細部分沒有必要看,我們只需要知道輸出都有哪些:

  • height:[dim,1,200](3D 目標框的高度即 z 方向上的大小)
  • dim:[dim,3,200](3D 目標框的中心點即 center_x,center_y,center_z)
  • rot:[dim,2,200](rotation 即 sin 和 cos)
  • reg:[dim,2,200](3D 目標框的長寬即 x,y 方向上的大小)
  • vel:[dim,2,200](速度即 vx、vy,用來表示在哪個方向移動)
  • score:[dim,10,200](class confidence)

在這里插入圖片描述

input:
在 BEV 空間上生成的特征圖

在這里插入圖片描述

output:
輸出在 BEV 空間上的 3D BBox 的各種信息(高度、深度、坐標、得分等等)

在這里插入圖片描述

輸入是 1x512x180x180,也就是融合后的 BEV 特征,輸出有 6 個,相關含義上面已經提到過了

以上就是 BEVFusion 中的各個 onnx 的分析,我們知道了每個 onnx 的輸入輸出以及如何銜接之后,再去閱讀代碼會相對簡單一些

總結

這節課程我們主要學習了 BEVFusion 中的各個 onnx,分析了每個 onnx 的輸入輸出以及它們之間是怎么銜接的,主要包括 camera.backbone、camera.vtransform、fuser、lidar.backbone.xyz、head 五個 onnx,我們還分析了不同精度下的 onnx 差異,主要對比了 FP16 和 INT8 兩種精度,INT8 下的 onnx 都插入了 Q/DQ 節點來做量化工作。

OK,以上就是第 7 小節有關 BEVFusion 中各個 onnx 分析的全部內容了,下節我們來學習 CUDA-BEVFusion 推理框架設計模式,敬請期待😄

下載鏈接

  • 論文下載鏈接【提取碼:6463】
  • 數據集下載鏈接【提取碼:data】
  • 代碼和安裝包下載鏈接【提取碼:cuda】

參考

  • TensorRT量化實戰課YOLOv7量化:YOLOv7-PTQ量化(一)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/717121.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/717121.shtml
英文地址,請注明出處:http://en.pswp.cn/news/717121.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

每日一類:Qt中的萬能容器

在Qt框架中,QVariant類扮演著一個非常重要的角色。它是一個萬能容器類,可以存儲Qt中的任何基本類型數據,包括自定義類型。這種靈活性使得QVariant成為Qt編程中不可或缺的工具,特別是在需要處理不同類型數據或進行對象間通信時。 …

Unity UGUI之Scrollbar基本了解

Unity的Scrollbar組件是用于在UI中創建滾動條的組件之一。滾動條通常與其他可滾動的UI元素(如滾動視圖或列表)一起使用,以便用戶可以在內容超出可見區域時滾動內容。 以下是Scrollbar的基本信息和用法: 1、創建 在Unity的Hierarchy視圖中右…

柯西矩陣介紹

經典定義 柯西矩陣(Cauchy Matrix),是一種特殊類型的矩陣,它在數學中的多個領域,包括線性代數、數值分析和插值理論中都有重要應用。柯西矩陣以19世紀法國數學家奧古斯丁-路易柯西的名字命名。 柯西矩陣是一個方陣&am…

Krylov matrix

Krylov矩陣是一種在數值線性代數中使用的矩陣,尤其是在迭代解法中用于求解線性方程組、特征值問題和其他線性代數問題。它是由俄國數學家阿列克謝尼古拉耶維奇克雷洛夫(Alexei Nikolaevich Krylov)的名字命名的。 Krylov子空間由以下形式的矩…

jetson nano——編譯安裝opencv==4.4

目錄 1.下載源碼,我提供的鏈接如下:1.1文件上傳的路徑位置,注意ymck是我自己的用戶名(你們自己換成你們自己相對應的就行) 2.解壓文件3.安裝依賴4.增加swap交換內存4.1臨時增加交換內存swap4.2永久增加swap 5.安裝open…

2024-03-03 作業

作業要求: 1.使用fwrite、fread將一張隨意的bmp圖片,修改成德國的國旗 2.使用提供的getch函數,編寫一個專門用來輸入密碼的函數,要求輸入密碼的時候,顯示 * 號,輸入回車的時候,密碼輸入結束 作業…

學習Android的第十九天

目錄 Android ExpandableListView 分組列表 ExpandableListView 屬性 ExpandableListView 事件 ExpandableListView 的 Adapter 范例 參考文檔 Android ViewFlipper 翻轉視圖 ViewFlipper 屬性 ViewFlipper 方法 為 ViewFlipper 加入 View 例子:全屏幕可…

【MySQL】索引(重點)-- 詳解

一、索引 沒有索引,可能會有什么問題? 索引 :提高數據庫的性能,索引是物美價廉的東西了。不用加內存,不用改程序,不用調 sql ,只要執行正確的 create index ,查詢速度就可能提高成…

加密與安全_探索數字證書

文章目錄 Pre概述使用keytool生成證書使用Openssl生成證書 (推薦)證書的吊銷小結 Pre PKI - 借助Nginx 實現Https 服務端單向認證、服務端客戶端雙向認證 PKI - 04 證書授權頒發機構(CA) & 數字證書 PKI - 數字簽名與數字證…

java面試題(spring框架篇)(黑馬 )

樹形圖: 一、Spring框架種的單例bean是線程安全嗎? Service Scope("singleton") public class UserServiceImpl implements UserService{ } singleton:bean在每個Spring IOC容器中只有一個實例 protype:一個bean的定義可以有多個…

CPU iowait是什么意思

在linux系統,使用top命令時,可以看到cpu使用統計情況,有時我們會注意到iowait這一項非常高。我們直到,在cpu運行進程、線程時,遇到IO操作,因為IO讀寫通常比較慢,CPU通常可以阻塞線程&#xff0c…

【Web安全靶場】xss-labs-master 1-20

xss-labs-master 其他靶場見專欄 文章目錄 xss-labs-masterlevel-1level-2level-3level-4level-5level-6level-7level-8level-9level-10level-11level-12level-13level-14level-15level-16level-17level-18level-19level-20 level-1 第一關沒有進行任何限制,get請求…

pytorch_神經網絡構建6

文章目錄 強化學習概念實現qLearning基于這個思路,那么解決這個問題的代碼如下 強化學習概念 強化學習有一個非常直觀的表現,就是從出發點到目標之間存在著一個連續的狀態轉換,比如說從狀態一到狀態456,而每一個狀態都有多種的行為&#xff…

全國青少年軟件編程(Python)等級考試試卷(一級) 測試卷2021年12月

第 1 題 【 單選題 】 下面程序的運行結果是什么?( ) a10 b5 ca*b print(c) A :10 B :15 C :50 D :5 正確答案:C 試題解析: 第 2 題 【 單選題 】 與a>b and b>c等價的是?( ) A…

設計模式學習筆記 - 設計原則 - 1.單一職責原則

前言 前面我們提到過 SOLID 原則,實際上 SOLID 由 5 個設計原則組成,分別是:單一職責原則、開閉原則、里氏替換原則、接口隔離原則和依賴反轉原則。它們分別對應 SLOID 中的 S、O、L、I、D 這 5 個英文字母。 今天來學習下 SOLID 原則中的第…

Libevent的使用及reactor模型

Libevent 是一個用C語言編寫的、輕量級的開源高性能事件通知庫,主要有以下幾個亮點:事件驅動( event-driven),高性能;輕量級,專注于網絡,不如 ACE 那么臃腫龐大;源代碼相當精煉、易讀…

【Java】Java 中的方法引用寫法

概述 方法引用(MethodReference)是Lambda表達式的另一種格式,在某些場景下可以提高代碼的可讀性 使用條件 只可以替換單方法的Lambda表達式 什么意思呢 ? 例如下面這個Lambda表達式就不可以使用方法引用替換,因為…

100243. 將元素分配到兩個數組中 I

說在前面 🎈不知道大家對于算法的學習是一個怎樣的心態呢?為了面試還是因為興趣?不管是出于什么原因,算法學習需要持續保持。 題目描述 給你一個下標從 1 開始、包含 不同 整數的數組 nums ,數組長度為 n 。 你需要通…

C語言 快速排序——qsort函數的介紹

qsort函數 1. 函數介紹2. 函數使用2.1 整型排序2.2 字符排序2.3 字符串排序2.4 結構體排序 3. 用冒泡思想模擬qsort函數 我們以往使用冒泡排序和選擇排序等對數據進行排序時,有可能會遇到搞不清排序次數,運行時間過長等一些問題,并且這些排序…

aop監控spring cloud接口超時,并記錄到數據庫

引入pom <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0.0…