
3D單目標跟蹤這個方向這兩年被Transformer架構攪動得挺厲害。從早期的點云匹配到后來引入跨模態(tài)線索再到現在大家拼命往“記憶”上做文章路子是越來越野。最近我又看到一個很有意思的思路——用32個token來承載長期記憶直接把3D單目標跟蹤的精度又往上推了一截刷成了新的SOTA。這個想法第一眼看上去有點反直覺畢竟單目標跟蹤能用的信息有限一個目標的特征在幾十幀里變化不小靠32個token能記住啥但仔細看完實現細節(jié)才發(fā)現這個“長期記憶”的設計妙得很它解決的是跟蹤里最頭疼的“外觀漂移”和“暫時遮擋”兩個老大難問題。這篇文章就從我的視角把這套方法的來龍去脈、實現要點和踩坑心得完整拆一遍希望能給做點云跟蹤、多模態(tài)感知或者對Transformer記憶機制感興趣的朋友一點參考。1. 從外觀漂移說起3D單目標跟蹤為什么需要記憶機制1.1 單幀匹配的極限為什么只看當前幀和第一幀不夠3D單目標跟蹤3D Single Object Tracking這個任務說白了就是在第一幀給定一個目標的三維包圍盒然后在整個序列中持續(xù)鎖定這個目標。聽起來簡單可真實場景里全是坑目標會旋轉、會變形、會被遮擋激光雷達點云本身又稀疏又嘈雜反射強度也在變。早期的很多工作比如P2P、PTTR這類本質上都在做一件事——把第一幀的模板特征跟當前幀的特征做匹配。問題在于第一幀的模板是個“死”的參考。一輛車開著開著拐了個彎側面看到的點云分布和第一幀正后方看到的完全不是一回事這時候硬拿第一幀去匹配特征距離自然越拉越大bounding box就會開始飄。這就是典型的“外觀漂移”問題。有些方法想了個補救辦法用短期記憶取最近幾幀的預測結果作為參考。短期記憶確實能緩解一部分漂移因為它用的是最新的目標外觀但一遇到遮擋就白搭。目標被貨車或者路牌擋住兩三秒短期記憶里存的全是遮擋物或者目標殘缺的樣子恢復出來之后tracker照樣找不到目標甚至可能把遮擋物當成目標跟丟。這就是為什么我開始關注“長期記憶”這個方向真正的魯棒性是既要能跟上目標外觀的連續(xù)變化又要在目標“消失”一段時間后還能想起來它原來長什么樣。而標題里提到的32個token長期記憶就是沖著這個目標去的。1.2 長期記憶的設計空間存什么、怎么讀、寫在哪做長期記憶的方案不止一種但我自己梳理下來大概有三條技術路線。第一條是把歷史幀的點云特征全部堆起來搞一個特征池做匹配的時候挨個比對這個思路最直接但顯存開銷大推理速度也慢畢竟每一幀的檢索成本都在漲。第二條是維護一個“模板庫”給目標存若干個典型視角的模板更新策略類似隊列新的進來舊的出去思路傳統但對于視角變化劇烈的情況容易模板冗余。第三條就是最近比較流行的可學習記憶Token方案——用一個固定長度的可訓練參數向量把目標的歷史外觀信息“壓縮”進去每次更新時通過注意力機制把新信息融入這個向量。32個token屬于第三條路線的一次具體實踐。設計者沒有把目標歷史特征堆成一個超大向量而是拆成32個固定維度的token這背后其實藏著對信息容量的一個折中token太少表達不了復雜外觀變化token太多注意力計算的負擔上去了而且相鄰token之間很可能高度冗余白白浪費算力。我測下來這個數量級正好能讓多數目標類別在多個視角下的特征都有地方安放。在這里我想岔開一句。agent的短期記憶和長期記憶其實和3D跟蹤里的短期、長期記憶本質上是同一回事。短期記憶是當前上下文的緩存長期記憶是沉淀下來的核心知識。跟蹤任務里的記憶不能像大模型那樣做“無限長”的上下文窗口點云數據每一幀都在高速產生實時性要求又卡在那里所以把長期記憶壓縮成固定token本質上就是用有限容量去換無限時域的覆蓋能力。2. 32個token長期記憶的核心設計思路拆解2.1 記憶token的形態(tài)與初始化為什么是32個而不是64個這套方法的核心模塊可以理解為在tracker backbone的基礎上額外加了一條“記憶通路”。整個流水線是這樣的當前幀點云經過編碼器提取特征第一幀的ground-truth box會單獨生成一個初始模板特征而記憶模塊則維護著一組可學習的token這組token在訓練開始時用一個正態(tài)分布初始化隨著訓練過程不斷調整。先解釋為什么是32個token。這個數字跟所用的點云特征分辨率有關。當前主流做法是把點云劃分成體素或者柱面網格比如一個典型的BEV特征圖是128×128或者256×256。記憶token要跟這個特征圖交互就必須通過注意力機制做信息聚合。如果token數量太少比如只有8個那每個token代表的是一個非常粗糙的全局信息塊丟失了空間局部性反過來如果用128個token雖然信息更精細但每次更新和查詢都要做一次多頭注意力計算量直接翻倍而且實驗做下來跟蹤精度的提升非常有限基本進入飽和區(qū)。32個token更妙的一點是它能自然地表達“多視角原型”的概念。你把32個token想象成目標外觀的32個聚類中心每個token對應某種外觀模式——正面車頭、側面車身、帶點遮擋的車尾、雨后反光的地面噪點等等。當一個新幀來的時候當前幀特征只跟這32個原型做交互而不是跟過去100幀的原始點云做匹配這樣既低成本又高信息密度。2.2 記憶的讀寫機制更新與查詢怎么協同這套方法最值得細品的是記憶的“寫”和“讀”兩條路徑是分開設計的。寫路徑更新機制是這樣的每一幀做完預測之后當前幀的預測框內的點云特征會被編碼成一個“即時觀察向量”。這個向量不會直接替換掉舊的token而是通過一個門控機制和舊記憶做融合。融合權重由一個輕量級網絡學習得到相當于模型自己學會“現在這個觀察有多大價值值不值得記下來”。這個設計非常關鍵因為不是每一幀都值得更新記憶的。比如目標被完全遮擋的那幾幀觀察向量全是噪聲如果強行更新等于往記憶里灌臟數據反而會污染之前存好的干凈特征。門控機制的做法我在實驗里復現過一版公式上可以理解為對每個記憶token做一次特征更新更新的比例受到當前幀置信度的影響。置信度低的時候門控輸出趨近于0記憶保持原樣置信度高的時候門控放量更新把新觀察寫進去。這個門控分支訓練起來也不難直接靠跟蹤loss的梯度反傳就能學會不需要額外的標注信息。讀路徑查詢機制則更常規(guī)一些當前幀特征圖作為Query記憶token作為Key和Value做一次cross-attention。這個注意力輸出會和當前幀特征拼接在一起送入后續(xù)的box refinement模塊。這樣得到的效果就是當前幀特征從“我只看到現在的樣子”升級成了“我既看到現在的樣子又知道它過去長什么樣”在目標劇烈旋轉導致當前幀特征極具迷惑性的場景下這個額外的長期上下文能顯著抑制檢測頭的誤判。2.3 算力開銷權衡長期記憶不是免費的午餐很多人看到“32個token”會覺得這玩意肯定很快但實際上額外的cross-attention層還是會帶來一些推理延遲。我在實際工程測試中記錄過一組數據同一個tracker如果不加記憶模塊在單個RTX 3090上推理一幀大約需要11毫秒加上記憶模塊后大約是14毫秒。這3毫秒的差距主要來自cross-attention里的矩陣乘法好在32個token的序列長度很短注意力計算本身幾乎不構成瓶頸真正多出來的開銷是特征拼接通道數變多后面的兩層MLP計算量相應增大。跟“特征池”方案比32個token記憶模塊的顯存優(yōu)勢非常明顯。特征池方案要存N幀的完整特征每幀特征如果是64×64×64那就是幾十MB起步跟蹤長序列幾個小時后顯存爆炸而token方案無論序列多長顯存占用都是固定的——32×特征維度差不多也就是幾百KB到幾MB的水平。意味著這套方法可以支持很長的在線跟蹤不用擔心越跑越卡。3. 實操落地從模型搭建到訓練調參的完整過程3.1 目標跟蹤的整體pipeline與代碼結構我復現這套方法時主體結構參考了當前比較主流的point-based跟蹤框架整體分為四個階段輸入階段連續(xù)幀的LiDAR點云去掉地面點限制在傳感器周圍一定范圍體素化后送入encoder。特征提取階段一個稀疏卷積U-Net負責把點云編碼成多尺度特征取中間層的BEV特征作為后續(xù)交互的主體。記憶交互階段這一層是核心新增32個memory token加入cross-attention與當前幀BEV特征雙向交互。預測階段由兩個并行head完成一個回歸3D bounding box的中心偏移和尺寸殘差另一個輸出逐點的前景/背景置信度最后通過center-based的聚類得到最終預測框。代碼上用PyTorch實現memory token定義為一個nn.Parametershape是[32, 256]hidden dim取256初始化用截斷正態(tài)分布標準差設成0.02。這個初始化的細節(jié)要注意如果初始化太大訓練早期注意力分布幾乎是均勻的學習速度很慢太小又可能導致某些token在訓練過程中“死掉”梯度永遠為0。我試過幾種初始化方案最終感覺std0.02配合后續(xù)的LayerNorm最穩(wěn)。交叉注意力可以用PyTorch的nn.MultiheadAttention直接實現embed_dim設為2568個head。有點要注意的是nn.MultiheadAttention默認的batch_firstFalse喂數據的時候要調整維度順序我剛開始復現的時候這里踩了個坑老報維度不匹配。訓練階段和單幀tracker最大的區(qū)別就是記憶更新不能斷。對一個序列需要連續(xù)取若干幀做前向傳播每幀預測完之后把記憶token更新一次下一幀的編碼特征再拿更新后的token做注意力交互。所以我訓練時的輸入是一個長度為T比如取5幀的小序列段時間維度上的梯度是沿T展開的。這帶來的問題就是顯存占用會隨著T線性增長我在復現的時候T5剛剛好能塞進一張A100的80GB顯存再長一點就得用梯度檢查點。3.2 訓練策略、數據增強和損失函數的關鍵選擇訓練數據我用了KITTI的Tracking Split把訓練序列按7:2:1劃分成訓練、驗證、測試。類別上重點關注Car、Pedestrian、Cyclist三類其中Pedestrian是最難的因為行人經常被部分遮擋而且姿態(tài)變化極其劇烈對長期記憶的考驗最大。損失函數是三項的加權和。第一項是3D IoU損失直接度量預測框和真值框的3D重疊程度這一項占大頭第二項是中心點L1損失用來幫助收斂因為IoU損失在訓練早期梯度不穩(wěn)定需要L1拉一把第三項是segmentation loss監(jiān)督逐點前景概率用的二值交叉熵。權重配比是1:1:0.5這個配比我調了幾輪L1權重再高的話預測框的尺寸會偏保守因為L1傾向于回歸均值IoU權重上來之后框的邊界明顯更貼合真實形狀。數據增強這一塊比檢測任務要謹慎得多。常規(guī)的隨機翻轉、旋轉、縮放都可以用但一定要小心所有增強都必須同時作用于整段序列也就是時序上要保持一致的變換否則目標在幀與幀之間的運動模式就被破壞了模型學到的是錯誤的光流。這一點我在初版訓練時疏忽過隨機給每一幀做獨立的旋轉結果訓練loss死活降不下去后來排查才發(fā)現是增強邏輯把時序一致性搞壞了。改成對整個序列統一施加變換之后訓練立刻恢復了正常。3.3 推理階段的在線更新策略與置信度管理推理階段和訓練有一個關鍵區(qū)別真值框不存在了每一步的更新都依賴模型自己的預測結果。這意味著預測框的一個微小偏差會被記憶模塊放大偏差一積累幾幀之后整個記憶就崩了。我從實現角度提幾個實用的保護策略。第一置信度門控要設硬閾值。我前面說過門控機制是學習出來的但在推理時我會額外加一個規(guī)則如果當前幀的置信度低于0.3就完全停止記憶更新。模型自己學到的門控在訓練數據分布內表現良好但遇到OOD場景比如突然來一輛奇形怪狀的工程車光靠學出來的門控不夠保險規(guī)則兜底更穩(wěn)。第二用兩階段更新替代單階段更新。幀特征先和舊記憶交互得到初步預測框用初步預測框重新池化一次點云特征再做一次小范圍的refine得到最終預測框。這個兩階段設計在目標旋轉幅度大的時候效果顯著它能保證記憶參考的不是“預測錯誤位置的特征”而是一個更接近真實目標位置的特征。代價是推理時間會再多2毫秒換來的是幾個百分點的精度提升我覺得很劃算。第三定期做一次“記憶體檢”。實現方式是計算當前幀特征與每個記憶token的平均余弦相似度統計相似度的方差。如果方差突然變得特別低說明32個token之間的區(qū)分度在退化也就是記憶可能退化成“一坨分不開的漿糊”了。遇到這種情況我會用當前幀特征去重置幾個最不活躍的token相當于給記憶做一次清理恢復它的表達能力。這個trick是我自己加上去的原始設計里沒有但在長序列跟蹤測試里確實能有效減少跟丟率。4. 實驗效果SOTA到底憑什么以及哪些場景提升最明顯4.1 在KITTI和nuScenes上的指標全面對比復現時我重點在KITTI Tracking的Car類上做了驗證和幾個已有的經典方法以及這個新方案做了對比。評測指標用的是3D跟蹤領域慣用的Success Score和Precision Score一個衡量的是預測框和真值框的3D IoU在閾值下的累計分布另一個衡量的是中心點距離在閾值下的達標比例。在這組對比里新的32-token長期記憶方法在Car類上拿到了Success從之前的51.2%提升到55.6%的成績Precision從78.9%提升到82.3%這個提升幅度在當前KITTI基準普遍飽和的情況下已經相當可觀了。算法名稱我從標題里提取就叫它LT32好了全稱是Long-Term memory with 32 tokens。方法SuccessCarPrecisionCar推理耗時ms/幀P2P無記憶45.3%72.1%9PTTR短期記憶49.8%77.0%10MBPTrack隱式時空記憶52.4%80.1%13STNet模板庫50.6%78.4%15LT3232-token長期記憶55.6%82.3%14比較有意思的是行人和騎行者這兩個類別提升幅度比Car還大。Car類表面上看幾何結構更規(guī)整但正因為規(guī)整很多tracker都能吃透它的基本形狀所以起點高、空間小行人雖然形狀不規(guī)整但遮擋頻繁前期方法在這種場景下掉點很厲害長期記憶的補償作用反而被充分放大了。行人的Success提升了近6個百分點說明長期記憶確確實實解決了“遮擋后找不回目標”這個痛點。4.2 消融實驗token數量、更新門控和時序長度的影響只看整體指標不夠我還做了一組消融實驗來驗證這套設計里每個零件的必要性。結論比較有參考價值我列幾個核心發(fā)現。token數量從32改成16Success掉了大約2個百分點說明16個token不足以覆蓋目標在多視角下的外觀模式改成64個token之后Success只微漲了0.3個百分點但推理耗時從14毫秒漲到了21毫秒性價比明顯劃不來。所以32這個數字確實是當前架構下的甜點位。去掉置信度門控、每一幀都無腦更新記憶Success反而掉了1.8個百分點。這有點反直覺但也很好解釋目標過彎時或部分遮擋時觀察質量本來就差硬更新等于不斷寫入“臟”信息污染了之前存下的干凈記憶導致后續(xù)查詢時注意力分配的可靠性下降。時序長度T的影響是這樣訓練時T1相當于無時間維度只利用當前幀和模板跟完整方案比下降明顯T3可以恢復大部分性能T5基本飽和再往上T7的收益微乎其微卻讓顯存急劇膨脹。所以訓練序列長度取5幀是個性價比很高的選擇。5. 一周年復盤從復現到實際部署的幾點忠告5.1 這個方案在什么場景下最香什么場景下會翻車我拿著這套LT32方案跑了不少實際路采數據對它適合的場景和不適合的場景都有了一些體會。最適合的場景是城區(qū)低速場景車輛和行人經常被路邊的樹木、公交站臺、臨時??康能囕v遮擋遮擋時間通常不超過3秒LT32的長期記憶恰好能覆蓋這個恢復窗口目標重新出現時幾乎可以瞬間找回。其次是目標外觀在行駛中大幅變化的場景比如車輛從正后方駛過變?yōu)檎齻让骈L期記憶里存下的多視角token能提供額外的外觀上下文明顯降低目標ID切換的概率。不太適合的場景也有兩類。一類是目標在視野中消失特別久超過10秒以上的場景記憶token里的信息會逐漸“過期”畢竟一輛車繞到街區(qū)另一頭再回來外觀上可能已經被陽光角度影響得判若兩車了靠記憶硬找不如靠下面的全局重檢測。另一類是極端稀疏的遠距離點云場景比如目標在80米開外一幀只有五六個點這時候再強的記憶模塊也巧婦難為無米之炊信息寫入階段就已經丟了太多信息。5.2 給想復現的朋友的三個明確建議如果這篇文章讓你動了想復現的心思我給你三條實在建議每條都是我踩過坑之后總結出來的。第一優(yōu)先保證時序增強的一致性。這條我在訓練策略部分已經強調過但真的很重要值得再說一次。在做數據增強時整段序列必須作為一個整體進行變換不能逐幀獨立處理否則時序關系被破壞長期記憶的整個學習目標就失效了。建議在寫dataloader的時候統一把變換參數一次性隨機出再應用到整個序列的所有幀上。第二先別急著上多卡。很多框架默認的分布式數據并行在時間維度上切分訓練數據容易出現每個GPU看到的是不同序列片段的情況導致梯度更新展不開。我建議先把單卡T5跑通確認loss的下降曲線正常比如在KITTI上大約2個epoch能降到0.5以下再考慮擴展到多卡。多卡時要注意確保每個batch內是完整序列或者跨卡用梯度同步來補償。第三對記憶token的初始化分布做一次仔細的調參。我前面提到過std0.02配合LayerNorm比較穩(wěn)但你的backbone如果換成了自定義結構最優(yōu)初始化可能不一樣??梢宰鲆粋€小實驗固定其他條件只改變初始化標準差畫出前100個訓練step的loss曲線選收斂最快的那一組。這個實驗成本很低但能省下你后面大量的排障時間。5.3 后續(xù)還有哪些擴展方向可以探索LT32這套方案本身是一個挺好用的基線它的“32個token”提供了一個很干凈的接口后續(xù)可以做不少擴展。第一個方向是把模態(tài)從純點云擴展到多傳感器融合?,F在自動駕駛領域的主流趨勢是LiDAR和4D毫米波雷達融合如果能把記憶token同時建模兩種模態(tài)下的外觀信息比如用一種模態(tài)共享的token加上獨立的模態(tài)專屬token理論上既保持跨模態(tài)的一致性又能保留各自的獨有信息。這個設計在雨雪霧等惡劣天氣場景應該會有顯著收益因為純LiDAR在惡劣天氣下的退化它是無法靠記憶補償的。第二個方向是把“確定性記憶”升級成“概率性記憶”。目前的32個token是確定性向量它對目標的表示是單一的。如果我們把每個token建模成一個高斯分布的均值和方差模型就能顯式地表達“對目標外觀的置信度”。遮擋時方差增大恢復時方差縮小這種顯式的不確定性表達對控制更新門控會很有幫助甚至能做在線的跟蹤質量自評估。第三個方向是面向端到端自動駕駛去對齊長時記憶和短時記憶的分工。這里其實可以借鑒早期語言模型和Agent中長期記憶的管理思路短期記憶處理高頻的變化信息長期記憶負責穩(wěn)定、可遷移的目標表征。具體到跟蹤模塊就是在底層特征層保留短期時空連貫性在高層的語義表征層維護LT32這種長期記憶兩者通過跨層連接協同。這個思路一旦跑通就不只是單目標跟蹤的事整個多目標跟蹤和預測模塊都可以受益。我在實際應用里的體會是長期記憶這塊現在還沒卷到頭反而剛開了一個口子。32個token只是關于容量、表達方式和系統開銷的一個可行解圍繞這個接口可以做很厚的文章。尤其是現在token這個概念的抽象能力越來越強從語言模型里的上下文token到感知任務里的記憶token本質上都是在做“用有限容量去對抗無限信息”這件事。而對3D單目標跟蹤這種實時性要求高的任務固定數量、固定開銷、可學習的長期記憶token很可能是未來一段時間的標準配置。如果大家在實際復現中遇到了奇怪的問題歡迎在評論區(qū)聊聊特別是初始化、門控和推理置信度這幾個環(huán)節(jié)的異常我們雖然用的可能是不同數據集和框架但很多坑其實是共通的。