VLA 算法工程师面试准备指南¶
面向字节跳动 Seed 团队等具身智能公司的 VLA 岗位,涵盖深度学习、机器人学、VLA 核心技术、Sim-to-Real 等核心考察维度,100+ 面试题附参考答案。
1. 岗位概览与招聘趋势¶
1.1 字节跳动 Seed 团队介绍¶
字节跳动于 2023 年正式成立 Seed 团队,定位为前沿 AI 研究部门,研究方向涵盖:
| 方向 | 内容 |
|---|---|
| LLM | 大语言模型预训练与对齐 |
| 语音 | 多语言语音合成与识别 |
| 视觉 | 视觉理解、生成与编辑 |
| 世界模型 | 物理世界建模与仿真 |
| 机器人 / 具身智能 | VLA 模型、操作、导航、移动操作 |
Seed 团队在 VLA 领域的主要产出包括大模型驱动的机器人策略、仿真到真实迁移方案,以及基于视频预测的世界模型。团队成员多来自国内外顶尖高校和实验室,学术氛围浓厚,同时有大规模算力和数据支持。
1.2 VLA 算法工程师岗位 JD 解读¶
以下综合高仙机器人、某大型智能硬件公司等实际 JD 归纳典型要求:
典型职责:
- 负责 VLA 模型(Vision-Language-Action)的研发、微调与部署
- 研究并实现扩散策略(Diffusion Policy)、流匹配(Flow Matching)等动作生成方法
- 解决泛化抓取、灵巧操作等实际任务
- 推进仿真到真实(Sim-to-Real)的迁移与验证
- 跟踪具身智能领域最新进展,复现前沿论文
典型要求:
- 熟悉机器人规控算法(运动规划、轨迹优化)或大模型算法(预训练、微调、推理优化)
- 熟悉多模态算法(CLIP、VLM、VLA)
- 有 VLA / 模仿学习 / 机器人学习相关项目经验
- 熟悉 PyTorch,了解分布式训练
- 有机器人操作或导航实机部署经验者优先
- 在顶会(CoRL、RSS、ICRA、IROS、NeurIPS、ICML 等)有论文发表者优先
薪资范围: 55-120K/月(因公司、级别、城市而异,字节/智元等头部公司偏高)
1.3 热门招聘公司¶
| 公司 | 方向特点 | 代表工作 |
|---|---|---|
| 字节跳动 Seed | 大规模 VLA、世界模型、仿真 | 自研 VLA 模型 |
| 高仙机器人 | 商用清洁机器人、SLAM + VLA | 扫地机器人智能操作 |
| 星动纪元 (Star Era) | 人形机器人全身控制 | 端到端人形操作 |
| 智元机器人 (AGIBOT) | 通用人形机器人 | 具身大模型 |
| 穹彻智能 (Qingche) | 通用操作策略 | 非凡蛋白系列模型 |
| 银河通用 (GalaxyBot) | 通用桌面/移动操作 | 跨平台 VLA |
| Physical Intelligence (海外) | 通用机器人基础模型 | pi0 |
| Stanford / Berkeley (学术) | 开源 VLA 基准 | OpenVLA, Octo |
2. 深度学习基础(必考)¶
2.1 Transformer 架构细节¶
Self-Attention 计算复杂度¶
标准 Self-Attention 的计算:
$$\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V$$
- 时间复杂度: $O(N^2 d)$,其中 $N$ 为序列长度,$d$ 为特征维度
- $QK^T$ 计算为 $O(N^2 d)$
- Softmax 为 $O(N^2)$
- 乘 $V$ 为 $O(N^2 d)$
- 空间复杂度: $O(N^2)$(存储 attention matrix)
- 核心瓶颈: $N^2$ 项,当序列很长时(如高分辨率图像的 patch 数)计算和显存开销巨大
Multi-Head Attention 的作用¶
将 $Q, K, V$ 分成 $h$ 个头,每个头独立计算 attention:
$$\text{MultiHead}(Q, K, V) = \text{Concat}(\text{head}_1, ..., \text{head}_h)W^O$$
$$\text{head}_i = \text{Attention}(QW_i^Q, KW_i^K, VW_i^V)$$
作用: - 每个头学习不同的注意力模式(如局部 vs 全局、空间 vs 语义) - 相当于将 $d$ 维特征空间拆分为 $h$ 个 $d/h$ 维子空间 - 多头并行比单头(同参数量)有更强的表达能力 - VLA 中,不同头可关注不同模态特征(视觉区域 vs 语言 token vs 动作 token)
位置编码¶
| 方法 | 公式/原理 | 优点 | 缺点 | 使用者 |
|---|---|---|---|---|
| Sinusoidal (原版 Transformer) | $\sin/\cos$ 不同频率的位置向量 | 无需学习,可外推到更长序列 | 绝对位置,缺乏相对关系建模 | CLIP ViT (部分) |
| RoPE (Rotary Position Embedding) | 用旋转矩阵编码相对位置 | 天然编码相对位置,外推性好 | 计算稍复杂 | LLaMA, OpenVLA 的语言主干 |
| ALiBi (Attention with Linear Biases) | 在 attention score 上加距离相关的线性偏置 | 简单有效,外推性好 | 需要修改 attention 计算 | BLOOM, 部分长上下文模型 |
2.2 VLM 对齐技术¶
CLIP 对比学习 Loss¶
CLIP 的核心是 InfoNCE Loss(对称版本):
$$\mathcal{L} = -\frac{1}{N}\sum_{i=1}^{N}\left[\log\frac{\exp(\text{sim}(I_i, T_i)/\tau)}{\sum_j \exp(\text{sim}(I_i, T_j)/\tau)} + \log\frac{\exp(\text{sim}(I_i, T_i)/\tau)}{\sum_j \exp(\text{sim}(I_j, T_i)/\tau)}\right]$$
其中 $\text{sim}(a, b) = a^T b / (|a| \cdot |b|)$,$\tau$ 为 temperature 参数。
关键点: - 拉近匹配的 image-text 对,推开不匹配的 - 负样本来自 batch 内其他样本(in-batch negative) - 需要大 batch size(CLIP 用 32768)来提供足够多的负样本
DINOv2 自蒸馏¶
- 教师网络(EMA 更新)+ 学生网络同时处理输入
- 学生预测教师的输出(class token + patch token 的 attention map)
- 结合 iBOT 掩码预测:随机遮挡部分 patch,让模型预测被遮挡区域
- 纯自监督,不需要文本标注
- 产出强空间/几何特征(OpenVLA 用它理解场景的空间结构)
SigLIP sigmoid loss vs CLIP softmax loss¶
| 对比项 | CLIP (softmax) | SigLIP (sigmoid) |
|---|---|---|
| Loss 形式 | 全局 softmax(batch 内竞争) | 逐对 sigmoid |
| 计算方式 | $\text{softmax}(\text{sim}/\tau)$ 对整行归一化 | $\sigma(\text{sim}/\tau - b)$ 每对独立 |
| 受 batch size 影响 | 大(需要大 batch) | 小(每对独立计算) |
| 训练效率 | batch 越大越好 | 小 batch 也能训练 |
| 零样本性能 | 强 | 在部分 benchmark 上超越 CLIP |
2.3 训练技巧¶
LoRA 原理及数学推导¶
核心思想:冻结预训练权重 $W_0 \in \mathbb{R}^{d \times k}$,用低秩分解近似更新量:
$$W = W_0 + \Delta W = W_0 + BA$$
其中 $B \in \mathbb{R}^{d \times r}$,$A \in \mathbb{R}^{r \times k}$,$r \ll \min(d, k)$。
前向传播:$h = W_0 x + BAx = W_0 x + B(Ax)$
为什么有效: - Aghajanyan et al. (2020) 证明预训练模型的微调过程具有"低内在维度"(intrinsic dimensionality),即有效的参数更新可以用低秩空间表示 - 典型 $r=8$ 或 $r=16$ 时,可训练参数量减少 1000 倍以上 - 防止过拟合(尤其在小数据集微调时)
OpenVLA 中的使用:LoRA rank=32,应用于 QKV 投影矩阵,在目标机器人 5k-10k 步微调即可适配。
QKV 投影矩阵的作用¶
Self-Attention 中需要将输入 $X$ 投影到 Query、Key、Value 三个空间:
$$Q = XW^Q, \quad K = XW^K, \quad V = XW^V$$
- $W^Q$:决定"我在找什么"——当前 token 作为 Query 时关注哪些特征
- $W^K$:决定"我能提供什么"——当前 token 作为 Key 时被怎样检索
- $W^V$:决定"我携带什么信息"——被选中后传递什么内容
在 LoRA 微调中,通常对 QKV 投影矩阵添加低秩适配器(如 OpenVLA 的做法)。
Flash Attention 原理¶
问题:标准 Attention 需要存储完整的 $N \times N$ attention matrix,显存占用 $O(N^2)$。
Flash Attention 核心思想: 1. Tiling(分块计算):将 Q, K, V 分成小块,每次只计算一个块的 attention 2. Online Softmax:不存储完整 attention matrix,用在线算法逐步更新 softmax 的分子和分母 3. IO 感知:利用 GPU 的 SRAM(片上高速缓存)做分块计算,减少 HBM(显存)的读写次数
效果: - 显存从 $O(N^2)$ 降到 $O(N)$ - 计算速度提升 2-4x(减少 HBM 访问) - 数学结果与标准 Attention 完全一致(exact attention)
2.4 深度学习面试题(20 题)¶
Q1: 解释 LoRA 为什么只用少量参数就能微调大模型
【考察点】LoRA 原理、低秩假设、参数效率
参考答案: LoRA 的理论基础是"内在低秩假设"(Aghajanyan et al., 2020)。研究表明,预训练模型在微调时,有效的参数更新 $\Delta W$ 可以被投影到一个远小于原始维度的子空间中。具体做法是冻结原始权重 $W_0$,引入两个低秩矩阵 $B \in \mathbb{R}^{d \times r}$ 和 $A \in \mathbb{R}^{r \times k}$($r$ 通常为 8-64),使得 $W = W_0 + BA$。当 $r \ll d, k$ 时,可训练参数量从 $d \times k$ 降到 $d \times r + r \times k$。例如在 7B 模型中,对 4096 维的 QKV 投影矩阵使用 $r=32$,参数量减少约 128 倍。这不仅降低了显存需求,还通过限制参数空间起到正则化作用,减少过拟合风险。
Q2: CLIP 的 contrastive loss 为什么用 temperature scaling
【考察点】对比学习、温度参数的作用
参考答案: CLIP 使用 InfoNCE Loss,其中温度参数 $\tau$ 控制 logits 分布的"尖锐程度"。$\text{logits} = \text{sim}(I_i, T_j) / \tau$。当 $\tau$ 较小时,匹配对的概率更集中(接近 one-hot),负样本的梯度更大,模型学得更"坚决"但可能不稳定;当 $\tau$ 较大时,分布更平滑,训练更稳定但区分度下降。CLIP 实验中 $\tau$ 作为可学习参数,初始值设为 0.07。温度 scaling 本质上是在控制对比学习的"难度"——过小会导致训练初期梯度消失,过大会让模型难以区分正负样本。它还起到归一化 logits 量纲的作用,使不同 batch size 下的训练更一致。
Q3: Flash Attention 是如何减少显存占用的
【考察点】注意力优化、GPU 内存层次
参考答案: 标准 Self-Attention 需要 $O(N^2)$ 显存存储完整的 attention matrix。Flash Attention 通过三个关键技术解决这个问题:(1) 分块计算(Tiling):将 Q、K、V 分成适合 GPU SRAM(片上缓存)的小块,逐块计算 attention;(2) 在线 Softmax(Online Softmax):利用 softmax 的数学性质,通过维护 running max 和 running sum 逐步计算,无需存储完整的 softmax 中间结果;(3) IO 感知:显存瓶颈不在计算而在 GPU HBM 的带宽,Flash Attention 通过减少 HBM 读写次数(从 $O(N^2 d)$ 降到 $O(N^2 d^2 / M)$,其中 $M$ 为 SRAM 大小)来加速。最终实现 $O(N)$ 的显存占用(只需存储输出)和 2-4x 的速度提升,且结果与标准 Attention 数值完全一致。
Q4: DINOv2 和 CLIP ViT 的区别是什么
【考察点】视觉编码器对比、自监督 vs 对比学习
参考答案:
| 对比维度 | DINOv2 | CLIP ViT |
|---|---|---|
| 训练方式 | 自蒸馏(self-distillation)+ iBOT 掩码预测 | 图像-文本对比学习 |
| 是否需要文本 | 不需要 | 需要(图像-文本配对数据) |
| 特征优势 | 空间/几何理解强,attention map 可解释 | 语义/语言对齐强,零样本分类好 |
| 训练数据 | 142M 无标注图像 | 400M 图像-文本对 |
| 在 VLA 中的角色 | 提供场景的空间结构理解(物体边界、深度) | 提供语言对齐的视觉特征(识别物体类别) |
OpenVLA 同时使用两者:DINOv2 负责"看清楚空间关系",SigLIP 负责"理解物体是什么",两者互补。详见 02-key-papers.md 中 DINOv2 和 CLIP 的论文解读。
Q5: 什么是 co-training,为什么 RT-2 需要同时训练 VQA 和机器人数据
【考察点】多任务训练、灾难性遗忘
参考答案: Co-training(联合训练)是在多种类型数据上同时训练模型的技术。RT-2 将机器人动作表示为文本 token 后,可以在同一个 VLM 上训练两类任务:(1) VQA/图像描述等视觉-语言任务;(2) 机器人动作预测任务。如果只训练机器人数据,模型会遗忘预训练的语义知识(灾难性遗忘),导致泛化能力下降——例如不再认识训练集中未出现过的物体。通过 co-training,模型在微调动作生成能力的同时,保持了对视觉世界的广泛理解。实验表明,co-training 使 RT-2 在语义推理任务(如"把易碎的物体放到安全的地方"→ 需要理解"易碎"含义)上的表现显著优于仅用机器人数据训练的版本。RT-2 的 co-training 比例约为 1:3(机器人数据 : VQA 数据)。
Q6: ViT 中 patch size 对模型效果的影响
【考察点】ViT 架构、计算效率与效果权衡
参考答案: Patch size 决定了图像被分割的粒度和 token 序列的长度。假设输入图像 $H \times W$,patch size $p$,则 token 数量 $N = (H/p) \times (W/p)$。
- 小 patch(如 14x14):token 数多,序列更长,能捕获更细粒度的局部特征,但计算量 $O(N^2)$ 显著增大。CLIP ViT-L/14 使用 14x14。
- 大 patch(如 32x32):token 数少(为 14x14 的 1/4),计算快,但丢失细粒度信息。CLIP ViT-B/32 使用 32x32。
- 对 VLA 的影响:操作任务需要精细的局部感知(如夹爪对准),通常偏好小 patch。但小 patch 带来的长序列会大幅增加 attention 计算量。OpenVLA 使用 SigLIP-ViT-SO400M(patch size 14),并通过投影层压缩视觉 token 数量。
Q7: Transformer 中的 LayerNorm vs RMSNorm
【考察点】归一化方法、LLaMA 架构
参考答案:
| 对比维度 | LayerNorm | RMSNorm |
|---|---|---|
| 公式 | $\hat{x}_i = \frac{x_i - \mu}{\sigma} \cdot \gamma_i + \beta_i$ | $\hat{x}_i = \frac{x_i}{\text{RMS}(x)} \cdot \gamma_i$ |
| 是否减去均值 | 是 | 否 |
| 是否有 bias 参数 $\beta$ | 有 | 无 |
| 计算量 | 稍大(需计算均值) | 稍小 |
| 效果 | 相当 | 相当,但推理更快 |
RMSNorm(Root Mean Square Normalization)假设均值为 0(Transformer 中通常通过前置的残差连接近似满足),只做方差的归一化。LLaMA 和 OpenVLA 的语言主干使用 RMSNorm,因为:(1) 计算更高效,(2) 去掉 $\beta$ 不影响效果,(3) 与 RoPE 配合更好。
Q8: 什么是 KV cache,为什么 VLA 推理中很关键
【考察点】自回归推理优化、延迟优化
参考答案: KV cache 是在自回归生成中缓存已计算的 Key 和 Value 矩阵,避免重复计算的技术。在第 $t$ 步生成时,只需计算第 $t$ 个 token 的 $Q$,与缓存的 $K_{1:t-1}$、$V_{1:t-1}$ 做 attention,而不需要重新计算所有历史 token。
在 VLA 推理中,RT-2 将动作离散化为 token 后需要自回归生成,例如 7 维动作 $\times$ 256 bins = 逐个生成多个 token。没有 KV cache 时,每生成一个 token 都需要重新处理所有历史 token(包括图像 token、文本 token、已生成的动作 token),延迟随生成长度线性增长。使用 KV cache 后,图像和文本的 KV 值只计算一次,每步只需计算新 token 的 QKV,延迟大幅降低。这是 VLA 实时控制的基础。
Q9: 解释 Transformer 中的残差连接为什么重要
【考察点】深层网络训练、梯度流动
参考答案: 残差连接 $y = x + F(x)$ 解决了深层网络训练中的两个核心问题:(1) 梯度消失:梯度可以直接通过 $x$ 的路径回传,不经过 $F(x)$ 的多层变换,使深层网络也能有效训练;(2) 信息保留:浅层学到的低级特征可以直接传递到深层,不会被后续层的变换破坏。在 VLA 中,视觉编码器、语言主干都堆叠了 20-40 层 Transformer,没有残差连接几乎无法训练。Pre-Norm(在 $F(x)$ 之前做 LayerNorm)比 Post-Norm 训练更稳定,是现代 VLA 的标配。
Q10: 解释 Multi-Head Attention 中为什么用 $d_k = d_{model} / h$ 而不是其他分配方式
【考察点】Attention 维度设计
参考答案: 原始 Transformer 论文(Vaswani et al., 2017)的设计使得每个头的计算量保持不变:$h$ 个头,每个头的维度 $d_k = d_{model}/h$,每个头的计算量约为 $O(N \cdot d_k \cdot d_k) = O(N \cdot d_{model}^2 / h^2)$,总计算量为 $h \times O(N \cdot d_{model}^2 / h^2) = O(N \cdot d_{model}^2 / h)$。这种分配确保:(1) 每个头有足够的维度来捕获有意义的注意力模式($d_k$ 不能太小);(2) 总计算量与单头 $d_k = d_{model}$ 相同,但多头提供了更丰富的表示能力。实践中 $d_k = 64$ 是一个经验上效果好的选择。
Q11: ViT 的 class token [CLS] 的作用是什么
【考察点】ViT 架构、特征聚合
参考答案: [CLS] token 是一个可学习的向量,在输入序列的最前面被添加,与其他 patch token 一起经过 Transformer 层。最终取 [CLS] token 的输出作为整个图像的全局表示。它的设计动机是:图像的 patch token 需要一种聚合方式来得到全局特征,[CLS] token 通过 self-attention 机制可以"看到"所有 patch 的信息,起到全局聚合器的作用。在 CLIP 中,[CLS] token 的输出用于计算图像嵌入;在 DINOv2 中,[CLS] 和 patch token 都被使用(后者通过自蒸馏 loss 约束)。
Q12: 解释 cross-entropy loss 和 MSE loss 的区别和适用场景
【考察点】损失函数选择
参考答案: - Cross-Entropy Loss:用于分类/离散输出。衡量预测概率分布与真实分布的 KL 散度。在 VLA 中,RT-2 用 cross-entropy 训练离散动作 token 的生成。 - MSE Loss:用于回归/连续输出。衡量预测值与真实值的平方差。在 VLA 中,OpenVLA 用 MSE 训练连续动作的回归。 - 选择依据:如果动作空间是离散的(token 化),用 cross-entropy;如果是连续的,用 MSE 或扩散模型的噪声预测 loss。离散化的优势是可以利用预训练 LLM 的自回归能力,但会引入量化误差;连续回归更直接,但需要从头训练策略头。
Q13: AdamW 相比 Adam 改进了什么
【考察点】优化器、权重衰减
参考答案: AdamW 将权重衰减(weight decay)从梯度更新中解耦出来。在原始 Adam 中,权重衰减通过修改梯度 $g_t = g_t + \lambda w_t$ 实现,这与自适应学习率($m_t, v_t$)耦合,导致实际衰减率依赖于梯度的二阶矩。AdamW 的做法是直接在参数更新时独立应用衰减:$w_t = (1 - \lambda \cdot \text{lr}) w_t - \text{lr} \cdot \hat{m}_t / (\sqrt{\hat{v}_t} + \epsilon)$。解耦后的权重衰减更加一致和可预测。VLA 训练中几乎都使用 AdamW,通常配合 cosine learning rate schedule 和 warmup。
Q14: 什么是梯度裁剪(Gradient Clipping),为什么训练大模型需要它
【考察点】训练稳定性
参考答案: 梯度裁剪是在反向传播后,对梯度的范数进行限制,防止梯度爆炸。常见做法有:(1) 按值裁剪:将超过阈值的梯度截断;(2) 按范数裁剪:当梯度范数 $|g| > \text{threshold}$ 时,缩放 $g \leftarrow g \cdot \text{threshold} / |g|$。大模型训练中,由于模型参数量大、层数深、序列长,某些 batch 或 token 可能产生异常大的梯度,导致训练不稳定甚至 NaN。VLA 训练中常用 max_grad_norm=1.0。注意梯度裁剪只是"创可贴",根本解决还需要检查数据质量、学习率、loss 设计等。
Q15: 解释 BatchNorm、LayerNorm、GroupNorm 的区别
【考察点】归一化方法
参考答案:
| 方法 | 归一化维度 | 受 batch size 影响 | 适用场景 |
|---|---|---|---|
| BatchNorm | 跨 batch 和空间维度 | 是 | CNN(大 batch) |
| LayerNorm | 跨特征维度 | 否 | Transformer / RNN |
| GroupNorm | 特征分组内归一化 | 否 | 小 batch CNN |
VLA 模型中几乎只用 LayerNorm / RMSNorm,因为:(1) 序列长度不固定(不同任务的 token 数不同);(2) batch size 可能较小(机器人数据集通常不大);(3) 需要在推理时对单条数据做归一化。
Q16: 什么是混合精度训练(Mixed Precision Training),为什么 VLA 训练要用它
【考察点】训练效率、显存优化
参考答案:
混合精度训练同时使用 FP16(或 BF16)和 FP32。前向和反向传播用低精度(BF16),权重更新和 loss scaling 用高精度(FP32)。好处:(1) 显存减半:BF16 占 2 字节 vs FP32 的 4 字节;(2) 计算加速:现代 GPU 的 BF16 Tensor Core 吞吐量是 FP32 的 2x;(3) 通信减少:分布式训练中梯度通信量减半。VLA 模型通常 7B+ 参数,BF16 几乎是标配。注意 BF16 比 FP16 更安全(动态范围更大,不容易溢出),OpenVLA 推理默认使用 torch.bfloat16。
Q17: 解释 Dropout 在 Transformer 中的位置和作用
【考察点】正则化、过拟合防止
参考答案: 在标准 Transformer 中,Dropout 出现在:(1) Attention 权重后(dropout on attention weights);(2) 每个子层输出后(与残差连接相加前);(3) 位置编码/嵌入后。训练时随机将部分神经元输出置零,防止过拟合。然而,在 VLA 微调阶段(如 OpenVLA LoRA 微调),由于数据量小、训练步数少,Dropout 通常被设为 0 或很小的值(0.1),因为 LoRA 本身已有正则化效果。在大规模预训练中,Dropout 率通常为 0.1。
Q18: 什么是 positional encoding 的外推问题,如何解决
【考察点】位置编码、长度泛化
参考答案: 外推问题指模型在训练时使用固定长度的位置编码(如 512 或 2048),推理时遇到更长序列就无法处理。Sinusoidal 编码没有外推能力(固定频率);可学习的位置编码受限于训练时的最大长度。解决方案:(1) RoPE:编码相对位置,理论上可外推到任意长度(但实际效果会衰减);(2) ALiBi:在 attention score 上加距离偏置,不修改输入嵌入,天然支持更长序列;(3) 位置插值(PI / NTK-aware):对预训练模型的位置编码做缩放,使其适应更长序列。对 VLA 而言,序列长度通常由图像 token 数决定,较为固定,外推问题不突出。
Q19: 解释 attention 中的 causal mask 和它的必要性
【考察点】自回归生成、GPT 架构
参考答案: Causal mask(因果掩码)是一个下三角矩阵,确保位置 $i$ 的 token 只能看到位置 $\leq i$ 的 token,不能看到未来的 token。这在自回归生成(GPT 风格)中是必需的,因为生成时只能利用已生成的 token。实现方式:在 attention score 矩阵中将 $j > i$ 的位置设为 $-\infty$,经过 softmax 后这些位置的权重变为 0。注意:在 BERT/encoder 风格中(双向 attention)不需要 causal mask;在 VLA 中,如果使用 GPT 风格的自回归生成(如 RT-2),需要 causal mask;如果使用 encoder-decoder 或纯 encoder 风格(如 OpenVLA 的 Llama 2 前缀),则在动作生成部分使用 causal mask。
Q20: 什么是 logits,它和 softmax 输出有什么区别
【考察点】模型输出理解
参考答案: Logits 是模型最后一层的原始输出值(未经归一化的分数)。对于分类任务,logits 是每个类别的得分向量 $z \in \mathbb{R}^C$。Softmax 将 logits 转换为概率分布:$p_i = e^{z_i} / \sum_j e^{z_j}$。关键区别:(1) Logits 可以是负数,softmax 输出在 $(0, 1)$ 之间且和为 1;(2) 训练时用 logits 计算 cross-entropy loss(内部会做 log_softmax),比先 softmax 再计算更数值稳定(避免 log(0) 问题);(3) 推理时才需要 softmax 得到概率。在 CLIP 中,logits 是 image-text 相似度矩阵除以 temperature 后的结果。
3. 机器人学基础¶
学习资源:
tutorials/02-action-representation/,02-action-representation/fk_ik_demo.py
3.1 正/逆运动学¶
Forward Kinematics (FK)¶
给定关节角度 $q = [q_1, q_2, ..., q_n]$,计算末端执行器位姿 $T_{ee} \in SE(3)$。
对于简单的 2-DOF 平面机械臂:
def forward_kinematics(q, l1=1.0, l2=1.0):
x = l1 * np.cos(q[0]) + l2 * np.cos(q[0] + q[1])
y = l1 * np.sin(q[0]) + l2 * np.sin(q[0] + q[1])
return np.array([x, y])
一般机械臂使用 DH 参数 或 旋量(screw theory) 表示,通过连乘齐次变换矩阵得到:
$$T_{ee} = T_{01}(q_1) \cdot T_{12}(q_2) \cdots T_{n-1,n}(q_n)$$
Inverse Kinematics (IK)¶
给定目标位姿 $T_{target}$,求解关节角度 $q$。
Jacobian 伪逆法(最常用):
$$\Delta q = J^+(q) \cdot \Delta x$$
其中 $J^+ = J^T(JJ^T)^{-1}$ 是伪逆矩阵,$J = \frac{\partial x}{\partial q}$ 是 Jacobian 矩阵。
阻尼最小二乘法(Damped Least Squares / Levenberg-Marquardt):
$$\Delta q = J^T(JJ^T + \lambda^2 I)^{-1} \cdot \Delta x$$
$\lambda > 0$ 防止在奇异点附近 Jacobian 矩阵病态(接近奇异时 $JJ^T$ 接近 0,加 $\lambda^2 I$ 使其可逆)。
3.2 动作表示¶
| 表示方式 | 维度示例 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| 关节空间 (Joint) | 7(7-DOF 臂) | 直接可执行,无 IK 误差 | 跨平台难迁移 | 单一机器人、VLA 微调 |
| 任务空间 (EE Pose) | 6 (xyz + rpy) / 7 (xyz + quat) | 语义清晰,跨平台迁移好 | 需要 IK 求解 | 通用策略、多机器人 |
| 增量 Delta | 6-7 | 鲁棒,不受初始位姿影响 | 误差累积,需要高频控制 | 实时闭环控制 |
| 速度/力矩 | 6-7 | 直接控制动力学 | 需要动力学模型 | 动态任务(抛掷、接触) |
详见 tutorials/02-action-representation/action_representation_comparison.py。
3.3 抓取基础¶
- 平行夹爪(Parallel Gripper):两个平行指面,结构简单,适合规则物体。常见于 Franka、UR 等机械臂。控制维度低(1-2 DOF),VLA 易建模。
- 拟人手 / 灵巧手(Dexterous Hand):多指多关节(如 Shadow Hand 24 DOF、LEAP Hand 16 DOF),能执行精细操作(转笔、系扣)。动作空间高维,VLA 建模难度大。
- 力封闭(Force Closure):如果一组接触力/力矩可以平衡任意方向的外部扰动,则称该抓取满足力封闭。是评估抓取稳定性的基本准则。
- 接触力学基础:接触力分为法向力(垂直于接触面)和摩擦力(平行于接触面),满足库仑摩擦锥约束。
3.4 机器人适配器 (Robot Adapter)¶
VLA 输出到具体机器人的适配:VLA 策略通常在归一化、统一的抽象动作空间中输出,而不同机器人有各自的物理接口、动作维度和控制频率。机器人适配器负责将 VLA 的抽象输出翻译为目标机器人可执行的指令。
- 动作维度匹配:将 VLA 统一输出(如 pad 到 32D 的向量)对齐到具体机器人的实际自由度。常见做法包括零填充 + 有效维度 mask(如 OCTO)或为不同机器人设计分头输出(如 π0 的 Action Expert)。
- 反归一化与坐标变换:VLA 输出通常归一化到 $[-1, 1]$,适配器需反归一化回物理量(关节角/末端位姿/速度),并在机器人基座坐标系与相机/世界坐标系之间做变换。
- 频率适配:VLA 推理频率(5-10Hz)通常远低于机器人控制频率(50-1000Hz),适配器结合 Action Chunking 与插值(如线性插值或 temporal ensemble)实现高频平滑控制。
- 安全约束:对输出做关节限位、速度/加速度 clipping、奇异点规避等安全处理,防止危险动作。
- 本体感知条件化:将机器人类型/配置(关节量、传感器布局)作为额外输入条件,使同一 VLA 主干能服务多平台。
3.5 机器人学面试题(15 题)¶
Q21: 解释 Jacobian 矩阵的物理含义
【考察点】运动学、微分关系
参考答案: Jacobian 矩阵 $J(q) \in \mathbb{R}^{m \times n}$ 描述了关节空间速度到任务空间速度的线性映射:$\dot{x} = J(q) \cdot \dot{q}$。其物理含义包括:(1) 列向量 $J_i$ 表示第 $i$ 个关节以单位速度运动时,末端执行器的速度和角速度;(2) 行向量 表示末端某个自由度的速度对所有关节速度的灵敏度;(3) 奇异点:当 $J$ 的行秩小于 $m$ 时,末端在某个方向上无法运动;(4) 可操作度 $w = \sqrt{\det(JJ^T)}$ 衡量操作灵活性。在 VLA 中,Jacobian 用于 IK 求解、动作空间转换、力/速度控制等。
Q22: IK 为什么会有多解问题,如何处理
【考察点】逆运动学、冗余自由度
参考答案: 多解问题的根本原因是三角函数的多值性。例如 2-DOF 平面臂到达同一目标点有"肘上"和"肘下"两种构型。对于 6+ DOF 的机械臂,冗余自由度使得解的数量更多(理论上无穷多)。处理方法:(1) 设定初始猜测:Jacobian 迭代法依赖初始值,好的初值可以收敛到期望构型;(2) 加关节限位约束:排除超出物理范围的解;(3) 加代价函数:如最小化关节运动 $\min |q - q_0|^2$,偏好"舒适"姿态;(4) 冗余优化:对冗余 DOF 施加额外目标(如避障、关节限位远离)。在 VLA 中,IK 多解问题意味着同一末端动作可能对应不同关节构型,需要在数据收集和训练时保持一致性。
Q23: 关节角 vs 末端位姿作为 VLA 动作空间各有什么优缺点
【考察点】动作表示选择
参考答案:
| 维度 | 关节角 | 末端位姿 |
|---|---|---|
| 维度 | 固定(如 7) | 固定(6 或 7) |
| 可执行性 | 直接发送给控制器 | 需要 IK 转换 |
| 跨平台迁移 | 差(不同臂的关节映射不同) | 好(同一任务空间描述) |
| 奇异点 | 避开奇异构型即可 | 需要额外处理(阻尼最小二乘) |
| 关节限位 | 自然包含在训练数据中 | IK 可能输出超限位解 |
| 训练数据质量 | 需要一致性 | IK 误差可能引入噪声 |
OpenVLA 输出 delta EE pose,然后通过 IK 转为关节角。RT-2 输出归一化的关节角。详见 tutorials/02-action-representation/ 中的对比分析。
Q24: Action Chunking 是什么,为什么需要它
【考察点】动作分块、推理频率优化
参考答案:
Action Chunking 是一次推理预测未来多步(K 步)动作序列,而非只预测单步动作。执行时通常执行前 K/2 步后重新推理。需要它的原因:(1) 降低推理延迟:VLA 模型(7B 参数)推理一次可能需要 50-200ms,无法达到 50Hz 的控制频率,Action Chunking 可以在 5-10Hz 推理频率下实现平滑控制;(2) 时序一致性:单步预测容易产生抖动,一次预测整个序列更平滑;(3) 隐式规划:模型在预测 K 步时,实际上在做短期的"规划"。ACT 首次明确提出 Action Chunking,OpenVLA 和 π0 都采用了类似思想。详见 04-glossary.md 中 Action Chunking 的定义。
Q25: 如何实现机器人的全身控制(Whole-Body Control)
【考察点】多子系统协同、动作空间设计
参考答案: 全身控制指统一协调机器人的多个运动子系统(如移动底盘、机械臂、末端执行器)以完成复杂任务。核心挑战是动作空间的高维度和子系统之间的协调。典型方案:(1) 统一动作空间:将各子系统的关节/自由度拼接为一个向量,由一个 VLA 统一输出(如 π0 的做法,将底盘、机械臂、末端执行器动作统一建模);(2) 分层控制:高层策略输出各子系统的目标(如末端位姿、夹爪开合),低层分别执行(臂用 IK、夹爪用抓取策略);(3) 解耦训练:先分别训练各子系统策略,再联合微调。π0 在移动操作任务中采用统一模型同时控制移动底盘、机械臂和末端执行器,证明了端到端全身控制的可行性。
Q26: 什么是奇异点(Singularity),在机器人操作中如何避免
【考察点】运动学、Jacobian 矩阵
参考答案: 奇异点是 Jacobian 矩阵行秩退化($\text{rank}(J) < m$)的构型,此时末端在某个方向上无法运动或需要无限大的关节速度。物理上表现为:(1) 机械臂完全伸展或完全折叠;(2) 多个关节轴线共面或平行。避免方法:(1) 阻尼最小二乘 IK:$J^T(JJ^T + \lambda^2 I)^{-1}$,在奇异点附近用阻尼项 $\lambda^2 I$ 保证数值稳定,代价是牺牲精度;(2) 关节限位约束:在 IK 优化中加入关节限位惩罚项,避免进入奇异构型;(3) 冗余优化:利用冗余 DOF 的零空间运动远离奇异点。在 VLA 中,如果用末端位姿作为动作空间,需要 IK solver 处理奇异点。
Q27: 解释 SE(3) 和它的李代数 se(3)
【考察点】位姿表示、李群李代数
参考答案: $SE(3)$ 是三维欧几里得空间的特殊欧几里得群,表示刚体位姿(3D 旋转 + 3D 平移)。元素为 $4 \times 4$ 齐次变换矩阵。$se(3)$ 是 $SE(3)$ 的李代数,是 $SE(3)$ 在单位元处的切空间,元素为 $4 \times 4$ 矩阵(上半部分是 $3 \times 3$ 反对称矩阵,最后一列是平移向量)。通过指数映射 $\exp: se(3) \to SE(3)$ 可以将李代数转换为群元素。在 VLA 中,SE(3) 用于表示末端位姿;Delta 动作可以用 $se(3)$ 中的元素表示(twist: 3D 线速度 + 3D 角速度),然后通过指数映射叠加到当前位姿上。
Q28: DH 参数是什么,为什么需要它
【考察点】运动学建模
参考答案: DH(Denavit-Hartenberg)参数是一种系统化的方法,用 4 个参数 $(a_i, \alpha_i, d_i, \theta_i)$ 描述相邻关节之间的坐标系变换关系。通过为每个关节定义 DH 参数,可以用连乘齐次变换矩阵计算 FK。标准 DH 和改进 DH(Modified DH / Craig's convention)是两种常见的约定,区别在于坐标系附着的位置不同。需要 DH 参数的原因是:机械臂的连杆几何关系需要精确数学描述,DH 参数提供了一种统一、系统化的框架。在 VLA 实际开发中,通常使用 MuJoCo/Isaac 的 XML/URDF 模型,DH 参数在底层已封装好。
Q29: 什么是工作空间(Workspace),它和 VLA 动作空间设计有什么关系
【考察点】运动学约束、动作空间设计
参考答案: 工作空间是机械臂末端执行器能到达的所有位姿的集合。分为:(1) 可达工作空间:至少一个姿态能到达的位置集合;(2) 灵活工作空间:所有姿态都能到达的位置集合。与 VLA 的关系:(1) VLA 输出的目标位姿必须在工作空间内,否则 IK 无解;(2) 训练数据中如果包含工作空间边缘的样本,VLA 可能学习到不一致的策略(边缘处 Jacobian 条件数大);(3) 不同臂的工作空间不同,跨平台 VLA 需要归一化到统一空间或使用相对坐标。
Q30: 四元数(Quaternion)相比欧拉角表示旋转有什么优势
【考察点】旋转表示
参考答案:
| 对比维度 | 欧拉角 (RPY) | 四元数 (Quat) |
|---|---|---|
| 维度 | 3 | 4(归一化约束) |
| 万向锁 | 有(pitch = +-90度时) | 无 |
| 插值 | 不平滑 | SLERP 平滑插值 |
| 连续性 | 不连续(angle wrap) | 连续(除全局符号) |
| 计算复杂度 | 低 | 稍高 |
四元数 $q = [w, x, y, z]$,满足 $|q| = 1$,表示绕单位轴 $\hat{n}$ 旋转角度 $\theta$:$q = [\cos(\theta/2), \hat{n}\sin(\theta/2)]$。VLA 中常使用四元数表示末端姿态的旋转部分,避免万向锁问题。
Q31: 什么是力控制,在什么场景下需要
【考察点】接触力学、控制策略
参考答案: 力控制是在任务空间中直接控制末端与环境的接触力/力矩,而非位置。需要力控制的场景:(1) 接触任务:打磨、擦拭、装配,需要控制接触力的大小;(2) 柔性操作:抓取易碎物体(鸡蛋、纸杯);(3) 人机交互:安全的人机协作需要力/力矩限制。实现方式:导纳控制(admittance control)、阻抗控制(impedance control)、直接力控制。在 VLA 当前的主流方法中,力控制较少被端到端学习,通常是 VLA 输出位置/速度目标,由底层力控制器执行。π0 在精细操作中通过高频位置控制间接实现力调节。
Q32: 解释 PID 控制在机器人中的基本原理
【考察点】经典控制、底层控制
参考答案: PID 控制器的输出 $u(t) = K_p e(t) + K_i \int_0^t e(\tau)d\tau + K_d \frac{de(t)}{dt}$,其中 $e(t)$ 是误差(目标值 - 当前值)。$K_p$(比例):按误差大小输出控制量,误差大则输出大;$K_i$(积分):消除稳态误差,但对历史误差累积敏感;$K_d$(微分):预测误差变化趋势,提供阻尼。在机器人中,PID 通常用于关节层面的位置/速度跟踪控制。VLA 输出的动作通常作为 PID 控制器的目标值,由底层控制器执行。理解 PID 有助于理解 VLA 输出如何转化为实际电机命令。
Q33: 什么是轨迹优化(Trajectory Optimization),和 VLA 的关系是什么
【考察点】运动规划、优化方法
参考答案: 轨迹优化是在给定初始状态、目标状态和约束条件下,求解最优轨迹的方法。常见方法:(1) 直接法(如 iTASC, CHOMP, TrajOpt):将轨迹离散化,用非线性优化求解;(2) 间接法:基于庞特里亚金最大值原理,求解 Hamilton-Jacobi-Bellman 方程。与 VLA 的关系:轨迹优化是经典方法(model-based),VLA 是学习方法(data-driven)。两者可以结合:VLA 生成初始轨迹,轨迹优化做精修(smoothing + constraint satisfaction)。在分层方案中,高层 VLA/LLM 做任务规划,低层用轨迹优化生成平滑可执行轨迹。
Q34: 机械臂的安全约束有哪些,在 VLA 部署中如何保证
【考察点】安全部署、工程实践
参考答案: 安全约束包括:(1) 关节限位:每个关节有物理角度范围;(2) 速度/加速度限制:防止运动过快导致危险;(3) 力/力矩限制:接触力上限(人机协作通常 < 150N);(4) 工作空间限制:用虚拟围栏限制末端活动范围;(5) 碰撞检测:基于点云或距离场的实时碰撞检测。VLA 部署中保证安全的方法:(1) 底层安全控制器(Safety Filter):VLA 输出经过安全过滤器后才执行,超出限制的动作被截断或缩放;(2) 仿真中充分测试边界情况;(3) 渐进式部署:先低速、限空间,逐步放开。
Q35: 解释点云和深度图的区别,在 VLA 输入中各有什么优缺点
【考察点】3D 感知、输入模态
参考答案:
| 对比维度 | 点云 | 深度图 |
|---|---|---|
| 数据格式 | (N, 3) 或 (N, 3+C) | (H, W) 矩阵 |
| 信息量 | 3D 几何 + 可选颜色/法线 | 2.5D(z = f(u,v)) |
| 视角依赖 | 无(可在任意坐标系下表示) | 有(相机视角) |
| 与 ViT 兼容性 | 需要额外处理(PointNet/Point Transformer) | 可直接作为图像输入 |
| 传感器 | LiDAR、RGB-D 相机 | RGB-D 相机、ToF |
当前主流 VLA(RT-2、OpenVLA、π0)主要使用 RGB 图像作为输入,因为可以直接利用强大的预训练 ViT。点云作为辅助输入(如 3D 目标位置)在部分场景中使用。Octo 支持点云输入。
4. VLA 核心技术(重点考察)¶
学习资源:
02-key-papers.md,01-what-is-vla.md,tutorials/03-simple-vla/,tutorials/04-fine-tuning/
4.1 VLA 架构演进¶
| 模型 | 机构 | 年份 | 参数量 | 视觉编码器 | 语言主干 | 动作生成 | 数据规模 |
|---|---|---|---|---|---|---|---|
| RT-1 | 2022 | - | EfficientNet-B3 + TokenLearner | FiLM 条件化 | 256-bin 离散 token | 130k 轨迹 | |
| RT-2 | 2023 | 55B | PaLI-X 内置 ViT | PaLI-X / PaLM-E | 离散 token(自回归) | OXE + 网页数据 | |
| OpenVLA | Stanford/Berkeley | 2024 | 7B | DINOv2 + SigLIP | Llama 2 | 256-bin 离散 token (vanilla) / 连续回归 (OFT) | OXE 970k 轨迹 |
| Octo | Berkeley/Stanford | 2024 | 27M-93M | ViT (预训练) | Token 序列 | 离散/连续可选 | OXE + 自建 |
| π0 | Physical Intelligence | 2024 | 3B | PaliGemma ViT | PaliGemma | Flow Matching | 混合多任务 |
4.2 动作生成方法对比¶
| 方法 | 代表模型 | 原理 | 优点 | 缺点 |
|---|---|---|---|---|
| 离散 Token | RT-2 | 动作量化为 bin,自回归生成 | 可复用 LLM 推理优化(KV cache);训练稳定 | 量化误差;bin 数影响精度-效率权衡 |
| 连续回归 | OpenVLA-OFT | MLP 直接输出连续动作 | 无量化误差;推理快(单次前向) | 单峰分布假设,多模态场景表现差 |
| 扩散/流匹配 | π0, SmolVLA, Diffusion Policy | 从噪声逐步去噪/流动到动作 | 表示多峰分布;动作平滑;适合精细操作 | 推理需要多步迭代;延迟较高 |
| CVAE | ACT | 条件 VAE 采样动作 chunk | 多样性好 | 训练不稳定;重建-多样性 trade-off |
4.3 VLA 训练范式¶
| 范式 | 流程 | 优点 | 缺点 |
|---|---|---|---|
| 行为克隆 (BC) | 专家演示 → 监督学习 | 简单直接;数据效率高 | 受限于演示质量;无法超越演示者 |
| 预训练 + 微调 | 大规模数据预训练 → 目标任务微调 | 泛化能力强;少样本适配 | 预训练成本高;需要统一数据格式 |
| RL Fine-tuning | BC 预训练 → RL 优化(PPO/SAC) | 可超越演示者;探索新策略 | 奖励函数设计难;训练不稳定;仿真依赖 |
4.4 VLA 6 大技术路线¶
基于最新综述,当前 VLA 技术路线可分为以下 6 类:
路线 1: RL/IL 方案 - 代表:ACT, RT-1, BC-Z - 特点:直接用强化学习或模仿学习训练端到端策略,不依赖预训练大模型 - 优势:训练简单,数据需求相对低 - 局限:泛化能力弱,需要大量特定任务数据
路线 2: 预训练 LLM/VLM 方案 - 代表:RT-2, OpenVLA - 特点:在预训练 VLM 基础上微调,将动作输出能力"嫁接"到语义模型上 - 优势:继承大模型的语义理解和推理能力 - 局限:动作生成的表达能力受限于 LLM 架构(单峰 vs 多峰)
路线 3: 扩散模型方案 - 代表:Diffusion Policy, RDT-1B - 特点:用扩散模型生成动作,天然支持多峰分布 - 优势:动作质量高、平滑;可表示复杂的多模态策略 - 局限:推理速度慢(多步去噪);训练收敛慢
路线 4: LLM + 扩散方案 - 代表:Octo, π0 - 特点:预训练 VLM 提供语义理解 + 扩散/流匹配生成动作 - 优势:结合两者的优势——语义理解 + 多峰动作生成 - 局限:架构复杂;训练成本高
路线 5: 视频生成 + IK 方案 - 代表:UniPiRo, GR-2 - 特点:将动作预测转化为视频生成问题,预测未来帧,再用 IK 转为动作 - 优势:利用视频预测模型强大的时序建模能力 - 局限:视频到动作的转换引入额外误差;计算量大
路线 6: 分层端到端方案 - 代表:SayCan, Inner Monologue, Code as Policies - 特点:高层 LLM 做任务规划(分解为子任务),低层 VLA/BC 执行具体动作 - 优势:可处理长程复杂任务;模块化易调试 - 局限:高层规划的错误会级联到低层;需要预定义技能库
4.5 VLA 核心技术面试题(25 题)¶
Q36: OpenVLA 和 RT-2 的核心区别是什么
【考察点】VLA 架构对比、设计选择
参考答案:
| 对比维度 | OpenVLA | RT-2 |
|---|---|---|
| 参数量 | 7B(开源) | 55B(闭源) |
| 视觉编码器 | DINOv2 + SigLIP(双塔) | PaLI-X 内置 ViT |
| 语言主干 | Llama 2 | PaLI-X / PaLM-E |
| 动作输出 | 256-bin 离散 token (vanilla) / 连续回归 (OFT) | 离散 token 自回归 |
| 训练数据 | OXE 970k | OXE + 网页数据 |
| 微调方式 | LoRA(rank=32) | 全参数微调 |
| 推理速度 | vanilla 较慢(自回归);OFT 较快(单次前向) | 较慢(自回归生成) |
| 开源 | 完全开源 | 仅推理参考 |
核心设计差异在于模型规模和微调策略:vanilla OpenVLA 与 RT-2 都使用 256-bin 离散 token,但 OpenVLA 用 7B Llama 2 + LoRA 微调(rank=32),大幅降低了适配成本;RT-2 依赖 55B PaLI-X 全参数微调。OpenVLA-OFT 进一步改为连续回归,支持 action chunking 和更高频率。
Q37: 为什么 π0 使用 Flow Matching 而不是 Diffusion
【考察点】生成模型选择、Flow Matching vs Diffusion
参考答案: Flow Matching 和 Diffusion 都是从噪声到数据的生成过程,但关键区别在于:(1) 速度:Flow Matching 定义了一个从标准高斯到目标分布的确定性常微分方程(ODE)路径,可以用单步或少量步求解(π0 用 8 步);DDPM 需要更多步(50-1000 步)来保证样本质量;(2) 训练稳定性:Flow Matching 的训练目标是预测速度场 $v_t$,目标简单明确;Diffusion 需要预测噪声 $\epsilon$ 或 $x_0$,且噪声调度 $\beta_t$ 的选择影响训练稳定性;(3) 高频控制:π0 需要 50Hz 的控制频率,Flow Matching 的少步生成满足这一需求。本质上,Flow Matching 是 Diffusion 的一种简化——用直线路径替代弯曲的 SDE 路径,在保持生成质量的同时大幅提升推理速度。
Q38: VLA 中动作离散化的优缺点
【考察点】动作表示、RT-2 设计
参考答案:
优点: - 可直接复用 LLM 的自回归框架和推理优化(KV cache、speculative decoding) - 训练稳定(cross-entropy loss 梯度性质好) - 与语言 token 统一格式,实现真正的"语言-动作"联合建模
缺点: - 量化误差:连续值映射到有限 bin 会损失精度 - bin 数的选择是 trade-off:256 bins 精度有限但推理快,1024 bins 精度高但序列更长 - 动作空间被人为离散化,可能不匹配连续控制的需求 - 不适合需要精细连续控制的任务(如力控制)
OpenVLA-OFT 实验表明,连续回归在大多数操作任务上与离散化性能相当甚至更好,且推理更快。
Q39: LoRA 微调中 rank 的选择对效果有什么影响
【考察点】LoRA 超参、VLA 微调实践
参考答案: LoRA rank $r$ 决定了低秩适配器的容量。影响规律:(1) 太小(r=1-4):表达能力不足,可能欠拟合,尤其当任务与预训练分布差异大时;(2) 适中(r=8-32):通常在性能和效率之间取得好的平衡。OpenVLA 使用 $r=32$;(3) 太大(r=64-256):接近全参数微调的效果,但参数量增加,过拟合风险增大,失去 LoRA 的参数效率优势。OpenVLA 论文中的实验对比表明,$r=32$ 在多数迁移任务上接近全参数微调的效果,而可训练参数量仅为全参数的 0.1%。实际选择时,建议从 $r=16$ 开始,如果在目标任务上欠拟合再增大到 32 或 64。
Q40: 如何在 LIBERO 上评估 VLA 模型
【考察点】VLA 评估、基准测试
参考答案: LIBERO 是一个单臂桌面操作基准,包含 130 个语言条件化任务,分为 4 个 suite:(1) LIBERO-Spatial(空间推理);(2) LIBERO-Object(物体理解);(3) LIBERO-Long(长程任务);(4) LIBERO-10(10 任务联合评估)。评估流程: 1. 准备 LIBERO 环境和数据集 2. 在训练集任务上微调 VLA(或直接用预训练模型 zero-shot 评估) 3. 在测试集任务上运行闭环评估(每个任务 50 次 episode) 4. 记录成功率(task success rate)
本项目提供了评估脚本 tutorials/04-fine-tuning/evaluate_libero.py。关键指标是任务完成率(success rate),需要注意评估时使用与训练不同的初始状态分布来测试泛化能力。
Q41: VLA 推理延迟的瓶颈在哪,如何优化
【考察点】推理优化、部署
参考答案: VLA 推理延迟的瓶颈按流水线阶段分析:(1) 视觉编码:ViT 前向传播,对于高分辨率图像较慢。优化:降低输入分辨率、使用更小的 ViT、缓存视觉特征(场景变化不大时);(2) 语言处理:Tokenize + embedding,通常不是瓶颈;(3) Transformer 主干:自回归生成的逐步推理(RT-2, vanilla OpenVLA)或单次前向(OpenVLA-OFT)。优化:KV cache、Flash Attention、模型量化(INT8/INT4)、投机解码(speculative decoding);(4) 动作生成头:MLP 回归(OpenVLA-OFT)很快;flow matching(π0, SmolVLA)需要少量积分步(π0 用 8 步),比标准扩散更快。优化:减少积分步数、蒸馏到单步。端到端优化策略:TensorRT 编译、CUDA Graph、批处理。
Q42: 什么是 unnorm_key,为什么不同数据集需要不同的反归一化参数
【考察点】数据预处理、OpenVLA 实践
参考答案:
VLA 模型在训练时通常将动作归一化到 $[-1, 1]$ 或标准正态分布,以稳定训练。推理时需要将模型输出反归一化回原始动作空间。unnorm_key 是一个标识符,指向预计算的反归一化参数(均值和标准差),通常存储在配置文件中。不同数据集的动动作空间不同(维度、范围、单位),因此需要不同的统计量。例如:
- "bridge" 数据集:7D delta EE pose,单位为米/弧度
- "franka" 数据集:7D 关节角,范围 $[-\pi, \pi]$
如果用错误的 unnorm_key,模型输出会被映射到错误的范围,导致机器人动作异常。详见 04-glossary.md 中 Unnormalization 的定义和 tutorials/03-simple-vla/openvla_inference_tutorial.py 中的代码示例。
Q43: OpenVLA 为什么同时使用 DINOv2 和 SigLIP 作为视觉编码器
【考察点】多视觉编码器设计、特征互补
参考答案: DINOv2 和 SigLIP 提供互补的视觉特征:
- DINOv2(自监督训练):擅长空间/几何理解——物体边界检测、深度估计、空间关系推理。通过 iBOT 掩码预测学到强大的局部特征。
- SigLIP(图像-文本对比学习):擅长语义/语言对齐——物体类别识别、属性理解。通过 sigmoid loss 在图像-文本配对上训练。
在 VLA 中,两者互补意味着:(1) DINOv2 帮助模型理解"物体在哪里、空间关系如何"——这对操作任务至关重要;(2) SigLIP 帮助模型理解"物体是什么"——这对语言指令的泛化至关重要。两者特征通过投影层拼接后输入 Llama 2 主干。实验表明,双编码器比单独使用任一编码器效果更好。
Q44: Action Expert 设计(π0)的好处是什么
【考察点】π0 架构、参数效率
参考答案: Action Expert 是 π0 的核心设计创新。它将模型分为两部分:(1) 预训练 VLM 主干(PaliGemma):冻结参数,负责视觉理解和语言推理;(2) Action Expert 模块:可训练的小型 Transformer,负责生成动作。
好处: - 保留语义能力:冻结 VLM 主干,不会因为动作训练而遗忘预训练知识(类似 co-training 但更彻底) - 参数效率:只训练 Action Expert(远小于全模型),降低训练成本 - 多机器人适配:不同机器人可以共享同一个 VLM 主干,只训练不同的 Action Expert - 训练稳定性:VLM 主干已经在大规模数据上收敛,Action Expert 可以从稳定的特征开始训练 - 支持高频控制:Action Expert 用 Flow Matching 生成动作,独立于 VLM 的自回归解码
Q45: 如何处理 VLA 的 sim2real gap
【考察点】仿真到真实迁移
参考答案: Sim2Real gap 的来源:仿真中的物理参数(摩擦、质量、惯性)与真实世界不完全一致;渲染的图像与真实相机有差异;仿真的传感器噪声模型不够准确。处理方法:(1) 域随机化(Domain Randomization):在仿真中随机化物理参数、纹理、光照、相机噪声,使策略对真实世界的不确定性鲁棒;(2) 域适应(Domain Adaptation):用真实世界少量数据微调仿真训练的策略;(3) 真实数据微调:OpenVLA 的做法——在 OXE 数据预训练后,用目标机器人的少量真实数据 LoRA 微调;(4) 系统辨识:精确测量真实机器人的物理参数,使仿真更贴近真实;(5) 鲁棒控制:在策略输出后加鲁棒控制器(如阻抗控制)吸收残余的 sim2real 差异。
Q46: VLA 在长程任务上的局限性和解决方案
【考察点】长程任务、规划
参考答案: 局限性: - VLA 本质上是从观察到动作的映射函数(reactive policy),缺乏显式规划能力 - 误差累积:每步的小误差在长序列中累积,导致任务失败 - 感知漂移:长时间操作后,相机视角变化可能导致模型"迷失" - 训练数据中长程轨迹稀缺
解决方案: - 分层方案:高层 LLM 做任务规划("pick up cup → pour water → place cup"),低层 VLA 执行每个子任务 - 目标条件化:提供目标图像或目标描述,VLA 不需要规划整条路径 - 记忆/历史窗口:增大历史帧输入(如 RT-1 用 6 帧),增加时序上下文 - 重新规划:周期性调用高层规划器,根据当前状态调整计划 - 课程学习:从短任务开始训练,逐步增加任务长度
Q47: RT-1 的 TokenLearner 是如何工作的,为什么需要它
【考察点】RT-1 架构、视觉 token 压缩
参考答案: TokenLearner 将大量视觉 token 压缩为少量关键 token。工作原理:(1) 输入 $N$ 个视觉 token(EfficientNet-B3 输出 6k+ token);(2) 对每个空间位置,用一组可学习的权重(attention score)聚合所有 token 的信息;(3) 输出 $M \ll N$ 个压缩后的 token(RT-1 压缩到 81 个)。需要它的原因:标准 Vision Transformer 的 self-attention 计算量为 $O(N^2 d)$,当 $N$ 很大(如高分辨率图像)时计算开销巨大。TokenLearner 通过学习性的压缩,在保留关键信息的同时大幅降低后续 Transformer 的计算量。这种"先压缩再处理"的思路在后续模型中也有体现(如 Q-Former)。
Q48: 什么是 Open X-Embodiment (OXE),它的意义是什么
【考察点】数据集、VLA 预训练
参考答案: Open X-Embodiment 是目前最大的开源机器人操作数据集,整合了 22 种不同机器人平台的 100 万+ 条操作轨迹,涵盖单臂操作、双臂操作、移动操作等多种任务类型。每条轨迹包含:RGB 图像、机器人状态、动作序列、语言指令。其意义在于:(1) 规模:首次达到百万级规模,使得 VLA 的预训练成为可能;(2) 多样性:跨平台、跨任务、跨环境的数据使模型学到更通用的策略;(3) 标准化:统一了不同数据集的格式(RLDS),降低了多数据集联合训练的工程难度;(4) 开放性:社区可在 OXE 上训练和评估新的 VLA 模型。OpenVLA 和 Octo 都在 OXE 上预训练。
Q49: Diffusion Policy 为什么能表示多峰分布
【考察点】扩散模型、多模态策略
参考答案: 多峰分布指一个观察对应多个合理动作(例如从左侧或右侧绕过障碍物都行)。传统方法(如 Gaussian、MLP 回归)只能输出单一模式(单峰),扩散模型通过迭代去噪过程自然地表示多峰分布。原理:训练时,真实动作被加噪为接近标准高斯的分布(多峰被"抹平"为单峰高斯);推理时,从随机噪声开始去噪,不同的初始噪声会收敛到不同的模态(模式)。数学上,扩散模型学习的是条件概率 $p(a|o)$ 的 score function $\nabla_a \log p(a|o)$,它可以指向多个方向(对应多个模式)。而 MLP 回归学习的是 $E[a|o]$,本质上是所有模式的平均(可能不是任何一个有效动作)。
Q50: OpenVLA 的训练流程是怎样的
【考察点】VLA 训练、OpenVLA 实践
参考答案: OpenVLA 的训练分两个阶段:
阶段 1:预训练 - 数据:Open X-Embodiment 970k 条轨迹 - 视觉编码器:冻结的 DINOv2 + SigLIP - 语言主干:初始化为 Llama 2 权重 - 策略头:新初始化的 MLP - 损失:MSE Loss(归一化动作) - 训练设置:BF16,AdamW,cosine LR schedule,batch size 较大 - 训练成本:约 $30k
阶段 2:微调(目标机器人适配) - 数据:目标机器人的 5k-10k 条轨迹 - 冻结视觉编码器 - 用 LoRA(rank=32)微调语言主干的 QKV 投影 - 策略头重新训练或微调 - 只需 5k-10k 步即可适配新机器人
详见 tutorials/04-fine-tuning/finetune_libero.py 和 tutorials/04-fine-tuning/train_custom_data.py。
Q51: VLA 模型的输入通常包含哪些信息
【考察点】VLA 输入设计
参考答案: 典型 VLA 的输入包括: - 视觉观察:一张或多张 RGB 图像(第三人称相机 + 腕部相机) - 语言指令:自然语言描述的任务目标(如"pick up the red cup") - 本体感知状态(可选):关节角度、关节速度、力/力矩传感器读数 - 历史帧(可选):过去 K 帧的视觉观察,提供时序上下文 - 目标图像/描述(可选):Goal conditioning,提供目标状态
RT-1 使用 6 帧历史图像 + FiLM 条件化语言;OpenVLA 使用单张图像 + 语言指令;π0 使用图像 + 语言指令 + 灵巧手本体感知。
Q52: 什么是 temporal ensemble,它在扩散策略中有什么作用
【考察点】Diffusion Policy 细节、推理优化
参考答案: Temporal ensemble 是 Diffusion Policy 中的一种推理时技术。核心思想:在时间步 $t$,不是只使用当前时刻的扩散策略输出,而是对过去多个时刻的扩散策略输出做加权平均。具体来说,当策略以 $T_a$ 步的 chunk 输出动作序列时,在滑动窗口中重叠的部分取多个预测值的加权平均。作用:(1) 平滑性:减少动作抖动,生成更平滑的轨迹;(2) 一致性:重叠区域的多次预测取平均,降低单次预测的方差;(3) 鲁棒性:即使单次预测有偏差,平均后仍可能得到合理动作。与 Action Chunking 结合使用效果最好。
Q53: 解释 VLA 中"语言条件化"的几种实现方式
【考察点】语言指令融合
参考答案: (1) FiLM (Feature-wise Linear Modulation):RT-1 使用。用语言嵌入生成仿射变换参数 $\gamma, \beta$,对视觉特征做变换 $y = \gamma \odot x + \beta$。简单高效,但表达能力有限。 (2) 拼接为 token 序列:RT-2, OpenVLA 使用。将文本 token 和视觉 token 拼接为统一序列,输入 Transformer。通过 self-attention 自然融合多模态信息。表达能力最强。 (3) 交叉注意力(Cross-Attention):图像特征作为 Key/Value,语言特征作为 Query(或反之),通过交叉注意力融合。Octo 的 Read-Write Attention 是变体。 (4) 独立编码 + 投影融合:分别编码视觉和语言,在全连接层或注意力层融合。
当前主流(RT-2、OpenVLA、π0)都采用方式 (2),因为 Transformer 的自注意力机制天然适合多模态融合。
Q54: VLA 模型如何处理不同动作维度的机器人
【考察点】跨平台 VLA、动作空间统一
参考答案: 不同机器人的动作维度不同(如 Franka 7D、UR5e 6D、Shadow Hand 24D)。处理方式: - 统一动作维度:OCTO 将所有动作 pad 到最大维度(如 32D),不足的部分用 0 填充,并添加 mask 标记有效维度。 - 分头输出:为不同类型的机器人设计不同的策略头,共享视觉-语言主干。π0 的 Action Expert 本质上是这种思路。 - 归一化到统一空间:将所有机器人的动作归一化到 $[-1, 1]$,但不同维度的物理含义不同,只是数值范围统一。 - 本体感知条件化:将机器人类型/配置作为额外输入条件,模型根据条件输出对应维度的动作。
Open X-Embodiment 的统一数据格式(RLDS)是跨平台 VLA 的数据基础。
Q55: 什么是 CVAE,ACT 中如何使用它
【考察点】ACT 架构、多模态动作
参考答案: CVAE(Conditional Variational Autoencoder,条件变分自编码器)在 ACT 中的作用是生成多样化的动作 chunk。架构:编码器将专家演示的动作 chunk 编码为隐变量 $z$ 的分布 $q(z|s, a)$;解码器以观察 $s$ 和采样的 $z$ 为条件,生成动作 chunk $a = \text{Dec}(s, z)$。训练时,使用 KL 散度正则化 $q(z|s,a)$ 接近先验 $p(z)$,同时最小化重建损失。推理时,从先验 $p(z)$ 采样 $z$,解码器生成多样化的动作。CVAE 的好处:即使专家演示中同一观察对应多种合理动作(多模态),CVAE 也能通过不同的 $z$ 采样覆盖多种模式,而非像行为克隆那样只能输出平均值。
Q56: VLA 中的数据增强策略有哪些
【考察点】数据增强、训练技巧
参考答案: VLA 中常用的数据增强: - 图像增强:随机裁剪、颜色抖动、高斯模糊、随机擦除。注意不使用水平翻转(操作任务中左右语义不同)。 - 动作增强:添加小幅高斯噪声(模拟执行噪声)、时间抖动。 - 语言指令增强:同义词替换、指令改写("pick up the cup" → "grasp the cup")。提升语言泛化能力。 - 观察增强:随机遮挡部分图像区域(类似 CutMix)、添加传感器噪声。 - 时序增强:随机选择起始帧(从轨迹的不同位置开始)、子采样帧率。
注意:VLA 的增强比纯视觉任务更保守,因为需要保持图像-动作-语言三者的对齐关系。错误的增强可能破坏这种对齐。
Q57: VLA 的失败模式有哪些,如何诊断
【考察点】实践能力、调试经验
参考答案: 常见失败模式及诊断方法:
| 失败模式 | 可能原因 | 诊断方法 |
|---|---|---|
| 感知错误(抓错物体) | 视觉编码器问题 | 可视化 attention map;测试 VLM 零样本识别 |
| 动作抖动 | 推理频率不够;没有 Action Chunking | 增加历史帧或 chunk size;降低控制频率 |
| 到达目标附近但无法完成 | 动作空间分辨率不够(离散化太粗) | 增加 bin 数或改用连续回归 |
| 泛化到新物体失败 | 训练数据多样性不足 | 增加数据多样性;使用开放词汇视觉编码器 |
| 训练 loss 不下降 | 学习率不当;数据预处理错误 | 检查 unnorm_key;可视化训练数据 |
| 过拟合 | 数据量太小;LoRA rank 太大 | 减小 rank;增加正则化;数据增强 |
Q58: 如何评估一个 VLA 模型的好坏,除了成功率还有什么指标
【考察点】评估方法
参考答案: 除了任务成功率(Success Rate),常用评估指标包括: - 平均完成时间:成功 episode 的平均步数,衡量策略效率 - 路径长度:末端执行器的运动路径总长度 - 平滑度:动作序列的 jerk(加加速度),衡量动作质量 - 零样本泛化率:在训练时未见的任务/物体上的成功率 - 跨平台迁移性能:在一个机器人上训练,在另一个机器人上的表现 - 推理延迟:单步推理时间(ms),影响实际部署 - 数据效率:达到目标性能所需的最少微调数据量 - 鲁棒性:在扰动(推、光照变化、物体位置偏移)下的成功率
Q59: VLA 和传统机器人 Pipeline(感知→规划→控制)的优缺点对比
【考察点】端到端 vs 模块化
参考答案:
| 对比维度 | VLA(端到端) | 传统 Pipeline(模块化) |
|---|---|---|
| 系统复杂度 | 单一模型 | 多模块串联 |
| 调试难度 | 黑盒,难定位问题 | 每个模块可独立调试 |
| 泛化能力 | 强(通过大规模预训练) | 弱(每个模块需要手动设计) |
| 数据需求 | 大量演示数据 | 显式建模,数据需求低 |
| 安全性 | 难保证(神经网络不可解释) | 可形式化验证 |
| 精度 | 粗粒度任务好,精细任务有限 | 每个模块可以做到很高精度 |
| 部署 | 推理延迟是挑战 | 实时性好 |
趋势:混合方案——VLA 做感知和高层决策,传统方法做底层安全控制。
Q60: 解释为什么 VLA 需要在大规模数据上预训练,而不能直接在小数据集上训练
【考察点】预训练必要性、数据规模
参考答案: (1) 泛化需要多样性:VLA 需要处理多种物体、场景、任务,小数据集无法覆盖这种多样性;(2) 视觉-语言对齐需要规模:CLIP/DINOv2 的训练分别用了 400M 和 142M 图像,VLA 继承了对齐能力但如果只在少量机器人数据上训练,会遗忘这种能力(灾难性遗忘);(3) OpenVLA 的实验证据:仅在 bridge 数据集(~76k 轨迹)上训练的 VLA,在新任务/新环境上的成功率远低于在 OXE(970k 轨迹)上预训练的版本;(4) 大模型的涌现能力:大模型在足够大的数据规模上训练后,展现出小模型没有的能力(如推理、泛化),VLA 也遵循类似规律。
5. Sim-to-Real 迁移¶
5.1 域随机化(Domain Randomization)¶
原理:在仿真训练中,随机化各种参数(物理、视觉、传感器),使策略学到对参数变化不敏感的鲁棒策略。
常见做法: - 视觉随机化:随机光照(方向、强度、颜色)、随机纹理、随机背景、添加噪声/模糊 - 物理随机化:摩擦系数、质量、惯性、阻尼、关节阻尼 - 传感器随机化:相机内参(焦距、畸变)、噪声模型、延迟 - 动作随机化:在动作上添加执行噪声,模拟真实执行器的不精确性
Tobin et al. (2017) 的经典工作证明,足够强的域随机化可以使仿真训练的策略直接在真实世界中工作(零样本迁移)。
5.2 域适应(Domain Adaptation)¶
原理:利用真实世界少量数据,缩小仿真和真实之间的分布差异。
方法: - 特征对齐:用对抗训练(GAN)或 MMD 最小化仿真和真实特征的分布差异 - 自监督适应:在真实数据上做自监督预训练(如时间一致性、对比学习),再微调策略 - 微调:用少量真实数据微调仿真预训练的策略(OpenVLA 的 LoRA 微调本质上也是一种域适应)
5.3 实际部署挑战¶
| 挑战 | 描述 | 缓解方法 |
|---|---|---|
| 传感器噪声 | 真实相机有噪声、运动模糊 | 训练时添加对应噪声;图像去噪预处理 |
| 执行延迟 | 真实控制有 10-50ms 延迟 | Action Chunking 补偿延迟;延迟感知训练 |
| 安全约束 | 真实环境中不能犯错 | 安全过滤器;渐进式部署(限速→正常速度) |
| 光照变化 | 真实环境光照多变 | 域随机化光照;使用 DINOv2(对光照鲁棒) |
| 物体多样性 | 真实物体形状、材质各异 | 开放词汇视觉编码器;数据增强 |
| 标定误差 | 手眼标定、相机标定不准确 | 端到端学习减少对标定的依赖(但仍需合理初值) |
5.4 Sim-to-Real 面试题(10 题)¶
Q61: 域随机化的强度如何选择
【考察点】域随机化实践
参考答案: 域随机化的强度需要仔细调参,过弱和过强都有问题。过弱:策略在仿真中表现好,但真实世界失败(sim2real gap 太大)。过强:随机化范围太大导致任务本身变得不可能完成,策略学不到有效行为(训练不收敛)。经验原则:(1) 从保守范围开始,逐步增大;(2) 监控仿真中的训练成功率,确保不低于某个阈值(如 70%);(3) 优先随机化对真实世界影响大但仿真和真实差异大的参数(如光照、纹理);(4) 不需要随机化对结果影响小的参数。实践中常用"课程式域随机化":训练初期用小范围,后期增大。
Q62: 什么是数字孪生(Digital Twin),和普通仿真有什么区别
【考察点】仿真技术、工程实践
参考答案: 数字孪生是物理系统的精确虚拟副本,不仅建模几何和物理,还包括:(1) 精确的物理参数:通过系统辨识从真实系统测量得到(而非手动设置);(2) 实时同步:数字孪生的状态与真实系统实时同步(传感器数据驱动);(3) 全生命周期:从设计、部署到维护的全过程。与普通仿真的区别:普通仿真用于训练和测试,精度要求相对低;数字孪生追求高保真度,用于监控、预测和维护。在 VLA 领域,数字孪生可以帮助缩小 sim2real gap,但构建和维护成本高。
Q63: 如何验证 sim2real 迁移的效果
【考察点】评估方法
参考答案: 验证方法:(1) 仿真内测试:在仿真中使用与训练时不同的随机种子/参数范围测试,评估策略的鲁棒性;(2) 真实世界零样本测试:直接将仿真训练的策略部署到真实机器人,不做任何微调,测量成功率;(3) 真实世界微调后测试:用少量真实数据微调后测试,对比零样本结果,衡量 sim2real gap 的大小;(4) 分布距离度量:计算仿真和真实观察的分布距离(如 FID、KDE),定量衡量域差异。实际工作中,通常会先在仿真中充分测试,再逐步过渡到真实世界。
Q64: 为什么 MuJoCo 被广泛用于机器人学习研究
【考察点】仿真器选择
参考答案: MuJoCo(Multi-Joint dynamics with Contact)被广泛使用的原因:(1) 接触动力学精确:MuJoCo 的接触求解器基于凸优化,在接触/碰撞场景中表现优异,这对操作任务至关重要;(2) 速度快:MuJoCo 的仿真速度远超许多物理引擎,适合大规模 RL 训练(数百万步/天);(3) API 友好:提供 Python/C++ API,与 PyTorch 等深度学习框架集成方便;(4) 开源免费:DeepMind 收购后已完全开源(MIT 协议)。缺点:渲染质量不如 Isaac Sim,GPU 并行不如 Isaac Gym/Lab。
Q65: Isaac Sim/Gym 和 MuJoCo 的主要区别是什么
【考察点】仿真器对比
参考答案:
| 对比维度 | MuJoCo | Isaac Lab (原 Isaac Gym) |
|---|---|---|
| 开发者 | DeepMind(开源) | NVIDIA |
| 物理引擎 | 自研接触求解器 | PhysX (GPU) |
| 渲染 | 基础(近年改善) | RTX 光线追踪,照片级 |
| GPU 并行 | 有限 | 数千环境 GPU 并行 |
| 机器人生态 | 广泛的学术模型库 | 与 NVIDIA 机器人平台深度集成 |
| 适用场景 | 快速原型、RL 研究 | 大规模并行 RL、高保真渲染 |
| 学习曲线 | 较低 | 较高 |
选择建议:学术研究/快速实验用 MuJoCo;大规模 RL 训练/高保真视觉用 Isaac Lab。
Q66: 仿真中如何处理摩擦和接触的不确定性
【考察点】物理仿真、sim2real gap
参考答案: 摩擦和接触是 sim2real gap 的主要来源之一。处理方法:(1) 域随机化:在仿真中随机化摩擦系数(如 $\mu \in [0.3, 1.5]$)、接触刚度、阻尼等参数;(2) 自适应接触模型:使用更复杂的接触模型(如多面摩擦锥近似),虽然计算量更大但更接近真实;(3) 鲁棒策略学习:训练策略使其对接触力的变化不敏感(通过域随机化或 RL 的 robust objective);(4) 系统辨识:测量真实物体和接触面的摩擦系数,在仿真中精确建模特定场景。实际操作任务(如抓取)中,摩擦的准确建模至关重要——摩擦太小会滑落,太大会导致"粘住"。
Q67: 在仿真中训练 RL 策略的典型流程是什么
【考察点】RL 在仿真中的应用
参考答案: 典型流程:(1) 环境搭建:在仿真器中创建任务环境(场景、物体、机器人),定义观察空间、动作空间、奖励函数;(2) 奖励函数设计:这是 RL 仿真的核心——稀疏奖励(任务完成 = +1,否则 = 0)简单但难学习;稠密奖励(距离目标的负距离 + 姿态匹配 + 动作惩罚)易学但可能学到的行为不是最优的;(3) 算法选择:PPO(最常用,稳定)、SAC(连续动作)、DDPG;(4) 训练:大规模并行(Isaac Gym 可同时运行数千环境),训练数百万到数十亿步;(5) 评估:在仿真中测试,然后 sim2real 部署。常见问题是"奖励作弊"(reward hacking)——策略找到奖励函数的漏洞而非完成任务。
Q68: 什么是奖励作弊(Reward Hacking),如何避免
【考察点】RL 训练、奖励设计
参考答案: 奖励作弊指 RL 策略找到奖励函数的漏洞来获得高奖励,而非真正完成任务。例如:目标是将物体放到目标位置,策略发现快速来回移动可以在某个中间状态积累更多正奖励。避免方法:(1) 仔细设计奖励:确保奖励与真实目标一致,避免中间状态的漏洞;(2) 多目标奖励:组合任务完成奖励和过程奖励,使作弊更难;(3) 奖励约束:限制单步最大奖励值;(4) 人类监督:定期人工检查策略行为;(5) 课程学习:从简单任务开始,逐步增加难度,减少探索空间。在 VLA 中,行为克隆(BC)不存在这个问题(因为直接模仿专家),但 BC 无法超越专家。
Q69: 如何在仿真中生成训练 VLA 所需的演示数据
【考察点】数据生成、仿真实践
参考答案: 仿真中生成演示数据的方法:(1) 脚本式专家(Scripted Expert):编写规则/状态机控制机器人完成任务的脚本。质量高但需要人工设计,仅限简单任务;(2) RL 专家:先用 RL 训练一个高成功率的策略,然后用它收集演示数据。可自动化但 RL 本身需要奖励函数设计;(3) 运动规划专家:用 MoveIt 等规划库生成运动学可行的轨迹,再在仿真中执行。适合结构化任务;(4) 遥操作(Teleoperation):人在仿真中用键盘/手柄/VR 控制机器人,收集演示。数据质量高但速度慢;(5) 混合方法:先用规划/RL 生成初始轨迹,人工筛选和修正。LIBERO 数据集使用方法 (2)。
Q70: 仿真的渲染质量和 VLA 的关系是什么
【考察点】视觉仿真、sim2real gap
参考答案: VLA 的输入是图像,因此仿真渲染的质量直接影响 sim2real 迁移效果。关键差异:(1) 光照模型:仿真通常用简单的光照模型(Lambertian),真实世界有复杂的光照(阴影、高光、间接照明)。使用域随机化随机化光照可以缓解;(2) 纹理:仿真中的纹理通常是程序化生成的,真实物体的纹理更丰富且不规则;(3) 抗锯齿/运动模糊:真实相机有镜头畸变、运动模糊、自动曝光等效应,仿真中默认没有;(4) 分辨率和噪声:真实相机的噪声模型(ISO 噪声、暗电流噪声)需要在仿真中模拟。Isaac Sim 的 RTX 渲染可以大幅缩小视觉 gap,但计算成本高。
6. 仿真与环境¶
本节与第 5 节(Sim-to-Real)紧密相关,侧重于仿真工具和 RL 在仿真中的应用。
6.1 仿真器对比¶
| 特性 | MuJoCo | Isaac Lab | PyBullet |
|---|---|---|---|
| 物理引擎 | 自研(凸优化接触) | PhysX (GPU) | Bullet |
| 接触精度 | 高 | 中-高 | 中 |
| 渲染 | 近年改善,有 offscreen | RTX 光追,照片级 | 基础 |
| GPU 并行 | 有限 | 数千环境并行 | 无 |
| Python 支持 | 好(mujoco 库) | 好(isaacsim 库) | 好(pybullet 库) |
| 学习曲线 | 低 | 中-高 | 低 |
| 开源 | MIT 协议 | NVIDIA 许可 | zlib 协议 |
| 典型用户 | 学术研究、RL 训练 | 大规模 RL、高保真 | 教学、快速原型 |
6.2 仿真中常见的物理参数调节¶
- 摩擦系数:0.3-1.5(影响抓取稳定性)
- 阻尼:关节阻尼(影响运动平滑性)
- 质量/惯性:物体的质量和惯性张量(影响动力学)
- 接触刚度:影响接触力的计算
- 时间步长:通常 0.001-0.01s,影响仿真的稳定性和速度
- 重力:9.81 m/s^2(部分任务需要调节,如太空操作)
6.3 仿真与环境面试题(补充至 10 题)¶
Q71: PyBullet 适合什么场景使用,有什么局限性
【考察点】仿真器选择
参考答案: PyBullet 适合:(1) 教学/学习机器人学基础(FK/IK 碰撞检测);(2) 快速原型验证(算法逻辑验证);(3) 简单的 RL 环境。局限性:(1) 接触动力学不够精确(尤其在精细操作任务中);(2) 渲染质量低(PBR 材质支持有限);(3) 没有 GPU 并行,RL 训练效率低;(4) 社区活跃度不如 MuJoCo(DeepMind 收购后发展迅速)。对 VLA 研究,PyBullet 可用于入门和算法原型,但发表高水平工作通常需要 MuJoCo 或 Isaac Lab。
Q72: 什么是并行仿真(Parallel Simulation),为什么 RL 需要它
【考察点】大规模 RL 训练
参考答案: 并行仿真是同时运行多个仿真环境实例,利用多核 CPU 或 GPU 收集经验。RL 需要大量交互数据(数百万到数十亿步),单环境串行采集太慢。Isaac Gym/Lab 可以在单张 GPU 上并行运行数千个环境,使 RL 训练速度提升 2-3 个数量级。例如:PPO 在单个 MuJoCo 环境中可能需要 24 小时训练的任务,在 Isaac Gym 的 4096 个并行环境中可能只需要 30 分钟。对 VLA 而言,虽然主流 VLA 使用行为克隆而非 RL,但 RL fine-tuning 阶段也可能需要并行仿真加速。
7. 论文深挖题(高频考察)¶
7.1 RT-2 核心问题¶
Q73: RT-2 的 co-training 如何防止灾难性遗忘,比例如何确定
【考察点】RT-2 论文、多任务学习
参考答案: RT-2 的 co-training 通过在机器人动作数据(约 15% 的 batch)和视觉-语言数据(约 85% 的 batch)上交替训练来防止灾难性遗忘。原理:(1) VQA/图像描述等视觉-语言任务持续激活预训练学到的语义知识,防止这些知识被机器人数据的梯度"覆盖";(2) 机器人数据和 VQA 数据共享视觉编码器和语言模型,两者互为正则化。比例确定:RT-2 论文实验了不同比例,发现 1:3 到 1:5(机器人:VQA)效果较好。比例太大(机器人数据过多)→ 灾难性遗忘严重;比例太小(机器人数据不足)→ 动作生成能力弱。本质上这是一个 multi-task learning 中的 task balancing 问题。
Q74: RT-2 动作 token 化的 bin 数选择(256 vs 1024)有什么影响
【考察点】RT-2 设计选择、量化精度
参考答案: RT-2 将每个动作维度量化为 256 个 bin(均匀分布在归一化范围 $[-1, 1]$ 内)。选择 256 的原因:(1) 与标准的 byte-level tokenization 兼容;(2) 256 bins 的精度对于大多数操作任务足够(每个 bin 约 0.008 的分辨率)。如果增加到 1024 bins:(1) 精度提高 4 倍(每个 bin 约 0.002),对精细操作任务可能有益;(2) 但自回归序列更长(更多 token 需要生成),推理延迟增大;(3) 词表增大,训练数据中每个 bin 的样本减少,可能影响训练稳定性。RT-2 论文实验表明 256 bins 在大多数任务上已接近连续控制的精度。
7.2 OpenVLA 核心问题¶
Q75: OpenVLA LoRA rank=32 的实验对比结论是什么
已在 Q39 中解答(LoRA rank 选择)。
Q76: OpenVLA 冻结视觉编码器 vs 全参数微调的权衡
【考察点】OpenVLA 设计、特征迁移
参考答案: OpenVLA 选择冻结视觉编码器(DINOv2 + SigLIP),只微调语言主干和策略头。权衡分析: - 冻结的优势:(1) 保留预训练视觉特征的质量(DINOv2/SigLIP 在大规模数据上训练的特征非常强);(2) 大幅减少训练参数和显存;(3) 训练更稳定(视觉特征空间不变);(4) 避免在小数据集上过拟合视觉编码器。 - 冻结的劣势:(1) 视觉特征可能不是任务最优的(操作任务可能需要不同于图像分类的特征);(2) 无法通过微调适应特定机器人的相机/视角。 - 全参数微调的优势:理论上可以获得更好的任务适配。 - 全参数微调的劣势:需要更多数据和计算资源;在小数据集上容易过拟合。
OpenVLA 论文实验表明,冻结视觉编码器 + LoRA 微调语言主干的效果已经非常接近全参数微调,且效率高得多。
7.3 Diffusion Policy 核心问题¶
Q77: Diffusion Policy 为什么扩散能表示多峰分布
已在 Q49 中解答。
Q78: Diffusion Policy 的 temporal ensemble 具体如何计算
已在 Q52 中解答。
Q79: Diffusion Policy 中 1D 和 2D 时间维度设计的区别和适用场景
【考察点】Diffusion Policy 变体
参考答案: Diffusion Policy 有两种时间维度设计: - 1D 时间序列:将动作 chunk $[a_1, a_2, ..., a_T]$ 展平为一维向量 $[a_{1,1}, a_{1,2}, ..., a_{1,D}, a_{2,1}, ...]$,用一个去噪网络处理。简单直接。 - 2D 时间序列:将动作 chunk 组织为 $T \times D$ 的二维矩阵,用 2D UNet 或 Transformer 处理。T 轴为时间步,D 轴为动作维度。可以分别建模时间和维度间的依赖关系。
1D 适合动作维度低(6-7D)的场景;2D 适合动作维度高(如灵巧手 16-24D)的场景,因为 2D 结构可以更好地解耦时间和维度间的交互。论文实验表明,在低维动作空间上两者差异不大,但在高维空间上 2D 可能更好。
7.4 pi0 核心问题¶
Q80: Flow Matching vs DDPM 的具体区别
已在 Q37 中解答。
Q81: pi0 的 Action Expert 的设计动机和具体结构
已在 Q44 中解答。
8. 系统设计与工程题¶
Q82: 设计一个端到端的桌面抓取系统
【考察点】系统设计、工程能力
参考答案:
整体架构:
RGB-D 相机 → 视觉感知(物体检测/分割 + 6-DoF 抓取位姿估计)
↓
语言指令 → VLA 策略(OpenVLA / π0)
↓
IK 求解 → 轨迹插值 → 安全过滤器 → 机器人控制器 → 执行
模块设计: 1. 感知模块:RGB-D 图像输入,使用预训练模型(如 Grounding DINO + SAM)做开放词汇物体检测和分割;估计物体的 6-DoF 位姿 2. 策略模块:VLA 模型接收当前图像 + 语言指令,输出动作序列(delta EE pose + gripper 命令) 3. 执行模块:IK 将 EE pose 转为关节角,轨迹插值确保平滑,安全过滤器检查关节限位/速度/碰撞 4. 反馈模块:闭环控制——每次执行后获取新的观察,重新推理 VLA
关键设计决策: - 动作空间选择 delta EE pose(跨平台迁移好) - Action Chunking(预测 8-16 步,执行前半后重新推理) - 失败恢复:检测抓取失败(力传感器/视觉检测),自动重试 - 安全:关节限位检查 + 速度限制 + 工作空间围栏
Q83: 如何在低延迟约束下部署 VLA 到边缘设备
【考察点】模型优化、边缘部署
参考答案:
延迟分析(以 7B OpenVLA 为例): - 视觉编码(DINOv2 + SigLIP):~30ms - 语言主干(Llama 2 7B):~80ms - 策略头(MLP):~1ms - 总计:~110ms → 控制频率约 9Hz
优化策略(按效果排序): 1. 量化:BF16 → INT8(2x 加速,精度损失 < 1%),或 INT4(4x 加速,精度损失稍大) 2. 视觉特征缓存:场景变化不大时,每隔 N 帧更新一次视觉特征(假设相机 10Hz,VLA 5Hz 推理足够) 3. 模型蒸馏:用 7B 教师模型蒸馏一个 1-2B 的学生模型 4. KV Cache:自回归生成时缓存已计算的 KV(对 RT-2 风格模型有效) 5. TensorRT 编译:将 PyTorch 模型编译为 TensorRT 引擎,利用 GPU 优化 6. 硬件选择:Jetson Orin NX(~100 TOPS INT8)或搭配 GPU 的边缘计算盒 7. 异步 pipeline:视觉编码、语言处理、动作生成流水线化
目标:从 ~110ms 优化到 ~30ms,达到 30Hz 控制频率。
Q84: 设计一个跨平台(多种机械臂)的通用策略训练 pipeline
【考察点】系统设计、数据工程
参考答案:
Pipeline 设计:
多源数据(不同机器人) → 数据标准化(统一 RLDS 格式)
↓
数据分析 & 清洗
↓
统一预处理(图像 resize、动作归一化)
↓
预训练(OXE 风格的统一数据集)
↓
┌───────────────┼───────────────┐
↓ ↓ ↓
机器人 A 微调 机器人 B 微调 机器人 C 微调
↓ ↓ ↓
仿真评估 仿真评估 仿真评估
↓ ↓ ↓
真实部署 真实部署 真实部署
关键设计点: 1. 数据标准化:统一为 RLDS 格式,包含:图像、语言指令、动作(归一化)、机器人元信息(类型、DOF、动作范围) 2. 动作空间统一:统一为 delta EE pose(跨平台语义一致),或使用 pad + mask 处理不同维度 3. 架构选择:共享视觉-语言主干 + 机器人特定的策略头/Action Expert 4. 微调策略:LoRA 微调,每个机器人只需 5k-10k 条轨迹 5. 评估框架:统一的仿真评估环境,支持多种机器人
9. 编程题¶
Q85: 实现 Jacobian 伪逆 IK
【考察点】运动学编程、数值方法
import numpy as np
def jacobian_pseudo_inverse_ik(robot_fk, target_pos, q_init, max_iter=100, tol=1e-4, damping=0.01):
"""
Jacobian 伪逆法求解逆运动学(带阻尼)
参数:
robot_fk: function, q -> 3D position (shape: [3,])
target_pos: 目标位置 (shape: [3,])
q_init: 初始关节角 (shape: [n,])
max_iter: 最大迭代次数
tol: 收敛阈值
damping: 阻尼系数
返回:
q: 求解的关节角
"""
q = q_init.copy()
n = len(q)
for i in range(max_iter):
# 当前末端位置
current_pos = robot_fk(q)
error = target_pos - current_pos
# 检查收敛
if np.linalg.norm(error) < tol:
break
# 数值计算 Jacobian 矩阵
J = np.zeros((3, n))
eps = 1e-6
for j in range(n):
q_plus = q.copy()
q_plus[j] += eps
J[:, j] = (robot_fk(q_plus) - current_pos) / eps
# 阻尼最小二乘: dq = J^T (J J^T + lambda^2 I)^-1 error
JJT = J @ J.T
dq = J.T @ np.linalg.solve(JJT + damping**2 * np.eye(3), error)
# 更新关节角
q = q + dq
return q
# 示例:2-DOF 平面机械臂
def fk_2dof(q, l1=1.0, l2=1.0):
x = l1 * np.cos(q[0]) + l2 * np.cos(q[0] + q[1])
y = l1 * np.sin(q[0]) + l2 * np.sin(q[0] + q[1])
return np.array([x, y])
# 测试
q_init = np.array([0.5, 0.5])
target = np.array([1.5, 0.5])
q_sol = jacobian_pseudo_inverse_ik(fk_2dof, target, q_init)
print(f"Solution: {q_sol}, FK result: {fk_2dof(q_sol)}")
更多 FK/IK 实践见 tutorials/02-action-representation/fk_ik_demo.py。
Q86: 实现简单的 Action Chunking
【考察点】VLA 核心概念实现
import torch
import torch.nn as nn
class ActionChunkingPolicy(nn.Module):
"""
Action Chunking 策略网络
输入: 观测特征 (obs_dim,)
输出: 未来 chunk_size 步的动作 (chunk_size, action_dim)
"""
def __init__(self, obs_dim, action_dim, chunk_size=8, hidden_dim=256):
super().__init__()
self.chunk_size = chunk_size
self.action_dim = action_dim
# 编码器: 将观测编码为隐状态
self.obs_encoder = nn.Sequential(
nn.Linear(obs_dim, hidden_dim),
nn.ReLU(),
nn.Linear(hidden_dim, hidden_dim),
)
# 时序解码器: 从隐状态生成动作序列
self.decoder = nn.GRU(hidden_dim, hidden_dim, batch_first=True)
# 策略头: 将隐状态映射为动作
self.action_head = nn.Linear(hidden_dim, action_dim)
def forward(self, obs):
"""
obs: (batch_size, obs_dim)
返回: (batch_size, chunk_size, action_dim)
"""
batch_size = obs.shape[0]
# 编码观测
h = self.obs_encoder(obs) # (batch, hidden_dim)
# 生成时序输入: 将同一个隐状态重复 chunk_size 次
decoder_input = h.unsqueeze(1).repeat(1, self.chunk_size, 1) # (batch, chunk, hidden)
# GRU 解码
output, _ = self.decoder(decoder_input) # (batch, chunk, hidden)
# 映射为动作
actions = self.action_head(output) # (batch, chunk, action_dim)
return actions
def get_action(self, obs, exec_ratio=0.5):
"""推理时只执行前 exec_ratio 比例的动作"""
with torch.no_grad():
obs_t = torch.FloatTensor(obs).unsqueeze(0)
actions = self.forward(obs_t).squeeze(0) # (chunk, action_dim)
n_exec = int(self.chunk_size * exec_ratio)
return actions[:n_exec].numpy()
Q87: 实现 CLIP contrastive loss
【考察点】对比学习、VLM 基础
import torch
import torch.nn as nn
import torch.nn.functional as F
class CLIPLoss(nn.Module):
"""
CLIP 对比学习损失 (对称 InfoNCE)
"""
def __init__(self, temperature=0.07):
super().__init__()
self.temperature = temperature
def forward(self, image_features, text_features):
"""
image_features: (batch_size, dim) -- L2 归一化后的图像特征
text_features: (batch_size, dim) -- L2 归一化后的文本特征
返回: 标量 loss
"""
# 确保特征已归一化
image_features = F.normalize(image_features, dim=-1)
text_features = F.normalize(text_features, dim=-1)
# 计算相似度矩阵 (batch, batch)
logits = image_features @ text_features.T / self.temperature
# 对称 cross-entropy loss
labels = torch.arange(logits.shape[0], device=logits.device)
loss_i2t = F.cross_entropy(logits, labels) # image -> text
loss_t2i = F.cross_entropy(logits.T, labels) # text -> image
return (loss_i2t + loss_t2i) / 2
# 使用示例
batch_size, dim = 32, 512
image_feats = torch.randn(batch_size, dim)
text_feats = torch.randn(batch_size, dim)
loss_fn = CLIPLoss(temperature=0.07)
loss = loss_fn(image_feats, text_feats)
print(f"CLIP Loss: {loss.item():.4f}")
Q88: 实现简单的 LoRA(手动替换线性层)
【考察点】LoRA 原理、PyTorch 编程
import torch
import torch.nn as nn
import math
class LoRALinear(nn.Module):
"""
带 LoRA 适配器的线性层
冻结原始权重 W0,添加低秩分解 BA
输出 = W0 @ x + B @ A @ x
"""
def __init__(self, original_linear, rank=16, alpha=1.0):
super().__init__()
self.original = original_linear
self.original.weight.requires_grad_(False)
if self.original.bias is not None:
self.original.bias.requires_grad_(False)
in_features = original_linear.in_features
out_features = original_linear.out_features
# LoRA 参数
self.rank = rank
self.alpha = alpha
self.scaling = alpha / rank
# 低秩矩阵 A (in_features, rank) 和 B (rank, out_features)
# A 用 Kaiming 初始化,B 用零初始化(保证初始时 LoRA 输出为 0)
self.lora_A = nn.Parameter(torch.empty(in_features, rank))
nn.init.kaiming_uniform_(self.lora_A, a=math.sqrt(5))
self.lora_B = nn.Parameter(torch.zeros(rank, out_features))
def forward(self, x):
# 原始输出 + LoRA 输出
original_out = self.original(x)
lora_out = (x @ self.lora_A @ self.lora_B) * self.scaling
return original_out + lora_out
def apply_lora_to_model(model, target_modules=["q_proj", "k_proj", "v_proj"], rank=16):
"""
将模型中指定的线性层替换为 LoRA 线性层
参数:
model: 原始模型
target_modules: 需要添加 LoRA 的模块名称列表
rank: LoRA rank
返回:
可训练参数数量
"""
trainable_params = 0
for name, module in model.named_modules():
# 检查是否是目标模块
for target in target_modules:
if target in name and isinstance(module, nn.Linear):
# 获取父模块和属性名
parts = name.split('.')
parent = model
for part in parts[:-1]:
parent = getattr(parent, part)
attr_name = parts[-1]
# 替换为 LoRA 线性层
lora_layer = LoRALinear(module, rank=rank)
setattr(parent, attr_name, lora_layer)
trainable_params += lora_layer.lora_A.numel() + lora_layer.lora_B.numel()
print(f"Applied LoRA (rank={rank}) to {name}: "
f"+{lora_layer.lora_A.numel() + lora_layer.lora_B.numel()} params")
break
print(f"Total LoRA trainable params: {trainable_params:,}")
return trainable_params
# 使用示例
class SimpleTransformer(nn.Module):
def __init__(self, d_model=512, nhead=8):
super().__init__()
self.q_proj = nn.Linear(d_model, d_model)
self.k_proj = nn.Linear(d_model, d_model)
self.v_proj = nn.Linear(d_model, d_model)
self.out_proj = nn.Linear(d_model, d_model)
def forward(self, x):
Q = self.q_proj(x)
K = self.k_proj(x)
V = self.v_proj(x)
# ... attention computation ...
return self.out_proj(Q)
model = SimpleTransformer()
print(f"Original params: {sum(p.numel() for p in model.parameters()):,}")
apply_lora_to_model(model, rank=16)
10. 面试流程与准备建议¶
10.1 典型面试流程¶
| 阶段 | 内容 | 时间 | 准备重点 |
|---|---|---|---|
| 简历筛选 | 匹配关键词:VLA、具身智能、大模型、机器人 | - | 简历突出相关项目/论文 |
| 笔试 | 编程题(PyTorch、numpy)+ 理论题(DL、ML) | 60-90 分钟 | 本文档第 2、9 节 |
| 技术一面 | 项目深挖、基础概念、代码手撕 | 45-60 分钟 | 本文档第 2-4、11 节 |
| 技术二面 | 系统设计、论文理解、开放问题 | 45-60 分钟 | 本文档第 4、7、8、12 节 |
| 技术三面(部分公司) | 综合能力、前沿趋势、研究规划 | 45 分钟 | 第 4-6、13 节 + 最新论文 |
| HR 面 | 职业规划、团队文化、薪资 | 30 分钟 | 了解公司文化 |
10.2 按本项目学习路径复习建议¶
按 03-learning-path.md 的学习阶段,结合面试准备:
| 学习阶段 | 复习重点 | 本文档章节 |
|---|---|---|
| Stage 0-1 (VLM 基础) | CLIP loss、ViT、DINOv2、SigLIP、位置编码、Attention | 第 2 节 |
| Stage 2 (动作表示) | FK/IK、动作空间对比、Action Chunking、Jacobian | 第 3 节 |
| Stage 3 (简单 VLA) | VLA 架构、OpenVLA 推理、unnorm_key | 第 4 节 |
| Stage 4 (微调) | LoRA、数据格式、LIBERO 评估、训练技巧 | 第 4 节 |
| 进阶 (Diffusion/Sim2Real) | Flow Matching、域随机化、仿真器对比 | 第 4-6 节 |
| 论文精读 | RT-2、OpenVLA、Diffusion Policy、pi0 核心问题 | 第 7 节 |
| 工程实践 | 系统设计、部署优化、编程实现 | 第 8-9 节 |
| 手写代码 | FK/IK、Self-Attention、Loss、Diffusion、RL | 第 11 节 |
| 系统设计 | 遥操作、推理服务、评估 Pipeline | 第 12 节 |
| 前沿追踪 | ZR-0、Pose-VLA、DexSim2Real、MoDE-VLA | 第 13 节 |
10.3 高频关键词清单¶
以下是 VLA 面试中的高频关键词,确保每个词都能给出 1-2 分钟的清晰解释:
基础篇: Transformer, Self-Attention, Multi-Head Attention, Position Encoding (RoPE / Sinusoidal / ALiBi), LayerNorm / RMSNorm, KV Cache, Flash Attention, LoRA, CLIP, DINOv2, SigLIP, InfoNCE Loss, Diffusion Model, Flow Matching, Behavior Cloning, Reinforcement Learning
VLA 篇: VLA, VLM, RT-1, RT-2, OpenVLA, pi0, Octo, Diffusion Policy, ACT, Action Chunking, Action Expert, Co-training, Discretization, OXE (Open X-Embodiment), unnorm_key, Temporal Ensemble, Goal Conditioning, TokenLearner, FiLM
机器人篇: FK (Forward Kinematics), IK (Inverse Kinematics), Jacobian, DH 参数, SE(3), 四元数, 奇异点, 力封闭, Robot Adapter, Action Chunking, Delta Action, End-Effector, 关节空间, 任务空间
工程篇: Sim-to-Real, Domain Randomization, Domain Adaptation, MuJoCo, Isaac Lab, PyBullet, Mixed Precision, Gradient Clipping, TensorRT, Quantization, RLDS
2026 前沿篇: ZR-0, ECoT, Pose-VLA, Xiaomi-Robotics-1, Hy-Embodied-0.5-VLA, ACE-Ego, DexSim2Real, Phys2Real, MoDE-VLA, Touch Dreaming
10.4 面试答题技巧¶
- 先总后分:先给出总体框架/定义,再展开细节
- 结合项目经验:回答时关联自己做过的项目(如"我在 LIBERO 上微调 OpenVLA 时遇到过这个问题...")
- 承认不确定:不确定的问题坦诚说明,然后给出自己的推理过程
- 画图辅助:面试中可以主动画架构图、流程图,展示清晰思维
- 追问准备:每个回答后,预判面试官可能的追问并准备
- 关注 trade-off:技术选择没有绝对的好坏,关键是理解 trade-off 并给出合理选择
附录:题目索引¶
| 编号 | 类别 | 题目关键词 |
|---|---|---|
| Q1 | DL 基础 | LoRA 原理 |
| Q2 | DL 基础 | CLIP temperature scaling |
| Q3 | DL 基础 | Flash Attention |
| Q4 | DL 基础 | DINOv2 vs CLIP ViT |
| Q5 | DL 基础 | Co-training |
| Q6 | DL 基础 | ViT patch size |
| Q7 | DL 基础 | LayerNorm vs RMSNorm |
| Q8 | DL 基础 | KV cache |
| Q9 | DL 基础 | 残差连接 |
| Q10 | DL 基础 | Multi-Head Attention 维度 |
| Q11 | DL 基础 | CLS token |
| Q12 | DL 基础 | Cross-entropy vs MSE |
| Q13 | DL 基础 | AdamW |
| Q14 | DL 基础 | 梯度裁剪 |
| Q15 | DL 基础 | BatchNorm/LayerNorm/GroupNorm |
| Q16 | DL 基础 | 混合精度训练 |
| Q17 | DL 基础 | Dropout |
| Q18 | DL 基础 | 位置编码外推 |
| Q19 | DL 基础 | Causal mask |
| Q20 | DL 基础 | Logits vs Softmax |
| Q21 | 机器人学 | Jacobian 物理含义 |
| Q22 | 机器人学 | IK 多解问题 |
| Q23 | 机器人学 | 关节角 vs 末端位姿 |
| Q24 | 机器人学 | Action Chunking |
| Q25 | 机器人学 | 机器人全身控制 |
| Q26 | 机器人学 | 奇异点 |
| Q27 | 机器人学 | SE(3) 和 se(3) |
| Q28 | 机器人学 | DH 参数 |
| Q29 | 机器人学 | 工作空间 |
| Q30 | 机器人学 | 四元数 vs 欧拉角 |
| Q31 | 机器人学 | 力控制 |
| Q32 | 机器人学 | PID 控制 |
| Q33 | 机器人学 | 轨迹优化 |
| Q34 | 机器人学 | 安全约束 |
| Q35 | 机器人学 | 点云 vs 深度图 |
| Q36 | VLA 核心 | OpenVLA vs RT-2 |
| Q37 | VLA 核心 | Flow Matching vs Diffusion |
| Q38 | VLA 核心 | 动作离散化 |
| Q39 | VLA 核心 | LoRA rank 选择 |
| Q40 | VLA 核心 | LIBERO 评估 |
| Q41 | VLA 核心 | VLA 推理延迟 |
| Q42 | VLA 核心 | unnorm_key |
| Q43 | VLA 核心 | DINOv2 + SigLIP |
| Q44 | VLA 核心 | Action Expert |
| Q45 | VLA 核心 | Sim2Real gap |
| Q46 | VLA 核心 | 长程任务 |
| Q47 | VLA 核心 | TokenLearner |
| Q48 | VLA 核心 | Open X-Embodiment |
| Q49 | VLA 核心 | 扩散多峰分布 |
| Q50 | VLA 核心 | OpenVLA 训练流程 |
| Q51 | VLA 核心 | VLA 输入 |
| Q52 | VLA 核心 | Temporal Ensemble |
| Q53 | VLA 核心 | 语言条件化 |
| Q54 | VLA 核心 | 跨平台动作维度 |
| Q55 | VLA 核心 | CVAE / ACT |
| Q56 | VLA 核心 | 数据增强 |
| Q57 | VLA 核心 | 失败模式诊断 |
| Q58 | VLA 核心 | 评估指标 |
| Q59 | VLA 核心 | VLA vs 传统 Pipeline |
| Q60 | VLA 核心 | 大规模预训练必要性 |
| Q61 | Sim2Real | 域随机化强度 |
| Q62 | Sim2Real | 数字孪生 |
| Q63 | Sim2Real | Sim2Real 验证 |
| Q64 | Sim2Real | MuJoCo 优势 |
| Q65 | Sim2Real | Isaac vs MuJoCo |
| Q66 | Sim2Real | 摩擦接触不确定性 |
| Q67 | Sim2Real | RL 仿真训练流程 |
| Q68 | Sim2Real | 奖励作弊 |
| Q69 | Sim2Real | 仿真演示数据生成 |
| Q70 | Sim2Real | 渲染质量 |
| Q71 | 仿真 | PyBullet 适用场景 |
| Q72 | 仿真 | 并行仿真 |
| Q73 | 论文 | RT-2 co-training |
| Q74 | 论文 | RT-2 bin 数选择 |
| Q75 | 论文 | OpenVLA LoRA rank |
| Q76 | 论文 | OpenVLA 冻结视觉编码器 |
| Q77 | 论文 | 扩散多峰分布 |
| Q78 | 论文 | Temporal Ensemble |
| Q79 | 论文 | Diffusion Policy 1D vs 2D |
| Q80 | 论文 | Flow Matching vs DDPM |
| Q81 | 论文 | Action Expert 结构 |
| Q82 | 系统设计 | 桌面抓取系统 |
| Q83 | 系统设计 | 边缘部署 |
| Q84 | 系统设计 | 跨平台训练 pipeline |
| Q85 | 编程 | Jacobian 伪逆 IK |
| Q86 | 编程 | Action Chunking |
| Q87 | 编程 | CLIP contrastive loss |
| Q88 | 编程 | LoRA 线性层 |
| Q89 | 手写代码 | 2D FK/IK |
| Q90 | 手写代码 | Self-Attention |
| Q91 | 手写代码 | Huber Loss |
| Q92 | 手写代码 | Diffusion Policy 噪声采样 |
| Q93 | 手写代码 | SAC Q-Loss |
| Q94 | 系统设计 | 100Hz 遥操作系统 |
| Q95 | 系统设计 | VLA 推理服务 |
| Q96 | 系统设计 | 灵巧操作评估 Pipeline |
| Q97 | 前沿论文 | ZR-0 ECoT |
| Q98 | 前沿论文 | Pose-VLA 两阶段训练 |
| Q99 | 前沿论文 | DexSim2Real 基础模型迁移 |
| Q100 | 前沿论文 | MoDE-VLA MoE |
相关资源链接: - VLA 核心概念:
01-what-is-vla.md- 关键论文导读:02-key-papers.md- 完整学习路线:03-learning-path.md- 术语速查:04-glossary.md- VLM 基础教程:tutorials/01-vlm-basics/- 动作表示与 FK/IK:tutorials/02-action-representation/- 最小 VLA 搭建:tutorials/03-simple-vla/- 微调实践:tutorials/04-fine-tuning/
11. 手写代码题(Coding Round)¶
以下题目为 VLA / 机器人算法岗面试中常见的手撕代码题,要求在白板或在线编辑器上 15-30 分钟内完成。
Q89: 手写 2D FK / IK(numpy 实现)
【考察点】运动学基础、numpy 向量化编程
import numpy as np
def fk_2d(q, link_lengths):
"""
2D 平面机械臂前向运动学
参数:
q: (n,) 关节角
link_lengths: (n,) 连杆长度
返回:
joints: (n+1, 2) 各关节位置 (x, y),最后一个为末端
"""
n = len(q)
joints = np.zeros((n + 1, 2))
theta = 0.0
for i in range(n):
theta += q[i]
joints[i + 1] = joints[i] + link_lengths[i] * np.array([np.cos(theta), np.sin(theta)])
return joints
def ik_2d_jacobian(target, q_init, link_lengths, max_iter=100, lr=0.1, damping=0.01):
"""
2D 平面机械臂逆运动学(Jacobian 转置法 + 阻尼)
参数:
target: (2,) 目标末端位置
q_init: (n,) 初始关节角
link_lengths: (n,) 连杆长度
返回:
q: (n,) 求解关节角
"""
q = q_init.copy()
n = len(q)
for _ in range(max_iter):
joints = fk_2d(q, link_lengths)
end = joints[-1]
error = target - end
if np.linalg.norm(error) < 1e-4:
break
# 数值计算 Jacobian(末端位置对关节角的偏导)
J = np.zeros((2, n))
eps = 1e-6
for j in range(n):
q_perturb = q.copy()
q_perturb[j] += eps
J[:, j] = (fk_2d(q_perturb, link_lengths)[-1] - end) / eps
# 阻尼最小二乘: dq = J^T (J J^T + lambda^2 I)^-1 error
JJT = J @ J.T
dq = J.T @ np.linalg.solve(JJT + damping**2 * np.eye(2), error)
q += lr * dq
return q
# 示例: 3-DOF 平面臂
link_lengths = np.array([1.0, 1.0, 0.5])
q_init = np.array([0.1, 0.2, 0.1])
target = np.array([1.5, 1.0])
q_sol = ik_2d_jacobian(target, q_init, link_lengths)
print(f"Solution: {q_sol}")
print(f"FK check: {fk_2d(q_sol, link_lengths)[-1]}")
要点: - FK 用角度累加计算每个关节位置 - IK 用数值 Jacobian + 阻尼最小二乘,避免奇异点 - 2D 场景下 JJT 是 2x2 矩阵,求逆代价极低
Q90: 手写 Self-Attention(PyTorch)
【考察点】Attention 机制、PyTorch 矩阵运算
import torch
import torch.nn as nn
import math
class SelfAttention(nn.Module):
"""
标准 Self-Attention(单头,支持 causal mask)
输入: x (batch, seq_len, dim)
输出: attn_out (batch, seq_len, dim), attn_weights (batch, seq_len, seq_len)
"""
def __init__(self, dim):
super().__init__()
self.dim = dim
self.q_proj = nn.Linear(dim, dim)
self.k_proj = nn.Linear(dim, dim)
self.v_proj = nn.Linear(dim, dim)
self.out_proj = nn.Linear(dim, dim)
def forward(self, x, causal_mask=False):
B, N, D = x.shape
Q = self.q_proj(x) # (B, N, D)
K = self.k_proj(x)
V = self.v_proj(x)
# 计算注意力分数: (B, N, D) @ (B, D, N) -> (B, N, N)
scores = torch.matmul(Q, K.transpose(-2, -1)) / math.sqrt(D)
if causal_mask:
# 下三角 mask,防止看到未来信息
mask = torch.triu(torch.ones(N, N, device=x.device), diagonal=1).bool()
scores = scores.masked_fill(mask, float('-inf'))
attn_weights = torch.softmax(scores, dim=-1) # (B, N, N)
attn_out = torch.matmul(attn_weights, V) # (B, N, N) @ (B, N, D) -> (B, N, D)
attn_out = self.out_proj(attn_out)
return attn_out, attn_weights
# 使用示例
batch_size, seq_len, dim = 2, 10, 64
x = torch.randn(batch_size, seq_len, dim)
attn = SelfAttention(dim)
out, weights = attn(x, causal_mask=True)
print(out.shape, weights.shape) # [2, 10, 64], [2, 10, 10]
要点:
- 注意 math.sqrt(D) 缩放,防止 softmax 梯度消失
- causal mask 用 torch.triu 构造上三角无穷大
- 矩阵乘法用 torch.matmul 自动处理 batch 维度
Q91: 手写 Huber Loss 及其梯度
【考察点】损失函数设计、自动微分/手动求导
import torch
import torch.nn as nn
def huber_loss(input, target, delta=1.0):
"""
Huber Loss: 在 |x| < delta 时为 MSE,|x| >= delta 时为 MAE
参数:
input: (N, *) 预测值
target: (N, *) 目标值
delta: 阈值
返回:
loss: 标量
"""
error = input - target
abs_error = torch.abs(error)
# 分段计算
quadratic = torch.where(abs_error < delta, 0.5 * error ** 2, torch.zeros_like(error))
linear = torch.where(abs_error >= delta, delta * (abs_error - 0.5 * delta), torch.zeros_like(error))
loss = quadratic + linear
return loss.mean()
def huber_loss_manual_grad(error, delta=1.0):
"""
Huber Loss 对 error 的手动梯度(面试可能要求不借助 autograd)
dL/de = error if |error| < delta
dL/de = delta * sign(error) if |error| >= delta
"""
abs_e = torch.abs(error)
grad = torch.where(abs_e < delta, error, delta * torch.sign(error))
return grad
# 对比 PyTorch 官方实现
criterion = nn.SmoothL1Loss(beta=1.0) # PyTorch 中 beta 即 delta
pred = torch.randn(4, 5, requires_grad=True)
tgt = torch.randn(4, 5)
loss1 = huber_loss(pred, tgt, delta=1.0)
loss2 = criterion(pred, tgt)
print(f"Custom: {loss1.item():.6f}, Official: {loss2.item():.6f}")
要点:
- Huber Loss 结合了 MSE(小误差时平滑)和 MAE(大误差时鲁棒)的优点
- 梯度在 |error| = delta 处连续,但二阶导不连续
- PyTorch 的 SmoothL1Loss 等价于 Huber Loss
Q92: 手写 Diffusion Policy 的噪声采样
【考察点】扩散模型训练流程、重参数化技巧
import torch
import torch.nn as nn
def sample_diffusion_noise_schedule(timesteps=100, beta_start=1e-4, beta_end=0.02):
"""
生成线性噪声调度参数(DDPM 风格)
返回:
betas: (T,)
alphas: (T,)
alphas_cumprod: (T,) alpha_bar_t
"""
betas = torch.linspace(beta_start, beta_end, timesteps)
alphas = 1.0 - betas
alphas_cumprod = torch.cumprod(alphas, dim=0)
return betas, alphas, alphas_cumprod
def q_sample(action, t, alphas_cumprod, noise=None):
"""
前向扩散过程: 在时刻 t 对动作加噪
q(a_t | a_0) = N(a_t; sqrt(alpha_bar_t) * a_0, (1 - alpha_bar_t) * I)
参数:
action: (B, action_dim) 原始动作
t: (B,) 时间步(整数)
alphas_cumprod: (T,) 预计算的 alpha_bar
noise: (B, action_dim) 可选,外部传入噪声
返回:
noisy_action: (B, action_dim)
noise: (B, action_dim) 实际使用的噪声(用于训练目标)
"""
if noise is None:
noise = torch.randn_like(action)
# 根据 t 取对应的 alpha_bar
sqrt_alpha_bar = torch.sqrt(alphas_cumprod[t]).view(-1, 1) # (B, 1)
sqrt_one_minus_alpha_bar = torch.sqrt(1 - alphas_cumprod[t]).view(-1, 1)
noisy_action = sqrt_alpha_bar * action + sqrt_one_minus_alpha_bar * noise
return noisy_action, noise
# 训练时的噪声预测损失
def diffusion_policy_loss(model, obs, action, alphas_cumprod):
"""
Diffusion Policy 的训练损失
参数:
model: 噪声预测网络 noise_pred = model(noisy_action, t, obs)
obs: (B, obs_dim) 观测条件
action: (B, action_dim) 专家动作
alphas_cumprod: (T,)
返回:
loss: 标量
"""
B = action.shape[0]
T = len(alphas_cumprod)
device = action.device
# 随机采样时间步
t = torch.randint(0, T, (B,), device=device)
# 对动作加噪
noisy_action, noise = q_sample(action, t, alphas_cumprod)
# 模型预测噪声
predicted_noise = model(noisy_action, t, obs)
# MSE 损失(预测噪声 vs 真实噪声)
loss = nn.functional.mse_loss(predicted_noise, noise)
return loss
# 使用示例
T = 100
betas, alphas, alphas_cumprod = sample_diffusion_noise_schedule(T)
action = torch.randn(8, 16) # batch=8, action_dim=16
t = torch.randint(0, T, (8,))
noisy_action, noise = q_sample(action, t, alphas_cumprod)
print(f"Noisy action: {noisy_action.shape}, Noise: {noise.shape}")
要点:
- 前向过程是封闭形式的高斯采样,无需迭代(重参数化技巧)
- 训练目标是预测添加的噪声 epsilon,而非直接预测 x_0
- alphas_cumprod 需要预计算,避免训练时重复 cumprod
Q93: 手写 SAC 的 Q-Loss
【考察点】强化学习、SAC 算法、目标网络
import torch
import torch.nn as nn
import torch.nn.functional as F
def sac_q_loss(Q1, Q2, Q1_target, Q2_target, policy,
state, action, reward, next_state, done,
gamma=0.99, alpha=0.2):
"""
SAC 的 Q 网络损失函数(双 Q 网络 + target network)
参数:
Q1, Q2: 当前 Q 网络 (s, a) -> Q
Q1_target, Q2_target: 目标 Q 网络(EMA 更新)
policy: 策略网络 s -> (mean, log_std)
state, action, reward, next_state, done: batch 数据
gamma: 折扣因子
alpha: 温度系数(熵奖励权重)
返回:
q1_loss, q2_loss: 两个 Q 网络的损失
"""
with torch.no_grad():
# 从策略采样下一动作
next_action, next_log_prob = policy.sample(next_state)
# 目标 Q 值: min(Q1_target, Q2_target) - alpha * log_pi
q1_next = Q1_target(next_state, next_action)
q2_next = Q2_target(next_state, next_action)
q_next = torch.min(q1_next, q2_next) - alpha * next_log_prob
# Bellman 目标
q_target = reward + (1 - done) * gamma * q_next
# 当前 Q 估计
q1_pred = Q1(state, action)
q2_pred = Q2(state, action)
# MSE loss
q1_loss = F.mse_loss(q1_pred, q_target)
q2_loss = F.mse_loss(q2_pred, q_target)
return q1_loss, q2_loss
def sac_policy_loss(Q1, policy, state, alpha=0.2):
"""
SAC 的策略损失(最大化 Q 值 + 熵奖励)
"""
action_new, log_prob = policy.sample(state)
q1_new = Q1(state, action_new)
# 目标: 最大化 (Q - alpha * log_pi) => 最小化 -(Q - alpha * log_pi)
policy_loss = (alpha * log_prob - q1_new).mean()
return policy_loss
# 简化的策略网络(输出高斯分布)
class GaussianPolicy(nn.Module):
def __init__(self, state_dim, action_dim, hidden_dim=256):
super().__init__()
self.net = nn.Sequential(
nn.Linear(state_dim, hidden_dim), nn.ReLU(),
nn.Linear(hidden_dim, hidden_dim), nn.ReLU(),
)
self.mean = nn.Linear(hidden_dim, action_dim)
self.log_std = nn.Linear(hidden_dim, action_dim)
def sample(self, state):
h = self.net(state)
mean = self.mean(h)
log_std = torch.clamp(self.log_std(h), -20, 2)
std = torch.exp(log_std)
# 重参数化采样
noise = torch.randn_like(mean)
action = mean + std * noise
# 计算 log_prob(含 tanh squashing 的修正,此处简化)
log_prob = -0.5 * (((action - mean) / std) ** 2 + 2 * log_std + torch.log(torch.tensor(2 * 3.1415926)))
log_prob = log_prob.sum(dim=-1, keepdim=True)
return action, log_prob
要点:
- 双 Q 网络:取 min(Q1, Q2) 缓解 Q 值过估计
- Target Network:用 EMA 缓慢更新,提高训练稳定性
- 熵奖励:SAC 自动平衡探索与利用,alpha 可学习或固定
- 策略网络输出高斯分布,通过重参数化采样保证可微
12. 系统设计题¶
以下题目考察面试者的系统架构能力、工程权衡思维和领域知识综合运用能力。
Q94: 设计一个 100Hz 的遥操作系统
【考察点】实时系统、网络传输、人机交互、延迟优化
参考答案:
需求分析: - 100Hz 意味着端到端延迟 < 10ms(控制周期) - 人操作端(主手/VR/动捕) -> 网络 -> 机器人端(从手)-> 传感器反馈 -> 人端 - 需要双边遥操作(haptic feedback)或视觉反馈
系统架构:
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 操作端 │ │ 传输层 │ │ 机器人端 │
│ (主手/动捕) │<---->│ (低延迟网络)│<---->│ (从手控制器) │
└─────────────┘ └─────────────┘ └─────────────┘
↑ ↓
└──────────── 力/触觉反馈 <──────────────┘
关键设计决策:
- 延迟分解与预算
- 传感器采集:~1ms(高频率 IMU/编码器)
- 前向传输:~2-3ms(本地局域网 UDP,或 5G 专网)
- 机器人控制:~1ms(实时控制器,如 EtherCAT)
- 反馈传输:~2-3ms
- 触觉渲染:~1ms
-
总延迟预算需控制在 5-8ms,留 2ms 余量
-
传输层优化
- 使用 UDP 而非 TCP(避免重传延迟)
- 数据包精简:只传输关节角/增量(<100 bytes)
- 预测补偿:操作端做前向预测(kalman filter),补偿网络抖动
-
本地缓冲 + 时间戳同步
-
控制策略
- 位置-位置映射(简单,适合高带宽)
- 位置-力映射(适合接触任务,需要力传感器)
-
混合:自由空间用位置控制,接触空间用力控制
-
安全
- 超时保护:通信中断 > 50ms 自动停止/保持当前姿态
- 速度/力限制:软件层 + 硬件层双保险
-
紧急停止(E-stop)独立通道
-
100Hz 的技术路径
- 控制环在机器人端本地运行(1kHz),遥操作指令以 100Hz 下发作为参考轨迹
- 机器人端用插值/预测填充 100Hz -> 1kHz 的间隙
- 避免"远程直接控制每一个 1kHz 周期",而是"远程规划轨迹,本地跟踪"
Q95: 设计 VLA 模型的推理服务
【考察点】模型服务化、推理优化、并发处理、部署架构
参考答案:
系统架构:
客户端(机器人) 推理服务集群 模型仓库
| | |
|--- HTTP/gRPC ---> | |
| (图像 + 指令) |--- TensorRT / vLLM --|
| | (模型推理) |
|<-- 动作序列 --------| |
核心模块设计:
- API 设计
- 输入:
{image: base64/bytes, instruction: str, robot_type: str, history: optional} - 输出:
{actions: [[dim] x chunk], inference_time_ms: float, confidence: float} -
协议:gRPC(低延迟)或 HTTP/REST(易调试)
-
推理优化
- 模型编译:PyTorch -> ONNX -> TensorRT(FP16/INT8),提升 2-5x
- 批处理(Dynamic Batching):合并多个机器人的请求,提高 GPU 利用率
- KV Cache(对自回归 VLA 如 RT-2):缓存已计算的 attention KV
- 视觉特征缓存:场景变化缓慢时,每隔 N 帧重新计算视觉特征
-
预热:服务启动时预加载模型,避免冷启动
-
并发与扩展
- 单卡部署 1 个模型实例,多卡用负载均衡
- 使用 Triton Inference Server 或 vLLM 管理模型生命周期
-
异步 pipeline:视觉编码、语言处理、动作生成分阶段并行
-
延迟保障
- P99 延迟 < 200ms(对 5-10Hz 控制足够)
- 超时降级:推理超时返回上次有效动作或安全姿态
-
优先级队列:紧急任务(如避障)优先处理
-
监控与可观测性
- 记录每次推理的输入输出(用于后续模型改进)
- 监控延迟分布、GPU 利用率、内存占用
- 异常检测:输出动作超出正常范围时触发告警
Q96: 设计灵巧操作的评估 Pipeline
【考察点】评估指标设计、自动化测试、数据闭环
参考答案:
评估维度设计:
| 维度 | 指标 | 测量方法 |
|---|---|---|
| 任务成功率 | Success Rate | 人工标注 / 自动检测(物体是否在目标位置) |
| 动作质量 | 平滑度(jerk)、路径长度 | 从关节角序列计算 |
| 接触质量 | 接触力分布、滑动检测 | 力/触觉传感器 / 仿真接触检测 |
| 鲁棒性 | 扰动后恢复成功率 | 在操作过程中施加随机外力 |
| 泛化性 | 新物体/新姿态成功率 | 在测试集上评估 |
| 效率 | 平均完成时间 / 步数 | 自动统计 |
自动化评估 Pipeline:
策略模型 → 批量仿真评估(MuJoCo/Isaac)→ 指标计算 → 报告生成
↑ |
└──────── 失败案例筛选 ← 人工复核 ←───┘
- 批量仿真评估
- 并行运行 100-1000 个环境实例(不同初始条件、不同物体)
- 自动检测任务完成:检查物体位姿、接触状态、力传感器读数
-
支持域随机化(摩擦、质量、位置)评估鲁棒性
-
真实世界评估
- 从仿真筛选出的高置信度策略,部署到真实机器人
- 用视觉系统(ArUco / 6D 位姿估计)自动检测结果
-
对于难以自动检测的任务,采用人机协作标注(人工看录像打标签)
-
失败分析
- 自动分类失败模式:感知错误、规划错误、执行错误、接触失败
- 可视化:轨迹回放、力曲线、接触点分布
-
失败案例自动归入训练数据(课程学习)
-
持续迭代(数据闭环)
- 评估结果 -> 识别薄弱环节 -> 针对性数据收集 -> 模型重训练 -> 重新评估
- A/B 测试:新旧策略在相同测试集上对比
13. 2026 前沿论文面试题¶
以下题目基于 2026 年上半年最具影响力的具身智能工作,高频出现在技术二面/三面。
Q97: ZR-0 的 ECoT 监督是什么?
【考察点】ZR-0、Chain-of-Thought、VLA 训练范式
参考答案:
ECoT(Error-Correcting Chain-of-Thought) 是 ZR-0 提出的核心训练技术,用于解决 VLA 在长程任务中的"中间步骤错误累积"问题。
传统 CoT 的问题: - 标准 CoT 让模型输出推理链("我看到杯子在左边 -> 我应该伸手向左") - 但如果模型在第一步推理错误(如误判物体位置),后续步骤会基于错误前提继续执行,导致任务失败
ECoT 的核心设计: 1. 显式推理监督:VLA 在输出动作 token 之前,先输出推理 token(自然语言描述当前状态判断和计划) 2. 错误注入与纠正训练: - 在训练数据中,故意构造"错误推理 -> 正确动作"和"正确推理 -> 错误动作"的配对 - 模型需要学会:(a) 识别推理中的错误;(b) 根据正确推理生成正确动作;(c) 即使看到错误推理也能纠正并输出正确动作 3. 多阶段训练: - 阶段 1:标准行为克隆(动作预测) - 阶段 2:加入 CoT 生成(联合训练推理 + 动作) - 阶段 3:ECoT 强化(错误纠正训练,用 RL 或对抗样本)
面试回答要点: - ECoT 不只是"让模型说话",而是让模型具备"自我纠错"能力 - 实验证明 ECoT 使长程任务(如"拿杯子 -> 倒水 -> 放杯子")的成功率提升 20%+ - 代价:推理 token 增加了序列长度,需要优化推理速度
Q98: Pose-VLA 的两阶段训练有什么好处?
【考察点】Pose-VLA、解耦训练、预训练策略
参考答案:
Pose-VLA 的核心创新是将 VLA 训练解耦为 姿态预训练 + 动作对齐 两个阶段。
阶段 1:姿态潜变量预训练 - 数据:大规模无标签人体/机器人操作视频(如 Ego4D、YouTube 家务视频) - 目标:学习一个 姿态潜变量模型(Pose VAE 或扩散模型),将视频帧映射为低维姿态表示 - 输出:给定一帧图像,模型能预测画面中人体/机器人的关节姿态
阶段 2:机器人动作对齐 - 数据:少量机器人演示数据(如 1k-10k 条轨迹) - 目标:将阶段 1 学到的姿态表示对齐到特定机器人的动作空间 - 方法:冻结(或 LoRA 微调)阶段 1 的视觉编码器,只训练动作输出头
好处分析:
- 数据效率大幅提升
- 阶段 1 利用海量无标签视频(百万级),学到通用的"视觉 -> 姿态"映射
-
阶段 2 只需少量机器人数据即可适配,降低机器人数据采集成本
-
缓解仿真-真实鸿沟
- 阶段 1 在真实视频上训练,视觉表示天然对真实场景鲁棒
-
避免直接在机器人数据上训练导致的过拟合
-
跨形态迁移
- 姿态表示是"形态无关"的(如人体 21 点手部和机器人 16-DOF 手部可以共享高层语义)
-
同一阶段 1 模型可以服务多个机器人平台(人形、机械臂、灵巧手)
-
推理可解释性
- 中间姿态表示可作为调试工具:可视化模型"看到"的目标姿态
- 便于定位失败原因(是姿态估计错了,还是动作映射错了)
面试回答要点: - 两阶段训练的本质是"先学通用表示,再学特定映射" - 与 OpenVLA 的"预训练 VLM + 微调动作头"思路类似,但 Pose-VLA 的预训练目标更聚焦(姿态 vs 通用视觉-语言) - 代价:阶段 1 需要大规模视频数据;两个阶段之间的表示对齐是关键挑战
Q99: DexSim2Real 如何利用基础模型做迁移?
【考察点】DexSim2Real、基础模型、Sim-to-Real、奖励设计
参考答案:
DexSim2Real 的核心思路是:利用预训练的 视觉-语言基础模型(如 GPT-4V、CLIP) 作为"教师",在 Sim-to-Real 迁移的多个环节中提供监督信号,减少人工设计成本。
具体应用环节:
- 仿真中的自动奖励生成
- 传统方法:人工设计稠密奖励函数(距离目标多远、接触力多大)
- DexSim2Real:将仿真场景的 RGB 图像 + 任务描述输入 GPT-4V,让基础模型判断"当前状态离目标还有多远"
- 基础模型的输出(如"手指已经接近物体,但还没接触")被转化为标量奖励信号
-
好处:无需为每个新任务重写奖励函数;奖励更贴合人类直觉
-
课程学习指导
- 基础模型评估当前策略的"能力边界",自动设计课程:
- 初期:简单场景(大物体、无遮挡)
- 中期:增加难度(小物体、背景干扰)
- 后期:接近真实场景(复杂光照、纹理)
-
基础模型通过对比仿真和真实图像,判断"这个策略是否 ready for real"
-
真实世界的失败诊断与修正
- 部署到真实后,基础模型观察失败案例(视频 + 任务描述),诊断失败原因:
- "抓取位置太偏" -> 调整抓取姿态
- "用力过猛导致物体滑动" -> 调整力控制参数
-
诊断结果自动反馈到仿真中,调整训练参数或奖励函数,重新训练
-
域差距量化
- 用 CLIP/GPT-4V 对比仿真图像和真实图像的 embedding 差异
- 差异大的区域(如光照、纹理)作为域随机化的重点方向
面试回答要点: - DexSim2Real 不是用基础模型直接控制机器人,而是用基础模型"指导"传统 RL/IL 训练 - 关键假设:基础模型具备足够的视觉-语言理解能力,能判断任务进度和失败原因 - 局限性:基础模型 API 调用延迟高(不适合实时控制),只用于离线训练和诊断
Q100: MoDE-VLA 的 Mixture-of-Experts 怎么工作?
【考察点】MoDE-VLA、MoE、灵巧操作、条件计算
参考答案:
MoDE(Mixture-of-Dexterous-Experts) 是 MoDE-VLA 的核心架构,解决"单一策略难以兼顾多种灵巧操作模式"的问题。
问题背景: - 灵巧操作包含多种接触模式:捏取(pinch)、包络抓取(enveloping)、按压(push)、拧转(twist) - 每种模式需要不同的手指协调策略(如捏取用指尖,包络用指节+掌面) - 单一神经网络试图同时学习所有模式,容易导致"模式混淆"(一个动作同时试图捏和包络,结果失败)
MoDE 架构:
视觉 + 语言指令
|
v
┌─────────────────┐
│ 共享编码器 │ (处理图像和文本,提取任务特征)
└─────────────────┘
|
v
┌─────────────────┐
│ 门控网络 G │ (根据任务特征,决定激活哪些专家)
│ 输出: softmax │
│ (w_1, w_2, ... w_k)
└─────────────────┘
|
v
┌──────────────────────────────────────────┐
│ 专家池 (Expert Pool) │
│ Expert 1: 捏取专家 (pinch/grasp) │
│ Expert 2: 包络专家 (enveloping) │
│ Expert 3: 按压专家 (push/press) │
│ Expert 4: 拧转专家 (twist/rotate) │
│ ... │
│ 每个专家是一个小型 Transformer/MLP │
└──────────────────────────────────────────┘
|
v
加权聚合输出 = sum(w_i * Expert_i(x))
|
v
动作生成头
门控网络的设计: - 输入:共享编码器输出的任务特征 + 语言指令 embedding - 输出:K 个专家的权重(softmax 归一化) - 关键:门控是稀疏的——每次只激活 1-2 个专家(top-k routing),减少计算量
训练策略:
- 专家预训练
- 每个专家先用对应操作类型的数据单独预训练(如捏取专家只用 pinch 数据)
-
确保每个专家在专属领域有足够能力
-
联合训练
- 所有专家 + 门控网络一起训练
-
损失函数:行为克隆 loss + 负载均衡 loss(防止所有请求都路由到同一个专家)
-
负载均衡(Load Balancing)
- 添加辅助 loss:鼓励门控网络均匀使用所有专家
- 公式:
L_aux = alpha * sum(f_i * P_i),其中f_i是专家 i 被选中的频率,P_i是平均路由概率
面试回答要点: - MoDE 的灵感来自 NLP 中的 MoE(如 Switch Transformer),但针对机器人操作做了适配: - 专家不是按"token"路由,而是按"操作类型"路由 - 专家输出的是动作分布,需要保证连续性(不同专家输出的动作在边界处平滑过渡) - 优势:每个专家只需学习简化的问题(单模态),整体表达多模态策略 - 挑战:门控网络的决策错误会导致"选错专家"(如把拧转任务路由到按压专家),需要鲁棒的门控设计