:提升機器人學習泛化性的關(guān)鍵)
做機器人學習這塊的朋友應該都有一種共同的體感視覺語言模型VLM越來越強但要把它真正“接”到機械臂上總覺得隔著一層東西。最近我花了一晚上認真讀了這篇標題很長的論文《LLARVA: Vision-Action Instruction Tuning Enhances Robot Learning》雖然名字繞口但核心命題非常直接把視覺觀測和動作輸出放到同一個“指令微調(diào)”框架里到底能不能提升機器人學習的泛化性讀完之后我的結(jié)論是這個思路的工程價值被低估了。這篇博文就是一篇論文拆解筆記我會先講清楚它解決的問題是什么、方法骨架怎么搭、實驗上通常關(guān)注哪些維度再聊聊如果我想在自己的數(shù)據(jù)集上復現(xiàn)這套視覺-動作指令微調(diào)管線應該從哪下手、有哪些坑。適合兩類人看一是剛?cè)霗C器人學習、想搞懂VLAVision-Language-Action這條路線的同學二是已經(jīng)在跑模仿學習基線但困惑“為什么視覺特征和動作頭總是不太匹配”的工程師。1. 這篇論文到底在解決什么問題1.1 一個容易被忽略的錯位視覺特征和動作輸出沒有對齊早期的機器人模仿學習管線通常是兩條腿視覺模塊負責從圖像里抽取特征動作模塊負責把這些特征映射成關(guān)節(jié)速度或末端位姿。常見的做法是拿一個預訓練的視覺模型做backbone后面再接一個MLP或者Transformer動作頭。聽起來順理成章但實際操作中你會發(fā)現(xiàn)一個尷尬的問題視覺模型在ImageNet或者Web數(shù)據(jù)集上預訓練時根本沒有接觸過“這張圖接下來對應什么動作”這個信息。它學習到的是物體類別、場景語義而不是“我現(xiàn)在應該把手往左移5厘米”。這就像教一個新手開車給他看了大量道路照片告訴他這是紅燈、這是行人、這是車道線但從來沒有把“看到紅燈”和“踩剎車”這兩件事綁定訓練。等真上車的時候他能認出路況卻不知道手腳該怎么動。LLARVA這篇論文的出發(fā)點就是把“看到什么”和“接下來動一下”直接打包成指令樣本讓模型在訓練階段就開始建立視覺特征與動作輸出之間的強關(guān)聯(lián)。這種做法術(shù)語叫Vision-Action Instruction Tuning本質(zhì)上是對齊視覺表征和動作表征的語義空間。1.2 為什么不是從頭訓練而是“指令微調(diào)”有人可能會問既然視覺和動作對不齊那干脆用一個端到端的大模型從零開始學任務不就行了理論上可以但實際上有幾個很現(xiàn)實的問題。第一是數(shù)據(jù)量。機器人示教數(shù)據(jù)的采集成本極高一條有效軌跡往往需要人工遙控機械臂、反復演示、清洗時間戳不對齊的壞樣本。哪怕是在仿真環(huán)境里批量生成也很難短時間湊夠從零訓練一個大模型所需的千萬級樣本量。第二是算力。從頭訓練一個多模態(tài)模型對大多數(shù)人來說遙不可及。第三是災難性遺忘。即便你費盡力氣從零訓了一個模型它的語言理解能力和通用視覺先驗也會因為訓練目標太聚焦而退化后續(xù)換一個任務又得重來。所以“指令微調(diào)”是性價比最高的路線先利用VLM已有的視覺語言基礎(chǔ)把動作知識當作一種新任務注入進去而且注入的方式不是傳統(tǒng)的“給一段文字prompt讓它輸出動作”而是把動作本身變成一個可以和視覺token相互作用的語義角色。這也是我把這類工作歸為VLA路線里偏“指令派”的原因。為了更直觀我畫了張對比表來區(qū)分主流做法和LLARVA這類指令微調(diào)做法的差別對比維度傳統(tǒng)“視覺特征動作頭”通用VLM直接輸出動作Vision-Action指令微調(diào)視覺特征訓練目標識別/分類為主語言對齊為主與動作token對齊為主動作輸出方式連續(xù)向量單獨head文本化/離散化token潛在動作token解碼器還原模間關(guān)系視覺模塊和動作頭分開訓練模型“讀”文本prompt再輸出視覺動作聯(lián)合組成指令樣本數(shù)據(jù)效率需要大量配對數(shù)據(jù)需要強語義任務描述中等數(shù)據(jù)量即可有明顯提升2. 方法拆解Vision-Action指令微調(diào)是怎么搭起來的2.1 數(shù)據(jù)層面把“圖像序列動作序列”做成指令對理解這套方法最關(guān)鍵的突破點在于數(shù)據(jù)組織方式。傳統(tǒng)方法里一條演示數(shù)據(jù)是“若干幀圖像 每個時刻對應的動作向量”。LLARVA的做法是把動作序列先編碼成潛在動作token然后按照語言模型的指令模板把“觀測圖像”和“動作token”組合成類似多輪對話的樣本。舉個例子假設一個桌面抓取任務示教數(shù)據(jù)有50幀圖像每一幀對應一個六維末端位姿動作。做法不是讓模型每幀輸出一個連續(xù)向量而是把整個動作序列通過一個動作編碼器壓縮成若干個離散token然后排列成類似這樣的格式System: 你是一個機械臂控制模型請根據(jù)當前觀測輸出下一步動作。User: [觀測圖像幀1][觀測圖像幀2][觀測圖像幀3]...Assistant: [動作token_1][動作token_2][動作token_3]...這樣做的第一個好處是模型在推理時看到的輸入格式和訓練時完全一致沒有“換個場景就不知道該怎么組織輸入”的問題。第二個好處是動作被離散化之后VLM可以像生成文本一樣逐token生成動作不需要在模型的輸出層外接一個額外的回歸頭模型結(jié)構(gòu)變簡單了訓練也更穩(wěn)定。關(guān)于動作編碼器我理解的常見做法是用一個類VAE變分自編碼器結(jié)構(gòu)把原始連續(xù)動作壓縮到低維潛在空間。為什么這樣做因為直接讓語言模型輸出連續(xù)坐標本質(zhì)上是在做一個高維回歸任務這對LLM來說并不擅長。離散化之后模型可以把“預測下一個動作token”當作一個類別選擇問題穩(wěn)定性高很多。如果做個生活化類比連續(xù)動作就像是鋼琴的每個琴鍵都要單獨記憶而潛在動作token就像是五線譜上的音符只需要記住有限的音符組合就能還原出各種旋律。當然壓縮過程中會有信息損失所以動作編碼器的重建質(zhì)量直接決定了整條管線的上限。這一點我在后面實操部分會再展開。2.2 模型結(jié)構(gòu)視覺編碼器、動作編碼器與LLM主干如何協(xié)作這套方法的模型結(jié)構(gòu)從大的模塊上分無外乎幾塊視覺編碼器、動作編碼器、投影層、LLM主干以及動作解碼器。視覺編碼器負責把原始圖像轉(zhuǎn)換成視覺token序列。這里通常會用一個在大規(guī)模數(shù)據(jù)上預訓練過的視覺Transformer但論文的取向是在視覺-動作指令微調(diào)階段需要對視覺編碼器做一定程度的解凍甚至是低秩適配因為通用視覺特征并不天然適合動作預測。只凍結(jié)視覺編碼器的話后續(xù)LLM再怎么學也很難把視覺里面跟動作強相關(guān)的細節(jié)比如物體邊緣的深度線索提出來。投影層的作用是把視覺token映射到LLM的embedding空間。這里有一個容易被忽視的細節(jié)投影層參數(shù)量不大但它決定了視覺信息以怎樣的“語言形式”進入LLM。如果投影層訓練不充分視覺token在LLM看來就是一堆亂碼。所以論文里普遍的做法是在正式指令微調(diào)之前先做一個階段性的跨模態(tài)預訓練讓投影層和視覺編碼器適應動作token的表征方式。LLM主干承擔的是跨模態(tài)推理職責。它不直接輸出動作而是把“視覺上下文歷史狀態(tài)”融合成隱狀態(tài)再用這個隱狀態(tài)去預測動作token的分布。訓練時的loss通常包括兩部分一部分是語言/推理目標的交叉熵另一部分是對動作token預測的交叉熵。但要注意動作token預測的權(quán)重不宜過大否則模型會把所有容量都用在動作映射上語言理解能力會退化。在推理階段模型接收最近N幀觀測圖像作為上下文自回歸地生成一串潛在動作token然后通過動作解碼器把它們還原成真實世界的動作序列。這里的上下文窗口設計也很有講究窗口太短模型看不到運動趨勢窗口太長則容易把無關(guān)的歷史信息帶進來而且推理延遲會顯著上升。2.3 一套最小訓練流程的偽代碼為了把上面的抽象描述變成更可操作的東西我寫一段簡化的偽代碼模擬從數(shù)據(jù)準備到訓練再到推理的完整流程。這段代碼不針對某個具體框架只用來表示關(guān)鍵步驟之間的依賴關(guān)系方便大家對照自己的項目理解。# 假設已有 # - demo_data: List[Dict]包含image_frames (T, H, W, 3) 和 actions (T, A) # - action_encoder: VAE模型含 encode() 和 decode() 方法 # - visual_encoder: 預訓練視覺Transformer # - projector: MLP投影層把視覺token映射為llm embedding # - llm: 預訓練語言模型 # - action_decoder: 與action_encoder配套 def prepare_instruction_samples(demo_data): samples [] for demo in demo_data: images demo[image_frames] actions demo[actions] # (T, A) latent_tokens action_encoder.encode(actions) # (T, L) for t in range(3, T): ctx_images images[t-3:t] # 取歷史N幀 target_tokens latent_tokens[t] sample { images: ctx_images, input_ids: tokenize(根據(jù)觀測輸出動作), labels: target_tokens, } samples.append(sample) return samples def train_one_step(batch): img_feats [visual_encoder(img) for img in batch[images]] img_feats projector(torch.stack(img_feats)) # (B, N, D) txt_feats llm.embed(batch[input_ids]) fused llm.forward(inputs_embedstxt_feats img_feats) logits llm.lm_head(fused.hidden_states) loss cross_entropy(logits, batch[labels]) return loss def inference(obs_images, action_decoder): ctx projector(visual_encoder(obs_images)) pred_tokens llm.generate(inputs_embedsctx, max_new_tokens8) real_action action_decoder.decode(pred_tokens) return real_action這里我把目標token設計成單獨的時間片實際論文里可能會采用更精細的因果掩碼和窗口關(guān)系但核心思想是一致的模型看到的上下文是“視覺幀動作token的歷史”預測目標是“下一個動作token”。訓練對象不再是一個孤立的動作回歸任務而是被嵌在指令模板里的多模態(tài)生成任務。3. 實驗上最值得關(guān)注的三個維度3.1 零樣本遷移與少樣本拿捏這類論文最看重的一個指標是模型在訓練時沒見過的環(huán)境里表現(xiàn)如何。比如只在仿真桌面場景上做視覺-動作指令微調(diào)然后直接拿到真實機械臂平臺上測試抓取成功率。這里的“零樣本”不是指模型憑空學會抓取而是指它能把訓練中抽象出來的“看到什么就做什么”映射規(guī)律遷移到新背景、新物體、新相機視角上。從標題語義和摘要描述來看LLARVA強調(diào)性能提升的關(guān)鍵是“指令微調(diào)”本身。也就是說同樣的骨干網(wǎng)絡如果只是做視覺特征提取動作頭回歸跟在指令模板里把視覺和動作token統(tǒng)一建模相比后者的遷移成功率會有明顯領(lǐng)先。原因在于指令微調(diào)強制模型把視覺表征和動作語義綁定在一個上下文里模型學到的不是孤立特征而是“視覺-動作配對”的條件分布。少樣本場景也值得關(guān)注。現(xiàn)實項目里不可能為每一個新物體都采集幾百條演示所以論文實驗如果展示了“在新任務上只給8~16條演示就能快速適應”那說明它的表征結(jié)構(gòu)更適合被新任務擴展。這個特性我認為來源于它把動作離散化、語義化之后模型可以利用語言模型強大的模式記憶能力而不是從零擬合一個動作流形。3.2 動作token化的粒度與重建誤差讀這類論文不能只看最終成功率還要看動作編碼器的信息瓶頸設置在什么位置。動作編碼過程像一個壓縮過程壓縮率越高模型預測越容易但丟掉的動作細節(jié)也越多。比如一個小小的夾爪閉合動作可能只占潛在空間里很細微的一個維度如果壓縮后這個維度被合并到其他動作里重建出來的動作就是“意思對了但差了那么一點”。公開研究里這種潛在動作表示通常會做一個重建誤差表對比不同碼本大小、不同潛在維度下的Mean Squared Error。我最關(guān)心的是在高頻動作比如快速插拔、抖動、轉(zhuǎn)向上重建誤差是不是顯著大于低速穩(wěn)定動作。如果誤差分布不均衡模型可能會系統(tǒng)性地學丟那些“關(guān)鍵時刻的小動作”導致任務失敗。讀實驗部分時我建議重點關(guān)注這個誤差表而不是只盯著平均成功率。3.3 泛化到“看不見的組合”的能力機器人學習領(lǐng)域有個常見陷阱模型在訓練環(huán)境里跑得飛起但換一個光照條件、換一個同款但不同顏色的物體性能就斷崖式下跌。這背后的原因是模型學到了背景特征和物體外表的捷徑而不是真正理解“夾爪接近物體表面時應該張開到什么程度”這種物理關(guān)系。視覺-動作指令微調(diào)的作用就是把這些物理關(guān)系更直接地暴露在訓練目標中。因為模型必須在視覺token和動作token之間建立顯式依賴它很難繞過視覺信息直接記憶動作。如果論文的實驗里設計了“訓練時只出現(xiàn)紅色方塊測試時換成綠色方塊”“訓練時機械臂在左臂位測試時在右臂位”這類組合那確實能說明指令微調(diào)帶來的泛化收益是結(jié)構(gòu)性的而不是數(shù)據(jù)集本身的紅利。4. 如果我要復現(xiàn)這個思路我會怎么做4.1 從最短路徑開始先做一個單任務demo很多人拿到這類論文第一反應是“我要完整復現(xiàn)它的模型結(jié)構(gòu)”。我的建議正好相反先不要碰復雜的模型架構(gòu)而是把你自己的模仿學習數(shù)據(jù)集重新打包成“視覺-動作指令對”的格式然后在一個很小的模型上做一次指令微調(diào)實驗。具體分三步第一步數(shù)據(jù)清洗。把演示數(shù)據(jù)中時間戳對齊、剔除停滯和抖動片段。這個工作在傳統(tǒng)模仿學習里也是必須的但在指令微調(diào)范式下格外重要。因為指令微調(diào)會把動作序列離散成token如果某一段動作明顯抖動token化之后會變成一堆互斥的離散選擇模型無所適從。第二步訓練一個最小的動作Token編碼器。用你任務里最常見的幾類動作片段比如平移、旋轉(zhuǎn)、抓取、放置訓練一個小的VAE。不用一開始就追求高精度重建只要重建后的動作能讓機械臂在仿真里執(zhí)行成功率達到60%左右就可以先拿去做指令微調(diào)實驗。第三步跑一個消融對比。同一份數(shù)據(jù)、同一個基礎(chǔ)模型A組用傳統(tǒng)“圖像特征動作回歸頭”B組用視覺-動作指令微調(diào)。你會發(fā)現(xiàn)B組的訓練收斂速度可能略慢一些因為在初期視覺和動作token之間的對齊關(guān)系還沒建立好但只要過了某個門檻它在新場景上的表現(xiàn)會穩(wěn)定超出一截。這個過程本質(zhì)上是為了驗證“這個方法到底適不適合你的數(shù)據(jù)分布”而不是直接復現(xiàn)一個論文里的SOTA數(shù)字。我實驗下來最值得復現(xiàn)的其實是這種“用指令模板把動作語義化”的思路而不是具體的網(wǎng)絡維度。4.2 數(shù)據(jù)組織與超參選擇的經(jīng)驗參考在數(shù)據(jù)組織上有一個細節(jié)容易踩坑圖像幀和動作token之間的對應關(guān)系要非常嚴格。動作token的粒度決定了多少個動作step對應一個token。如果你把連續(xù)5個step編碼成一個token那推理時模型只能每5個step輸出一個動作中間的動作要靠解碼器線性插值補上。這個問題在低速精細操作時很致命。我建議的動作token粒度是先把一段軌跡按時間均勻切片讓每個token覆蓋3到5幀前提是你的控制頻率足夠高比如30Hz以上。如果控制頻率太低就不要過度壓縮寧可讓token序列長一點也要保證重建精度。超參方面有幾個我實測后比較靠譜的參考值超參數(shù)建議范圍個人心得上下文圖像幀數(shù)4~8幀太少看不到運動趨勢太多主要增加推理延遲視覺編碼器狀態(tài)部分解凍或LoRA適配完全凍結(jié)容易導致視覺特征與動作語義脫節(jié)動作token潛在維度16~64維維度太低動作細節(jié)丟失明顯指令微調(diào)輪數(shù)2~4個epoch再多容易過擬合到數(shù)據(jù)集的軌跡模式訓練batch size視計算資源而定小batch下先保證梯度穩(wěn)定此外有一點容易被忽略推理時的動作平滑。即使模型預測的潛在動作token在語義空間是連續(xù)的解碼到真實世界坐標系后依然可能出現(xiàn)相鄰動作之間的小幅跳變。通常需要加一個低通濾波或者指數(shù)移動平均代價是會讓動作延遲一點點但能顯著提升實機部署的穩(wěn)定性。4.3 計算資源不夠時的替代方案如果手頭沒有A100這類大顯存顯卡也不是不能跑??梢韵劝岩曈X編碼器凍結(jié)用LoRA微調(diào)投影層并且把語言模型換成最小號的開源模型甚至用中等規(guī)模的多模態(tài)模型。這時候模型的絕對性能不會太高但你依然可以驗證一個核心問題視覺-動作指令微調(diào)這個數(shù)據(jù)組織方式是否比傳統(tǒng)的獨立動作頭更好。我自己的經(jīng)驗是用大約50~100條示教數(shù)據(jù)在單張消費級顯卡上花半小時訓練一個最小demo就足以觀察到明顯的表征優(yōu)勢。因為指令微調(diào)成功與否很大程度上取決于數(shù)據(jù)的組織邏輯而不是模型的絕對規(guī)模。5. 實操中常見的坑與排查實錄5.1 兩個模態(tài)“雞同鴨講”loss下降緩慢這個坑我遇到過很多次?,F(xiàn)象很典型loss降得非常慢或者降到某個值就下不去了視覺token和動作token在模型看來好像各說各話完全無法融合。排查思路很簡單第一步先查投影層輸出和文本embedding的分布是否在一個量級。如果視覺特征經(jīng)過投影后像素值波動很大而文本embedding的分布很平滑那LLM根本沒法把兩者等權(quán)重地融合。另一個比較容易忽視的原因是視覺編碼器輸出token數(shù)量太多。一張384×384的圖通常輸出幾百個視覺token如果全部塞給LLM注意力基本被視覺token淹沒動作token很難得到有效關(guān)注。通常需要做一個token合并或者采樣把視覺token數(shù)量壓縮到幾十個以內(nèi)讓動作token在序列里占有合理的比例。5.2 動作重建誤差很大預測再準也是白搭我見過很多項目花了大量時間調(diào)指令微調(diào)模型最后發(fā)現(xiàn)瓶頸根本不在預測部分而是動作編碼器重建動作時就已經(jīng)變形了。最典型的例子是模型預測的潛在動作token明明很準但解碼后的動作速度曲線有明顯的“臺階感”不是平滑的軌跡。排查方法很簡單從訓練集里隨機抽一批動作數(shù)據(jù)過一遍動作編碼器解碼然后把重建動作和原始動作畫在同一張圖上逐個維度檢查誤差。如果發(fā)現(xiàn)某個維度比如手腕旋轉(zhuǎn)角度、夾爪開合度的誤差顯著大于其他維度不要急著調(diào)LLM先優(yōu)化VAE那邊的loss權(quán)重或者給那個維度單獨增加重建損失權(quán)重。5.3 模型在訓練環(huán)境很猛換一個背景就崩這個問題可以追溯到視覺編碼器過擬合到背景特征。解決方法有兩個方向。第一個方向是在數(shù)據(jù)組織階段做視覺擾動比如隨機改變亮度、隨機裁剪、隨機遮擋讓模型必須依靠物體本身的幾何特征而不是背景色塊來做動作決策。第二個方向是在指令微調(diào)階段刻意在部分樣本里把物體和背景做組合重組比如仿真渲染的時候隨機換桌面紋理強迫模型把視覺特征和動作邏輯解耦。如果條件不允許重新生成數(shù)據(jù)可以用一種“注意力引導”的排查法把模型在某個樣本上的注意力圖拿出來看它在生成動作token時注意力到底是集中在物體輪廓附近還是集中在背景某個角落。如果是后者那基本可以確定模型學了一個背景捷徑。5.4 推理延遲過高實機控制跟不上機器人控制對延遲極其敏感。如果模型自回歸生成動作token太慢控制頻率跟不上整個策略就沒法部署。一個常見的優(yōu)化點是用“粗預測精修正”兩段式先讓模型以較快的速度生成一批低精度的動作草圖token再在一個輕量解碼器里做高精度的局部修正。另一個優(yōu)化方向是緩存視覺特征。因為在一段連續(xù)的任務里相鄰幾個控制周期之間的圖像變化通常不大不需要每幀都重新過一遍視覺編碼器。每10幀或者20幀更新一次視覺特征中間的時間步直接復用緩存配合動作token的自回歸預測可以把端到端延遲壓到可接受范圍內(nèi)。6. 這個思路還能往外擴展到哪里視覺-動作指令微調(diào)這個思路不只是個“機械臂抓取任務專用”的小技巧。我個人的看法是它給了一類通用問題的解法當一個高能力的多模態(tài)模型需要接入一個低維度的連續(xù)控制量時與其在模型外面加一堆任務頭不如先把控制量token化然后再用指令模板把它和觀測輸入一起“講給”模型聽。順著這個思路我可以想到幾個很有潛力的擴展方向。第一個是操作多個機器人的協(xié)同任務把每個機械臂的動作都編碼成獨立的token流模型可以交錯預測兩臺機械臂的動作。第二個是移動機器人底盤的導航?jīng)Q策把線速度和角速度壓成潛在動作token讓模型基于第一視角圖像預測下一步移動。第三個是智能體的工具使用模擬把鼠標移動和點擊還原成token流讓模型通過閱讀屏幕截圖來控制光標這其實和很多自動化腳本項目的底層邏輯是相通的。我自己目前在一套桌面整理演示數(shù)據(jù)上嘗試了類似的做法最明顯的變化不是單次準確率提升而是模型對“同樣場景不同起始位置”的適應性變好了。以前動作頭回歸出來的軌跡像是背答案現(xiàn)在更像是在“看情況做決策”。雖然離真正的通用機器人策略還很遠但至少這條路踩上去是實的。讀這類論文我的建議是帶著“它改變了什么接口關(guān)系”這個問題去讀而不是只盯著準確率數(shù)字。LLARVA這類視覺-動作指令微調(diào)的核心其實就是把“視覺輸入到動作輸出”這件事從一個回歸問題平移到了語言模型的token預測框架里。想通這一點剩下的網(wǎng)絡結(jié)構(gòu)和訓練技巧都能按自己的資源條件做取舍。