X-VLA 模型架构
1. 整体架构概览
X-VLA (Extended Vision-Language-Action) 是一个基于扩散的跨具身视觉-语言-动作模型,将 Florence2 视觉语言模型作为感知主干网络,配合软提示 Transformer (SoftPromptedTransformer) 动作头进行机器人动作预测。其核心设计思路为:Florence2 的 Vision Tower 和 BART 编码器提取多模态特征(移除 BART 解码器以降低计算量),再通过域感知线性层 (DomainAwareLinear) 实现多机器人具身支持,最终以扩散去噪方式生成动作序列。模型支持多视角图像输入、多种动作空间(ee6d / joint / auto 等),并通过可学习的软提示 token 实现域特定的知识注入。
graph TB
subgraph Input["输入"]
IMG["多视角相机图像<br/>(pixel_values)<br/>[B, num_views, C, H, W]"]
TXT["语言指令<br/>(input_ids)<br/>[B, seq_len]"]
STATE["本体感受状态<br/>(proprio)<br/>[B, state_dim]"]
DID["域 ID<br/>(domain_id)<br/>[B]"]
end
subgraph VLM["Florence2 视觉语言模型 (VLM)"]
VT["DaViT Vision Tower<br/>图像编码"]
PROJ["多模态投影层"]
BART_ENC["BART 编码器<br/>文本-图像融合"]
BART_DEC["BART 解码器<br/>❌ 已移除"]
end
subgraph ActionHead["SoftPromptedTransformer 动作头"]
TE["时间步编码器<br/>(正弦编码)"]
AE["DomainAwareLinear<br/>(动作编码器)"]
VLP["VLM 投影层"]
AUXP["辅助视觉投影层"]
SP["软提示 Hub<br/>(num_domains x 32 tokens)"]
BLOCKS["24层 TransformerBlock<br/>(Pre-LN, MHSA + MLP)"]
AD["DomainAwareLinear<br/>(动作解码器)"]
end
subgraph Output["输出"]
ACT["预测动作轨迹<br/>[B, chunk_size, action_dim]"]
end
IMG --> VT
VT --> PROJ --> BART_ENC
TXT --> BART_ENC
BART_ENC -->|"vlm_features<br/>[B, T_vlm, D]"| VLP
BART_ENC -->|"aux_visual_inputs<br/>[B, T_aux, D]"| AUXP
STATE --> AE
DID --> AE
DID --> SP
DID --> AD
TE --> AE
VLP -->|"投影特征"| BLOCKS
AUXP -->|"辅助视觉特征"| BLOCKS
AE -->|"动作 token"| BLOCKS
SP -->|"32个软提示 token"| BLOCKS
BLOCKS --> AD --> ACT
style Input fill:#e8f4fd,stroke:#2196F3
style VLM fill:#fff3e0,stroke:#FF9800
style ActionHead fill:#e8f5e9,stroke:#4CAF50
style Output fill:#fce4ec,stroke:#E91E63
2. 核心组件详解
2.1 Florence2 视觉语言模型 (Vision Tower + BART 编码器)
Florence2 作为 X-VLA 的感知主干网络,负责将多视角图像和语言指令编码为统一的多模态特征。X-VLA 仅使用编码器部分,在初始化时显式移除了 BART 的解码器 (lm.model.decoder) 和语言模型头 (lm.lm_head),以节省显存和计算量。
多视角处理流程: 第一个视角图像与文本 token 在 BART 编码器中融合,产生 vlm_features;其余视角图像作为辅助视觉输入 (aux_visual_inputs) 直接传递给 Transformer 动作头。
graph LR
subgraph ImageEnc["DaViT Vision Tower"]
PIX["pixel_values<br/>[B, num_views, C, H, W]"]
FLAT["展平 & 掩码过滤<br/>仅处理有效视角"]
DAVIT["DaViT 视觉编码器<br/>_encode_image()"]
RESHAPE["重塑为<br/>[B, num_views, tokens, D]"]
PIX --> FLAT --> DAVIT --> RESHAPE
end
subgraph TextEnc["BART 文本-图像融合"]
IDS["input_ids<br/>[B, seq_len]"] --> EMB["词元嵌入<br/>get_input_embeddings()"]
V0["第0视角特征<br/>[B, tokens, D]"]
EMB --> MERGE["_merge_input_ids_with_image_features()<br/>图像 token 插入文本序列"]
V0 --> MERGE
MERGE --> ENC["BART 编码器<br/>language_model.model.encoder"]
end
subgraph Outputs["输出"]
ENC -->|"vlm_features<br/>[B, T_vlm, D]"| OUT1["主视觉语言特征"]
AUX["辅助视角特征<br/>[B, (num_views-1)*tokens, D]"]
RESHAPE -->|"image_features[:, 1:]"| AUX
end
RESHAPE -->|"image_features[:, 0]"| V0
style ImageEnc fill:#e3f2fd,stroke:#2196F3
style TextEnc fill:#fff3e0,stroke:#FF9800
style Outputs fill:#e8f5e9,stroke:#4CAF50
关键设计:BART 解码器移除
graph LR
subgraph Full["Florence2 原始结构"]
FVT["Vision Tower ✅"]
FPROJ["投影层 ✅"]
FENC["BART 编码器 ✅"]
FDEC["BART 解码器 ❌ 已删除"]
FLM["LM Head ❌ 已删除"]
FVT --> FPROJ --> FENC --> FDEC --> FLM
end
subgraph Used["X-VLA 实际使用"]
UVT["Vision Tower<br/>DaViT"]
UPROJ["多模态投影层"]
UENC["BART 编码器<br/>输出多模态特征"]
UVT --> UPROJ --> UENC
end
UENC -->|"vlm_features"| XVLA["SoftPromptedTransformer"]
style Full fill:#ffebee,stroke:#f44336
style Used fill:#e8f5e9,stroke:#4CAF50
移除逻辑 (见 modeling_xvla.py:79-84):
python
if hasattr(self.vlm, "language_model"):
lm = self.vlm.language_model
if hasattr(lm, "model") and hasattr(lm.model, "decoder"):
del lm.model.decoder
if hasattr(lm, "lm_head"):
del lm.lm_head
冻结策略:
| 组件 |
默认状态 |
配置项 |
| Vision Tower |
可配置冻结 |
freeze_vision_encoder (默认 False) |
| BART 编码器 |
可配置冻结 |
freeze_language_encoder (默认 False) |
| BART 解码器 |
已删除 |
N/A |
| LM Head |
已删除 |
N/A |
SoftPromptedTransformer 是 X-VLA 的核心动作生成模块。它接收 VLM 特征、辅助视觉特征、含噪动作、本体感受状态和时间步信息,通过 24 层标准 Transformer 块进行处理,最终解码出预测动作。
核心特色: 每个域 (embodiment) 拥有独立的 32 个可学习软提示 token,通过 nn.Embedding(num_domains, len_soft_prompts * hidden_size) 存储,在前向传播时按 domain_id 索引并拼接到序列末尾。
graph TB
subgraph InputPrep["输入准备"]
direction LR
ACT_N["含噪动作<br/>[B, T, dim_action]"]
PROP["本体感受<br/>[B, dim_propio]"]
TIME["时间步 t<br/>[B]"]
TIME --> TE["正弦时间步编码<br/>timestep_embedding()"]
TE -->|"[B, dim_time]"| EXPAND_T["扩展至<br/>[B, T, dim_time]"]
PROP --> EXPAND_P["扩展至<br/>[B, T, dim_propio]"]
ACT_N --> CAT_IN["Concat<br/>[action, proprio, time]<br/>[B, T, dim_action+dim_propio+dim_time]"]
EXPAND_T --> CAT_IN
EXPAND_P --> CAT_IN
end
subgraph Encode["动作编码 (DomainAwareLinear)"]
CAT_IN --> AE["action_encoder<br/>DomainAwareLinear"]
DID1["domain_id"] --> AE
AE -->|"[B, T, hidden_size]"| ACT_TOK["动作 token"]
end
subgraph VisualProj["视觉投影"]
VLM_F["vlm_features<br/>[B, T_vlm, D]"] --> VP["vlm_proj<br/>(Linear 或 DomainAwareLinear)"]
AUX_F["aux_visual_inputs<br/>[B, T_aux, D]"] --> AP["aux_visual_proj<br/>(Linear 或 DomainAwareLinear)"]
end
subgraph SeqBuild["序列构建"]
ACT_TOK --> CONCAT["Concat 所有 token"]
VP --> CONCAT
AP --> CONCAT
CONCAT -->|"[B, T+T_vlm+T_aux, H]"| POS["+ 位置编码<br/>pos_emb[:, :seq_len]"]
POS --> SOFT["拼接软提示 token<br/>[B, 32, hidden_size]"]
DID2["domain_id"] --> SOFT
end
subgraph TransBlocks["24层 TransformerBlock"]
SOFT --> B0["Block 0: LN->MHSA->残差->LN->MLP->残差"]
B0 --> B1["Block 1"]
B1 --> DOTS["..."]
DOTS --> B23["Block 23"]
end
subgraph Decode["动作解码"]
B23 --> NORM["LayerNorm"]
NORM --> SLICE["取前 T 个 token<br/>x[:, :num_actions]"]
SLICE --> ADEC["action_decoder<br/>DomainAwareLinear"]
DID3["domain_id"] --> ADEC
ADEC -->|"[B, T, dim_action]"| OUT["预测动作"]
end
style InputPrep fill:#e3f2fd,stroke:#2196F3
style Encode fill:#f3e5f5,stroke:#9C27B0
style VisualProj fill:#fff3e0,stroke:#FF9800
style SeqBuild fill:#e0f7fa,stroke:#00BCD4
style TransBlocks fill:#e8f5e9,stroke:#4CAF50
style Decode fill:#fce4ec,stroke:#E91E63
序列拼接顺序
graph LR
subgraph Sequence["Transformer 输入序列"]
direction LR
S1["动作 token<br/>[T 个]"]
S2["VLM 特征 token<br/>[T_vlm 个]"]
S3["辅助视觉 token<br/>[T_aux 个]"]
S4["软提示 token<br/>[32 个]"]
S1 --> S2 --> S3 --> S4
end
subgraph Output["输出提取"]
ONLY["仅解码前 T 个 token<br/>(动作位置)"]
end
S1 -.->|"action_decoder"| ONLY
style Sequence fill:#e8f4fd,stroke:#2196F3
style Output fill:#fce4ec,stroke:#E91E63
设计要点: 软提示 token 拼接在序列末尾,但最终只解码序列开头的动作 token 位置。这使得软提示通过注意力机制间接影响动作预测,而非直接参与解码。
graph TB
IN["hidden_states<br/>[B, T, H]"] --> LN1["LayerNorm"]
LN1 --> MHSA["多头自注意力<br/>(16 heads, head_dim=64)<br/>支持 Flash Attention"]
MHSA --> ADD1["+ 残差连接"]
IN --> ADD1
ADD1 --> LN2["LayerNorm"]
LN2 --> MLP["MLP<br/>Linear(H, 4H) -> GELU -> Dropout(0.1)<br/>-> Linear(4H, H) -> Dropout(0.1)"]
MLP --> ADD2["+ 残差连接"]
ADD1 --> ADD2
ADD2 --> OUT["输出<br/>[B, T, H]"]
style IN fill:#e3f2fd,stroke:#2196F3
style OUT fill:#e8f5e9,stroke:#4CAF50
2.3 DomainAwareLinear (域感知线性层)
DomainAwareLinear 是 X-VLA 实现多具身支持的核心机制。每个域 (embodiment) 拥有独立的权重矩阵和偏置向量,通过 nn.Embedding 存储,在前向传播时按样本级别的 domain_id 索引选择对应的权重进行计算。
graph TB
subgraph WeightStore["权重库 (nn.Embedding)"]
W["fc: Embedding(num_domains, output_size * input_size)<br/>每个域一个完整权重矩阵"]
B["bias: Embedding(num_domains, output_size)<br/>每个域一个偏置向量"]
end
subgraph Forward["前向传播"]
X["输入 x<br/>[B, T, input_size]"]
DID["domain_id<br/>[B]"]
DID --> IDX["索引选择"]
W --> IDX
B --> IDX
IDX -->|"weight [B, I, O]"| BMM["批量矩阵乘法<br/>y = matmul(x, weight) + bias"]
IDX -->|"bias [B, O]"| BMM
X --> BMM
BMM --> OUT["输出<br/>[B, T, output_size]"]
end
subgraph Usage["在 X-VLA 中的使用位置"]
U1["action_encoder:<br/>DomainAwareLinear(action+propio+time, hidden_size)"]
U2["action_decoder:<br/>DomainAwareLinear(hidden_size, dim_action)"]
U3["soft_prompt_hub:<br/>Embedding(num_domains, 32*hidden_size)"]
U4["vlm_proj (可选):<br/>DomainAwareLinear(multi_modal_dim, hidden_size)"]
end
style WeightStore fill:#fff3e0,stroke:#FF9800
style Forward fill:#e8f5e9,stroke:#4CAF50
style Usage fill:#e3f2fd,stroke:#2196F3
与 GR00T 的 CategorySpecificLinear 对比: 两者设计思路一致——通过 Embedding 存储多组权重,按 embodiment ID 索引选择。X-VLA 的 DomainAwareLinear 支持 2D 和 3D 输入(自动 squeeze/unsqueeze),且使用 Xavier 均匀初始化权重、零初始化偏置。
2.4 动作空间管理器 (ActionSpace Registry)
X-VLA 通过注册表模式管理多种动作空间,每种动作空间定义了维度、损失计算、预处理和后处理逻辑。
graph TB
subgraph Registry["ACTION_REGISTRY (注册表)"]
direction TB
R1["'ee6d' -> EE6DActionSpace"]
R2["'joint' -> JointActionSpace"]
R3["'auto' -> AutoActionSpace"]
R4["'agibot_ee6d' -> AGIBOTEE6DActionSpace"]
R5["'franka_joint7' -> FrankaJoint7ActionSpace"]
R6["'so101_bimanual' -> BimanualSO101ActionSpace"]
end
subgraph Builder["build_action_space(name)"]
CALL["调用方"] --> LOOKUP["查找注册表"]
LOOKUP --> INST["实例化对应类"]
end
subgraph Interface["BaseActionSpace 接口"]
I1["dim_action: int<br/>动作维度"]
I2["gripper_idx: tuple<br/>夹爪通道索引"]
I3["compute_loss(pred, target)<br/>-> dict[str, Tensor]"]
I4["preprocess(proprio, action)<br/>-> (proprio, action)"]
I5["postprocess(action)<br/>-> action"]
end
Registry --> Builder
Builder --> Interface
style Registry fill:#f3e5f5,stroke:#9C27B0
style Builder fill:#e0f7fa,stroke:#00BCD4
style Interface fill:#e8f5e9,stroke:#4CAF50
3. 训练流水线
训练时,模型使用扩散过程(Flow Matching)对动作进行加噪和去噪预测。时间步 t 在 [0, 1) 范围内均匀采样(带批次内偏移以增强多样性),含噪动作通过线性插值生成。
graph TB
subgraph DataPrep["数据准备"]
direction LR
BATCH["训练 Batch"]
BATCH --> IMG_P["_prepare_images()<br/>多视角图像堆叠 + 填充"]
BATCH --> STATE_P["_prepare_state()<br/>本体感受状态填充"]
BATCH --> ACT_P["_prepare_action_targets()<br/>动作目标填充至 chunk_size"]
BATCH --> LANG["input_ids<br/>语言 token"]
BATCH --> DID_P["_get_domain_id()<br/>域 ID"]
end
subgraph VLMEnc["VLM 编码"]
IMG_P --> FWD_VLM["forward_vlm()"]
LANG --> FWD_VLM
FWD_VLM -->|"vlm_features"| ENC_OUT["编码输出"]
FWD_VLM -->|"aux_visual_inputs"| ENC_OUT
end
subgraph Diffusion["扩散加噪"]
direction TB
T_SAMPLE["时间步采样<br/>t = (rand(1) + arange(B)/B) % (1-1e-5)<br/>均匀分布, 批次内偏移"]
ACT_GT["真实动作<br/>[B, chunk_size, dim_action]"]
NOISE["高斯噪声<br/>randn_like(action)"]
T_SAMPLE --> INTERP["线性插值<br/>action_noisy = noise * t + action * (1-t)"]
ACT_GT --> INTERP
NOISE --> INTERP
INTERP --> PREPROC["action_space.preprocess()<br/>预处理 (如清零夹爪通道)"]
end
subgraph TransFwd["Transformer 前向"]
ENC_OUT --> TRANS["SoftPromptedTransformer"]
PREPROC -->|"action_noisy_m"| TRANS
STATE_P -->|"proprio_m"| TRANS
DID_P --> TRANS
T_SAMPLE -->|"t"| TRANS
TRANS -->|"pred_action<br/>[B, chunk_size, dim_action]"| PRED["预测动作"]
end
subgraph LossCalc["分通道损失计算 (ee6d 模式)"]
PRED --> LOSS_POS["Position MSE<br/>XYZ 通道 * 500"]
PRED --> LOSS_ROT["Rotation MSE<br/>6D旋转通道 * 10"]
PRED --> LOSS_GRIP["Gripper BCE<br/>夹爪通道 * 1"]
ACT_GT --> LOSS_POS
ACT_GT --> LOSS_ROT
ACT_GT --> LOSS_GRIP
LOSS_POS --> TOTAL["total_loss =<br/>position_loss + rotate6D_loss + gripper_loss"]
LOSS_ROT --> TOTAL
LOSS_GRIP --> TOTAL
end
style DataPrep fill:#e3f2fd,stroke:#2196F3
style VLMEnc fill:#fff3e0,stroke:#FF9800
style Diffusion fill:#f3e5f5,stroke:#9C27B0
style TransFwd fill:#e8f5e9,stroke:#4CAF50
style LossCalc fill:#fce4ec,stroke:#E91E63
扩散加噪公式
t ~ Uniform[0, 1) (带批次内偏移)
noise ~ N(0, I)
action_noisy = noise * t + action_gt * (1 - t)
模型预测的目标是直接预测去噪后的动作(而非预测噪声或速度),损失计算在原始动作空间中进行。
4. 推理流水线
推理时,模型从纯随机噪声出发,通过迭代去噪逐步恢复动作轨迹。默认使用 10 步去噪。
graph LR
subgraph Init["初始化"]
X1["纯随机噪声 x1<br/>~ N(0, I)<br/>[B, 32, dim_action]"]
A0["初始动作 = 0<br/>[B, 32, dim_action]"]
S["去噪步数 = 10"]
end
subgraph VLMOnce["VLM 编码 (仅一次)"]
IMG["图像"] --> VLM["forward_vlm()"]
TXT["文本"] --> VLM
VLM --> ENC["vlm_features<br/>aux_visual_inputs"]
end
subgraph Loop["迭代去噪循环 (10步)"]
direction TB
STEP10["步骤 10: t=1.0<br/>x_t = x1*1.0 + action*0.0 = x1<br/>-> Transformer -> action"]
STEP9["步骤 9: t=0.9<br/>x_t = x1*0.9 + action*0.1<br/>-> Transformer -> action"]
STEP8["步骤 8: t=0.8<br/>x_t = x1*0.8 + action*0.2<br/>-> Transformer -> action"]
DOTS["..."]
STEP1["步骤 1: t=0.1<br/>x_t = x1*0.1 + action*0.9<br/>-> Transformer -> action"]
STEP10 --> STEP9 --> STEP8 --> DOTS --> STEP1
end
subgraph Post["后处理"]
STEP1 --> PP["action_space.postprocess()<br/>(如 sigmoid 夹爪)"]
PP --> FINAL["最终动作轨迹<br/>[B, 32, action_dim]"]
end
Init --> STEP10
ENC --> Loop
style Init fill:#e3f2fd,stroke:#2196F3
style VLMOnce fill:#fff3e0,stroke:#FF9800
style Loop fill:#e8f5e9,stroke:#4CAF50
style Post fill:#fce4ec,stroke:#E91E63
单步去噪展开
graph LR
subgraph ImageEnc["DaViT Vision Tower"]
PIX["pixel_values<br/>[B, num_views, C, H, W]"]
FLAT["展平 & 掩码过滤<br/>仅处理有效视角"]
DAVIT["DaViT 视觉编码器<br/>_encode_image()"]
RESHAPE["重塑为<br/>[B, num_views, tokens, D]"]
PIX --> FLAT --> DAVIT --> RESHAPE
end
subgraph TextEnc["BART 文本-图像融合"]
IDS["input_ids<br/>[B, seq_len]"] --> EMB["词元嵌入<br/>get_input_embeddings()"]
V0["第0视角特征<br/>[B, tokens, D]"]
EMB --> MERGE["_merge_input_ids_with_image_features()<br/>图像 token 插入文本序列"]
V0 --> MERGE
MERGE --> ENC["BART 编码器<br/>language_model.model.encoder"]
end
subgraph Outputs["输出"]
ENC -->|"vlm_features<br/>[B, T_vlm, D]"| OUT1["主视觉语言特征"]
AUX["辅助视角特征<br/>[B, (num_views-1)*tokens, D]"]
RESHAPE -->|"image_features[:, 1:]"| AUX
end
RESHAPE -->|"image_features[:, 0]"| V0
style ImageEnc fill:#e3f2fd,stroke:#2196F3
style TextEnc fill:#fff3e0,stroke:#FF9800
style Outputs fill:#e8f5e9,stroke:#4CAF50
0
与 GR00T 的区别: GR00T 使用欧拉积分 (action += dt * v) 逐步更新动作;X-VLA 则在每一步直接用模型输出替换 action,下一步再以新的 action 与噪声插值。两者都属于 Flow Matching 框架,但积分方式不同。
动作选择策略 (Action Chunking)
graph LR
subgraph ImageEnc["DaViT Vision Tower"]
PIX["pixel_values<br/>[B, num_views, C, H, W]"]
FLAT["展平 & 掩码过滤<br/>仅处理有效视角"]
DAVIT["DaViT 视觉编码器<br/>_encode_image()"]
RESHAPE["重塑为<br/>[B, num_views, tokens, D]"]
PIX --> FLAT --> DAVIT --> RESHAPE
end
subgraph TextEnc["BART 文本-图像融合"]
IDS["input_ids<br/>[B, seq_len]"] --> EMB["词元嵌入<br/>get_input_embeddings()"]
V0["第0视角特征<br/>[B, tokens, D]"]
EMB --> MERGE["_merge_input_ids_with_image_features()<br/>图像 token 插入文本序列"]
V0 --> MERGE
MERGE --> ENC["BART 编码器<br/>language_model.model.encoder"]
end
subgraph Outputs["输出"]
ENC -->|"vlm_features<br/>[B, T_vlm, D]"| OUT1["主视觉语言特征"]
AUX["辅助视角特征<br/>[B, (num_views-1)*tokens, D]"]
RESHAPE -->|"image_features[:, 1:]"| AUX
end
RESHAPE -->|"image_features[:, 0]"| V0
style ImageEnc fill:#e3f2fd,stroke:#2196F3
style TextEnc fill:#fff3e0,stroke:#FF9800
style Outputs fill:#e8f5e9,stroke:#4CAF50
1
5. 动作空间详解
各模式对比
| 动作空间 |
维度 |
布局 |
夹爪索引 |
损失函数 |
适用场景 |
| ee6d |
20D |
[XYZ(3)+Rot6D(6)+Gripper(1)] x2 臂 |
(9, 19) |
Pos MSE500 + Rot MSE10 + Grip BCE*1 |
末端执行器双臂 |
| joint |
14D |
[Joints(6)+Gripper(1)] x2 臂 |
(6, 13) |
Joints MSE1 + Grip BCE0.1 |
关节空间双臂 |
| auto |
可配置 |
前 real_dim 维有效, 填充至 max_dim |
无 |
MSE*1 (仅前 real_dim 维) |
任意维度自适应 |
| agibot_ee6d |
20D |
同 ee6d |
(9, 19) |
Pos MSE500 + Rot MSE10 + Grip MSE*10 |
AGI-Bot (全 MSE) |
| franka_joint7 |
20D (实际7D) |
7关节 + 13维填充 |
无 |
MSE*1 (仅前7维) |
Franka Panda |
| so101_bimanual |
20D (实际12D) |
[5关节+Gripper] x2 + 8维填充 |
(5, 11) |
MSE1 + Grip MSE1 |
SO-101 双臂 |
ee6d 动作布局 (20D)
graph LR
subgraph ImageEnc["DaViT Vision Tower"]
PIX["pixel_values<br/>[B, num_views, C, H, W]"]
FLAT["展平 & 掩码过滤<br/>仅处理有效视角"]
DAVIT["DaViT 视觉编码器<br/>_encode_image()"]
RESHAPE["重塑为<br/>[B, num_views, tokens, D]"]
PIX --> FLAT --> DAVIT --> RESHAPE
end
subgraph TextEnc["BART 文本-图像融合"]
IDS["input_ids<br/>[B, seq_len]"] --> EMB["词元嵌入<br/>get_input_embeddings()"]
V0["第0视角特征<br/>[B, tokens, D]"]
EMB --> MERGE["_merge_input_ids_with_image_features()<br/>图像 token 插入文本序列"]
V0 --> MERGE
MERGE --> ENC["BART 编码器<br/>language_model.model.encoder"]
end
subgraph Outputs["输出"]
ENC -->|"vlm_features<br/>[B, T_vlm, D]"| OUT1["主视觉语言特征"]
AUX["辅助视角特征<br/>[B, (num_views-1)*tokens, D]"]
RESHAPE -->|"image_features[:, 1:]"| AUX
end
RESHAPE -->|"image_features[:, 0]"| V0
style ImageEnc fill:#e3f2fd,stroke:#2196F3
style TextEnc fill:#fff3e0,stroke:#FF9800
style Outputs fill:#e8f5e9,stroke:#4CAF50
2
预处理与后处理
graph LR
subgraph ImageEnc["DaViT Vision Tower"]
PIX["pixel_values<br/>[B, num_views, C, H, W]"]
FLAT["展平 & 掩码过滤<br/>仅处理有效视角"]
DAVIT["DaViT 视觉编码器<br/>_encode_image()"]
RESHAPE["重塑为<br/>[B, num_views, tokens, D]"]
PIX --> FLAT --> DAVIT --> RESHAPE
end
subgraph TextEnc["BART 文本-图像融合"]
IDS["input_ids<br/>[B, seq_len]"] --> EMB["词元嵌入<br/>get_input_embeddings()"]
V0["第0视角特征<br/>[B, tokens, D]"]
EMB --> MERGE["_merge_input_ids_with_image_features()<br/>图像 token 插入文本序列"]
V0 --> MERGE
MERGE --> ENC["BART 编码器<br/>language_model.model.encoder"]
end
subgraph Outputs["输出"]
ENC -->|"vlm_features<br/>[B, T_vlm, D]"| OUT1["主视觉语言特征"]
AUX["辅助视角特征<br/>[B, (num_views-1)*tokens, D]"]
RESHAPE -->|"image_features[:, 1:]"| AUX
end
RESHAPE -->|"image_features[:, 0]"| V0
style ImageEnc fill:#e3f2fd,stroke:#2196F3
style TextEnc fill:#fff3e0,stroke:#FF9800
style Outputs fill:#e8f5e9,stroke:#4CAF50
3
6. 关键超参数表
| 参数 |
默认值 |
说明 |
hidden_size |
1024 |
Transformer 隐藏层维度 |
depth |
24 |
Transformer 层数 |
num_heads |
16 |
注意力头数 (head_dim = 64) |
mlp_ratio |
4.0 |
MLP 隐藏层倍数 (MLP dim = 4096) |
chunk_size |
32 |
预测的未来动作步数 |
n_action_steps |
32 |
每次推理使用的动作步数 |
num_denoising_steps |
10 |
推理时去噪步数 |
num_domains |
30 |
最大支持的机器人域数量 |
len_soft_prompts |
32 |
每个域的可学习软提示 token 数 |
dim_time |
32 |
时间步嵌入维度 |
max_len_seq |
512 |
最大序列长度 (位置编码) |
max_state_dim |
32 |
最大本体感受状态维度 |
max_action_dim |
20 |
最大动作维度 (auto 模式填充目标) |
action_mode |
"ee6d" |
动作空间模式 |
dtype |
"float32" |
模型精度 ("bfloat16" / "float32") |
tokenizer_name |
"facebook/bart-large" |
语言分词器 |
tokenizer_max_length |
64 |
最大文本 token 长度 |
use_proprio |
True |
是否使用本体感受状态 |
use_hetero_proj |
False |
是否使用域感知视觉投影 |
optimizer_lr |
1e-4 |
基础学习率 |
optimizer_grad_clip_norm |
10.0 |
梯度裁剪范数 |
scheduler_warmup_steps |
1,000 |
学习率预热步数 |
scheduler_decay_steps |
30,000 |
余弦衰减总步数 |
Attention dropout |
0.1 |
注意力 Dropout 率 |
MLP dropout |
0.1 |
MLP Dropout 率 |
优化器配置
X-VLA 使用差分学习率策略:
| 参数组 |
学习率 |
说明 |
| VLM 参数 (vision + language) |
lr * 0.1 |
1/10 基础学习率, 稳定优化 |
| Transformer / 动作头 |
lr |
完整学习率 |
| 软提示 |
lr * soft_prompt_lr_scale |
可配置缩放, 支持独立 warmup |
7. 关键源文件表
| 组件 |
类名 |
文件路径 |
| 主模型 |
XVLAModel |
lerobot/policies/xvla/modeling_xvla.py:43 |
| LeRobot 策略封装 |
XVLAPolicy |
lerobot/policies/xvla/modeling_xvla.py:271 |
| 模型配置 |
XVLAConfig |
lerobot/policies/xvla/configuration_xvla.py:41 |
| 软提示 Transformer |
SoftPromptedTransformer |
lerobot/policies/xvla/soft_transformer.py:292 |
| Transformer 模块 |
TransformerBlock |
lerobot/policies/xvla/soft_transformer.py:258 |
| 多头自注意力 |
Attention |
lerobot/policies/xvla/soft_transformer.py:92 |
| 域感知线性层 |
DomainAwareLinear |
lerobot/policies/xvla/soft_transformer.py:215 |
| 时间步嵌入 |
timestep_embedding() |
lerobot/policies/xvla/soft_transformer.py:183 |
| MLP 模块 |
Mlp |
lerobot/policies/xvla/soft_transformer.py:47 |
| 动作空间注册表 |
ACTION_REGISTRY |
lerobot/policies/xvla/action_hub.py:27 |
| 动作空间基类 |
BaseActionSpace |
lerobot/policies/xvla/action_hub.py:55 |
| ee6d 动作空间 |
EE6DActionSpace |
lerobot/policies/xvla/action_hub.py:113 |
| joint 动作空间 |
JointActionSpace |
lerobot/policies/xvla/action_hub.py:175 |
| auto 动作空间 |
AutoActionSpace |
lerobot/policies/xvla/action_hub.py:345 |
| Florence2 配置 |
Florence2Config |
lerobot/policies/xvla/configuration_florence2.py |
| Florence2 模型 |
Florence2ForConditionalGeneration |
lerobot/policies/xvla/modeling_florence2.py |