SmolVLA 模型架构
1. 整体架构概览
SmolVLA (Small Vision-Language-Action) 是由 Hugging Face 设计的轻量级视觉-语言-动作 (VLA) 模型,采用 SmolVLM2-500M-Video-Instruct 作为视觉语言主干网络,并引入独立的 Action Expert 网络通过交叉注意力机制从 VLM 中提取特征来生成机器人动作。SmolVLA 使用 Flow Matching(与 Pi0 相同的范式)进行动作生成,通过迭代去噪将高斯噪声转化为动作轨迹。其核心设计理念是:VLM 处理前缀序列(图像 + 语言 + 状态),Action Expert 处理后缀序列(含噪动作 + 时间步),两者通过交叉注意力层交互,最终输出预测动作。
graph TB
subgraph Input["输入"]
IMG["相机图像<br/>(1~N 个视角)"]
TXT["语言指令<br/>(token 化)"]
STATE["机器人状态<br/>[B, max_state_dim]"]
end
subgraph VLMBackbone["SmolVLM2-500M 主干网络 (可冻结)"]
VE["SigLIP 视觉编码器"]
CONN["Connector 投影层"]
LLM["SmolVLM2 语言模型<br/>(前 16 层)"]
end
subgraph Projection["投影层"]
SP["state_proj<br/>Linear: state_dim -> hidden_size"]
end
subgraph ActionExpert["Action Expert 网络"]
AIP["action_in_proj<br/>Linear: action_dim -> expert_hidden"]
TML["action_time_mlp<br/>时间步融合 MLP"]
EXP["lm_expert<br/>(交叉注意力 + 自注意力<br/>交替的 Transformer 层)"]
AOP["action_out_proj<br/>Linear: expert_hidden -> action_dim"]
end
subgraph FlowMatch["Flow Matching"]
FM["高斯噪声采样<br/>+ Beta(1.5, 1.0) 时间步"]
end
subgraph Output["输出"]
ACT["预测动作轨迹<br/>[B, chunk_size, action_dim]"]
end
IMG --> VE --> CONN --> LLM
TXT --> LLM
STATE --> SP
SP -->|"状态嵌入"| LLM
LLM -->|"KV Cache<br/>前缀特征"| EXP
FM -->|"含噪动作 x_t"| AIP
AIP --> TML
TML -->|"动作+时间步嵌入"| EXP
EXP --> AOP --> ACT
style Input fill:#e8f4fd,stroke:#2196F3
style VLMBackbone fill:#fff3e0,stroke:#FF9800
style Projection fill:#f3e5f5,stroke:#9C27B0
style ActionExpert fill:#e8f5e9,stroke:#4CAF50
style FlowMatch fill:#e0f7fa,stroke:#00BCD4
style Output fill:#fce4ec,stroke:#E91E63
SmolVLA 的核心设计特点:
| 特性 |
SmolVLA |
GR00T N1.5 (对比) |
| VLM 主干 |
SmolVLM2-500M (SigLIP + SmolLM2) |
Eagle (SigLIP2 + Qwen3-1.7B) |
| 动作生成 |
Action Expert (交叉注意力) |
DiT (交替注意力) |
| 动作范式 |
Flow Matching (连续) |
Flow Matching (连续) |
| 注意力模式 |
前缀双向 + 后缀交叉注意力 |
交替交叉/自注意力 |
| 模型规模 |
~500M 参数 |
~2B+ 参数 |
| 推理步数 |
10 步 |
4 步 |
2. 核心组件详解
2.1 SmolVLM2-500M 视觉语言模型
SmolVLA 使用 HuggingFaceTB/SmolVLM2-500M-Video-Instruct 作为 VLM 主干,内部包含 SigLIP 视觉编码器、Connector 投影层和 SmolLM2 语言模型。VLM 的作用是处理前缀序列(图像 + 语言 + 状态),生成供 Action Expert 使用的 KV Cache。
graph LR
subgraph VisionEncoder["SigLIP 视觉编码器 (vision_model)"]
PIX["pixel_values<br/>[B, 3, 512, 512]<br/>像素范围 [-1, 1]"] --> SIG["SigLIP<br/>视觉编码器"]
SIG --> FEAT["图像特征<br/>[B, N_patches, vis_dim]"]
end
subgraph Connector["Connector 投影层"]
FEAT --> CPROJ["Connector<br/>(Modality Projection<br/>+ Resampling)"]
CPROJ --> VFEAT["投影后特征<br/>[B, N_tokens, hidden_size]"]
end
subgraph TextModel["SmolLM2 语言模型 (text_model)"]
LANG["语言 token<br/>[B, seq_len]"] --> LEMB["词元嵌入层"]
LEMB --> NORM["嵌入 * sqrt(dim)<br/>归一化"]
VFEAT -->|"图像特殊 token<br/>包裹后拼接"| MERGE["融合至序列"]
NORM --> MERGE
MERGE --> LAYERS["SmolLM2 Transformer<br/>前 num_vlm_layers 层<br/>(默认 16 层)"]
end
LAYERS -->|"VLM 隐藏状态<br/>[B, prefix_len, hidden_size]"| OUT["前缀特征"]
style VisionEncoder fill:#e3f2fd,stroke:#2196F3
style Connector fill:#f3e5f5,stroke:#9C27B0
style TextModel fill:#e8f5e9,stroke:#4CAF50
图像预处理流程:
- 图像缩放至
512x512,保持宽高比并用 0 填充(resize_with_pad)
- 像素值从
[0, 1] 映射至 [-1, 1](SigLIP 要求)
- SigLIP 编码后经过 Connector 投影至语言模型维度
- 图像嵌入乘以
sqrt(dim) 进行归一化
- 可选:添加特殊图像 token(
fake_image_token + global_image_token)包裹
前缀序列拼接顺序:
[图像1特殊token] [图像1 patch嵌入] [图像1结束token] ... [语言嵌入] [状态嵌入]
VLM 层截断: 与 GR00T 类似,SmolVLA 通过 num_vlm_layers 参数(默认 16)截断 VLM 的 Transformer 层数,仅使用前 16 层。
冻结策略:
- freeze_vision_encoder=True(默认):SigLIP 视觉编码器完全冻结
- train_expert_only=True(默认):整个 VLM 冻结,仅训练 Action Expert
2.2 Action Expert 网络(交叉注意力)
Action Expert 是 SmolVLA 的核心创新:一个独立的、更小的 Transformer 网络,通过交叉注意力从 VLM 的 KV Cache 中读取信息。其宽度通过 expert_width_multiplier(默认 0.75)控制,隐藏维度为 VLM 隐藏维度的 75%。
graph TB
subgraph ExpertConfig["Action Expert 配置"]
direction LR
C1["hidden_size = int(vlm_hidden * 0.75)"]
C2["intermediate_size = get_intermediate_size(hidden_size)"]
C3["num_layers = num_vlm_layers (默认 16)"]
C4["每 2 层交替一次自注意力"]
end
subgraph ExpertArch["Action Expert Transformer 层结构"]
direction TB
subgraph Layer0["Layer 0 — 自注意力层 (layer_idx % 2 == 0)"]
IN0["后缀嵌入"] --> LN0["RMSNorm"]
LN0 --> SA0["自注意力<br/>Q, K, V 均来自后缀"]
SA0 --> RES0["+ 残差"]
RES0 --> PLN0["Post-Attention RMSNorm"]
PLN0 --> MLP0["前馈 MLP"]
MLP0 --> PRES0["+ 残差"]
end
subgraph Layer1["Layer 1 — 交叉注意力层 (layer_idx % 2 != 0)"]
IN1["后缀嵌入"] --> LN1["RMSNorm"]
LN1 --> CA1["交叉注意力<br/>Q 来自后缀<br/>K, V 来自 VLM KV Cache"]
CA1 --> RES1["+ 残差"]
RES1 --> PLN1["Post-Attention RMSNorm"]
PLN1 --> MLP1["前馈 MLP"]
MLP1 --> PRES1["+ 残差"]
end
PRES0 --> IN1
subgraph Layer2["Layer 2 — 自注意力层"]
SA2["自注意力..."]
end
PRES1 --> SA2
SA2 --> DOTS["... 交替至第 N 层"]
end
subgraph KVSource["KV 来源"]
VLM_KV["VLM KV Cache<br/>(前缀特征的 K, V)"]
end
VLM_KV -->|"K, V 投影<br/>(k_proj, v_proj 重新定义<br/>输入维度 = vlm_kv_dim)"| CA1
style ExpertConfig fill:#fff8e1,stroke:#FFC107
style ExpertArch fill:#e8f5e9,stroke:#4CAF50
style Layer0 fill:#e3f2fd,stroke:#2196F3
style Layer1 fill:#fce4ec,stroke:#E91E63
style Layer2 fill:#e3f2fd,stroke:#2196F3
style KVSource fill:#fff3e0,stroke:#FF9800
交叉注意力层的 K, V 投影重塑:
在交叉注意力层中,K 和 V 来自 VLM 的 KV Cache,其维度为 num_kv_heads * head_dim。由于 Expert 的隐藏维度不同于 VLM,SmolVLA 在初始化时重新创建了这些层的 k_proj 和 v_proj:
# 交叉注意力层的 K, V 投影
k_proj = Linear(vlm_kv_heads * vlm_head_dim, expert_kv_heads * expert_head_dim)
v_proj = Linear(vlm_kv_heads * vlm_head_dim, expert_kv_heads * expert_head_dim)
层对应关系: 当 num_expert_layers < num_vlm_layers 时,Expert 层与 VLM 层按比例对应。例如 VLM 有 16 层、Expert 有 8 层时,每隔一层 VLM 层对应一个 Expert 层。未对应的层跳过 Expert 处理。
2.3 Flow Matching 扩散机制
SmolVLA 使用 Flow Matching(条件流匹配)范式生成动作,与 Pi0 相同。核心思想是学习从噪声分布到动作分布的"速度场",训练时通过线性插值构造含噪样本,推理时通过欧拉积分迭代去噪。
graph TB
subgraph Training["训练时: 构造含噪样本"]
direction TB
A_GT["真实动作 a<br/>[B, 50, action_dim]"]
NOISE["高斯噪声 epsilon<br/>~ N(0, 1)"]
BETA["时间步 t<br/>~ Beta(1.5, 1.0) * 0.999 + 0.001"]
A_GT --> INTERP["线性插值<br/>x_t = t * epsilon + (1 - t) * a"]
NOISE --> INTERP
BETA --> INTERP
A_GT --> TARGET["速度目标<br/>u_t = epsilon - a"]
NOISE --> TARGET
INTERP --> XT["含噪动作 x_t"]
TARGET --> UT["目标速度 u_t"]
end
subgraph Model["模型预测"]
XT --> VLA["SmolVLA<br/>(VLM + Expert)"]
BETA -->|"时间步条件"| VLA
VLA --> VT["预测速度 v_t"]
end
subgraph Loss["损失"]
UT --> MSE["MSE Loss<br/>||u_t - v_t||^2"]
VT --> MSE
end
style Training fill:#e0f7fa,stroke:#00BCD4
style Model fill:#e8f5e9,stroke:#4CAF50
style Loss fill:#fce4ec,stroke:#E91E63
Flow Matching 关键公式:
| 公式 |
说明 |
t ~ Beta(1.5, 1.0) * 0.999 + 0.001 |
时间步采样,偏向 t 接近 1(更接近噪声) |
x_t = t * noise + (1 - t) * action |
线性插值构造含噪样本(t=0 为干净动作,t=1 为纯噪声) |
u_t = noise - action |
速度目标(从动作到噪声的方向) |
loss = MSE(u_t, v_t) |
训练损失 |
x_{t+dt} = x_t + dt * v_t |
推理时欧拉积分(dt = -1/num_steps) |
注意: SmolVLA 的插值方向与某些文献相反:t=0 对应干净动作,t=1 对应纯噪声。推理时从 t=1 开始,逐步向 t=0 去噪。
2.4 状态投影与动作投影
SmolVLA 通过一系列线性投影层实现不同维度空间之间的映射。
graph LR
subgraph StateProj["状态投影 (state_proj)"]
S_IN["机器人状态<br/>[B, max_state_dim=32]"]
S_IN --> SP["Linear<br/>(32 -> vlm_hidden_size)"]
SP --> S_OUT["状态嵌入<br/>[B, 1, vlm_hidden_size]"]
end
subgraph ActionInProj["动作输入投影 (action_in_proj)"]
A_IN["含噪动作 x_t<br/>[B, 50, max_action_dim=32]"]
A_IN --> AIP["Linear<br/>(32 -> expert_hidden_size)"]
AIP --> A_EMB["动作嵌入<br/>[B, 50, expert_hidden]"]
end
subgraph TimeEmb["时间步嵌入"]
T_IN["时间步 t<br/>[B]"]
T_IN --> SIN["正弦余弦位置编码<br/>dim=expert_hidden_size<br/>period: [4e-3, 4.0]"]
SIN --> T_EMB["时间嵌入<br/>[B, 1, expert_hidden]"]
T_EMB --> EXPAND["广播至动作长度<br/>[B, 50, expert_hidden]"]
end
subgraph TimeFusion["时间步融合 MLP (action_time_mlp)"]
A_EMB --> CAT["Concat<br/>[B, 50, expert_hidden*2]"]
EXPAND --> CAT
CAT --> MLP_IN["Linear<br/>(expert_hidden*2 -> expert_hidden)"]
MLP_IN --> SILU["SiLU 激活函数"]
SILU --> MLP_OUT["Linear<br/>(expert_hidden -> expert_hidden)"]
MLP_OUT --> FUSED["融合后的动作+时间嵌入<br/>[B, 50, expert_hidden]"]
end
subgraph ActionOutProj["动作输出投影 (action_out_proj)"]
EXP_OUT["Expert 输出<br/>[B, 50, expert_hidden]"]
EXP_OUT --> CAST["上转型至 float32"]
CAST --> AOP["Linear<br/>(expert_hidden -> 32)"]
AOP --> V_OUT["预测速度 v_t<br/>[B, 50, max_action_dim=32]"]
end
style StateProj fill:#e3f2fd,stroke:#2196F3
style ActionInProj fill:#f3e5f5,stroke:#9C27B0
style TimeEmb fill:#fff8e1,stroke:#FFC107
style TimeFusion fill:#e0f7fa,stroke:#00BCD4
style ActionOutProj fill:#fce4ec,stroke:#E91E63
维度填充机制: SmolVLA 将所有状态和动作向量填充至固定维度(max_state_dim=32,max_action_dim=32),不足部分补零。推理后再截断回原始维度。这使得模型能够兼容不同自由度的机器人。
3. 训练流水线
训练时,模型接收完整的前缀和后缀序列,一次前向传播同时处理 VLM 和 Expert。注意力掩码确保前缀序列(图像、语言)采用双向注意力,而后缀序列(含噪动作)只能通过交叉注意力关注前缀。
graph TB
subgraph DataPrep["数据准备"]
direction LR
IMG_RAW["原始图像"] --> RESIZE["resize_with_pad<br/>-> [512, 512]<br/>-> [-1, 1]"]
STATE_RAW["原始状态"] --> PAD_S["pad_vector<br/>-> [max_state_dim=32]"]
ACT_RAW["原始动作"] --> PAD_A["pad_vector<br/>-> [B, 50, 32]"]
LANG_RAW["语言指令"] --> TOKENIZE["分词器<br/>max_length=48"]
end
subgraph NoiseSample["噪声采样"]
direction LR
EPSILON["epsilon ~ N(0, 1)<br/>[B, 50, 32]"]
T_SAMPLE["t ~ Beta(1.5, 1.0)<br/>* 0.999 + 0.001"]
T_SAMPLE --> INTERP
EPSILON --> INTERP["x_t = t*epsilon + (1-t)*action"]
PAD_A --> INTERP
EPSILON --> VEL_TARGET["u_t = epsilon - action"]
PAD_A --> VEL_TARGET
end
subgraph PrefixEmbed["前缀嵌入 (embed_prefix)"]
RESIZE --> VE["SigLIP 编码"]
VE --> IMG_EMB["图像嵌入 * sqrt(dim)"]
TOKENIZE --> LANG_EMB["语言嵌入 * sqrt(dim)"]
PAD_S --> STATE_EMB["state_proj"]
IMG_EMB --> PREFIX_CAT["拼接: [img | lang | state]"]
LANG_EMB --> PREFIX_CAT
STATE_EMB --> PREFIX_CAT
PREFIX_CAT --> PREFIX["prefix_embs<br/>[B, prefix_len, vlm_hidden]"]
end
subgraph SuffixEmbed["后缀嵌入 (embed_suffix)"]
INTERP --> AIN["action_in_proj"]
T_SAMPLE --> TIME_EMB["正弦余弦编码"]
AIN --> FUSE["concat + action_time_mlp<br/>+ SiLU"]
TIME_EMB --> FUSE
FUSE --> SUFFIX["suffix_embs<br/>[B, 50, expert_hidden]"]
end
subgraph AttMask["注意力掩码构造"]
direction LR
AM1["前缀 att_mask: 0<br/>(双向注意力)"]
AM2["状态 att_mask: 1<br/>(因果边界)"]
AM3["后缀 att_mask: 1<br/>(因果边界)"]
AM1 --> MASK_2D["make_att_2d_masks<br/>构造 2D 注意力掩码"]
AM2 --> MASK_2D
AM3 --> MASK_2D
end
subgraph Forward["联合前向传播"]
PREFIX --> VLM_EXP["VLM + Expert<br/>逐层交替处理"]
SUFFIX --> VLM_EXP
MASK_2D --> VLM_EXP
VLM_EXP --> EXPERT_OUT["Expert 输出<br/>取最后 50 个 token"]
EXPERT_OUT --> AOUT["action_out_proj<br/>(float32)"]
AOUT --> V_PRED["预测速度 v_t"]
end
subgraph LossCalc["损失计算"]
V_PRED --> MSE["MSE Loss<br/>||u_t - v_t||^2"]
VEL_TARGET --> MSE
MSE --> MASK_LOSS["应用 in_episode_bound 掩码<br/>+ 截断至原始 action_dim"]
MASK_LOSS --> FINAL_LOSS["最终损失"]
end
style DataPrep fill:#fff3e0,stroke:#FF9800
style NoiseSample fill:#e0f7fa,stroke:#00BCD4
style PrefixEmbed fill:#e3f2fd,stroke:#2196F3
style SuffixEmbed fill:#f3e5f5,stroke:#9C27B0
style AttMask fill:#fff8e1,stroke:#FFC107
style Forward fill:#e8f5e9,stroke:#4CAF50
style LossCalc fill:#fce4ec,stroke:#E91E63
训练时注意力掩码详解:
前缀 (图像+语言): att_mask = [0, 0, 0, ..., 0] -> 双向注意力(互相可见)
前缀 (状态): att_mask = [1] -> 因果边界(图像/语言不关注状态)
后缀 (动作+时间): att_mask = [1, 1, ..., 1] -> 因果边界(前缀不关注后缀)
通过 make_att_2d_masks 函数,基于 att_mask 的累积和构造完整的 2D 注意力掩码矩阵。结果是:
- 图像和语言 token 之间双向可见
- 状态和动作 token 可以看到前面的所有 token
- 图像和语言 token 无法看到状态和动作 token
4. 推理流水线
推理时采用两阶段:先计算前缀的 KV Cache(一次),然后通过 10 步欧拉积分迭代去噪后缀。KV Cache 使得前缀只需计算一次,大幅节省推理时间。
graph TB
subgraph Phase1["阶段 1: 前缀编码 (一次性)"]
IMG_IN["图像"] --> EMB_P["embed_prefix<br/>SigLIP + 语言嵌入 + 状态投影"]
LANG_IN["语言指令"] --> EMB_P
STATE_IN["机器人状态"] --> EMB_P
EMB_P --> VLM_FWD["VLM 前向<br/>fill_kv_cache=True"]
VLM_FWD --> KV["KV Cache<br/>(每层的 key_states, value_states)"]
end
subgraph Phase2["阶段 2: 迭代去噪 (10 步欧拉积分)"]
INIT["初始化<br/>x_1 ~ N(0, 1)<br/>[B, 50, 32]"]
INIT --> STEP1
subgraph STEP1["Step 1: t=1.0"]
E1["embed_suffix(x_t, t)"] --> D1["denoise_step<br/>Expert 前向 + KV Cache"]
D1 --> V1["v_1"]
V1 --> U1["x_t += dt * v_1<br/>dt = -0.1"]
end
subgraph STEP2["Step 2: t=0.9"]
E2["embed_suffix(x_t, t)"] --> D2["denoise_step"]
D2 --> V2["v_2"]
V2 --> U2["x_t += dt * v_2"]
end
subgraph STEP3["Step 3~9: t=0.8 ... 0.2"]
DOTS2["...重复去噪..."]
end
subgraph STEP10["Step 10: t=0.1"]
E10["embed_suffix(x_t, t)"] --> D10["denoise_step"]
D10 --> V10["v_10"]
V10 --> U10["x_t += dt * v_10"]
end
U1 --> STEP2
U2 --> STEP3
STEP3 --> STEP10
end
KV -->|"传入每步"| D1
KV -->|"传入每步"| D2
KV -->|"传入每步"| D10
subgraph Output["输出"]
U10 --> UNPAD["截断至原始 action_dim"]
UNPAD --> ACTIONS["最终动作轨迹<br/>[B, 50, action_dim]"]
end
style Phase1 fill:#e3f2fd,stroke:#2196F3
style Phase2 fill:#e8f5e9,stroke:#4CAF50
style STEP1 fill:#f1f8e9,stroke:#8BC34A
style STEP2 fill:#f1f8e9,stroke:#8BC34A
style STEP3 fill:#f1f8e9,stroke:#8BC34A
style STEP10 fill:#f1f8e9,stroke:#8BC34A
style Output fill:#fce4ec,stroke:#E91E63
单步去噪详解 (denoise_step)
graph LR
XT["x_t<br/>[B, 50, 32]"] --> AIP["action_in_proj"]
TS["timestep t"] --> SIN_COS["正弦余弦编码<br/>[B, expert_hidden]"]
AIP --> ACT_EMB["动作嵌入<br/>[B, 50, expert_hidden]"]
SIN_COS --> EXPAND["广播<br/>[B, 50, expert_hidden]"]
ACT_EMB --> CAT["Concat<br/>[B, 50, expert_hidden*2]"]
EXPAND --> CAT
CAT --> TML_IN["action_time_mlp_in"]
TML_IN --> SILU["SiLU"]
SILU --> TML_OUT["action_time_mlp_out"]
TML_OUT --> SUFFIX["suffix_embs"]
SUFFIX --> ATTN["构造注意力掩码<br/>(prefix KV + suffix 2D mask)"]
KV["KV Cache"] --> ATTN
ATTN --> EXPERT["Expert 前向<br/>(交叉注意力读取 KV Cache)"]
EXPERT --> LAST50["取最后 50 token"]
LAST50 --> FP32["转为 float32"]
FP32 --> AOP["action_out_proj"]
AOP --> VT["预测速度 v_t<br/>[B, 50, 32]"]
style XT fill:#e0f7fa,stroke:#00BCD4
style EXPERT fill:#e8f5e9,stroke:#4CAF50
style VT fill:#fce4ec,stroke:#E91E63
推理时的注意力掩码: 后缀的每个 token 可以通过交叉注意力看到前缀 KV Cache 中的所有有效 token(基于 prefix_pad_masks),同时后缀 token 之间通过 suffix_att_masks 控制可见性。
5. 关键超参数表
| 参数 |
默认值 |
说明 |
| 模型结构 |
|
|
vlm_model_name |
HuggingFaceTB/SmolVLM2-500M-Video-Instruct |
VLM 主干模型 |
num_vlm_layers |
16 |
VLM 使用的 Transformer 层数 |
num_expert_layers |
-1 (与 VLM 相同) |
Action Expert 层数 |
expert_width_multiplier |
0.75 |
Expert 隐藏维度 = VLM 隐藏维度 * 0.75 |
self_attn_every_n_layers |
2 |
每 2 层插入一个自注意力层 |
attention_mode |
cross_attn |
交叉注意力模式 |
| 输入/输出 |
|
|
chunk_size |
50 |
动作块大小(预测未来 50 步) |
n_action_steps |
50 |
每次执行的动作步数 |
n_obs_steps |
1 |
观测步数 |
max_state_dim |
32 |
状态向量最大维度(不足补零) |
max_action_dim |
32 |
动作向量最大维度(不足补零) |
| 图像处理 |
|
|
resize_imgs_with_padding |
(512, 512) |
图像缩放至 512x512 |
empty_cameras |
0 |
空相机数量(用零填充) |
add_image_special_tokens |
False |
是否添加图像特殊 token |
| Flow Matching |
|
|
num_steps |
10 |
推理去噪步数 |
| 噪声分布 |
N(0, 1) |
高斯噪声 |
| 时间步分布 |
Beta(1.5, 1.0) * 0.999 + 0.001 |
偏向 t 接近 1 |
min_period |
4e-3 |
时间步正弦编码最小周期 |
max_period |
4.0 |
时间步正弦编码最大周期 |
| 训练设置 |
|
|
freeze_vision_encoder |
True |
冻结 SigLIP 视觉编码器 |
train_expert_only |
True |
仅训练 Action Expert |
train_state_proj |
True |
训练状态投影层 |
optimizer_lr |
1e-4 |
学习率 |
optimizer_betas |
(0.9, 0.95) |
Adam beta 参数 |
optimizer_weight_decay |
1e-10 |
权重衰减 |
optimizer_grad_clip_norm |
10 |
梯度裁剪 |
scheduler_warmup_steps |
1,000 |
学习率预热步数 |
scheduler_decay_steps |
30,000 |
余弦衰减步数 |
scheduler_decay_lr |
2.5e-6 |
衰减后最低学习率 |
| 推理优化 |
|
|
use_cache |
True |
使用 KV Cache 加速推理 |
tokenizer_max_length |
48 |
分词器最大长度 |
prefix_length |
-1 (不填充) |
前缀固定长度(-1 表示不填充) |
6. 关键源文件表
| 组件 |
类名 |
文件路径 |
| 策略封装 |
SmolVLAPolicy |
lerobot/policies/smolvla/modeling_smolvla.py:225 |
| 核心模型 |
VLAFlowMatching |
lerobot/policies/smolvla/modeling_smolvla.py:530 |
| VLM + Expert 封装 |
SmolVLMWithExpertModel |
lerobot/policies/smolvla/smolvlm_with_expert.py:61 |
| 模型配置 |
SmolVLAConfig |
lerobot/policies/smolvla/configuration_smolvla.py:29 |
| 注意力掩码工具 |
make_att_2d_masks |
lerobot/policies/smolvla/modeling_smolvla.py:102 |
| 正弦位置编码 |
create_sinusoidal_pos_embedding |
lerobot/policies/smolvla/modeling_smolvla.py:81 |
| RoPE 实现 |
apply_rope |
lerobot/policies/smolvla/smolvlm_with_expert.py:28 |
| 图像缩放 |
resize_with_pad |
lerobot/policies/smolvla/modeling_smolvla.py:135 |
| 向量填充 |
pad_vector |
lerobot/policies/smolvla/modeling_smolvla.py:157 |
| RTC 处理器 |
RTCProcessor |
lerobot/policies/rtc/modeling_rtc.py |