ACT(Action Chunking with Transformers)和 Diffusion Policy(扩散策略)是目前具身智能(Embodied AI)和机器人模仿学习(Imitation Learning)领域最经典、最主流的两个基线模型。
在面试中,通常会重点考察对多模态动作分布建模、时序依赖处理、以及模型工程落地的理解。
一、 核心原理与架构对比类
1. 请对比 ACT 和 Diffusion Policy 的核心思想、优缺点及适用场景。
参考答案:
- ACT :基于 CVAE(条件变分自编码器) 架构。通过引入隐变量 z 来建模动作的多峰分布 ,结合 Action Chunking 预测动作序列。
- 优点:推理速度极快(一次前向传播即可输出一个 Chunk),实时性好;架构相对简单,训练稳定。
- 缺点 :CVAE 的生成能力上限受限于高斯假设,在处理极度复杂、多峰且形状不规则的动作分布时,可能会出现动作模糊(Blurring)。
- Diffusion Policy (DP) :将动作生成建模为条件去噪扩散过程。通过迭代去噪,从纯噪声中逐步恢复出动作序列 。
- 优点:生成质量极高,能完美拟合复杂的多峰分布;生成的动作轨迹非常平滑,符合物理直觉;在长视野(Long-horizon)复杂任务上表现优异。
- 缺点 :推理需要多步迭代,延迟较高;训练和调参(如噪声调度)相对复杂。
- 适用场景:ACT 适合对实时性要求高、动作相对连贯的中低频任务(如桌面抓取);DP 适合对动作精度、平滑度要求极高,或任务逻辑极其复杂的场景(如精密装配、柔性物体操作)。
2. 为什么在机器人模仿学习中,直接回归动作(如 MSE Loss)效果不好?ACT 和 DP 是如何解决这个问题的?
考察点 :对模仿学习核心痛点(多峰分布坍塌)的理解。
参考答案:
- MSE 的缺陷 :当面对多模态动作分布时(例如:桌上有个障碍物,机器人可以从左边绕,也可以从右边绕),MSE Loss 会迫使模型预测这两个动作的均值。这个"均值"动作往往会直接撞上障碍物,导致任务失败。
- ACT 的解决方式 :引入 CVAE 的隐变量 z。在推理时,从先验分布中采样不同的 z,Decoder 会基于不同的 z 生成完全不同的动作分支,从而避开均值化陷阱。
- DP 的解决方式 :扩散模型在去噪过程中,模型会根据当前条件(观测)被吸引到不同的数据流形(即不同的动作模式)上,从而自然地输出多峰分布中的某一个合理动作。
3. ACT 中的 Action Chunking(动作分块)具体解决了什么问题?Chunk size 应该怎么选?
考察点:对时序误差累积的理解及超参调优经验。
参考答案:
- 解决的问题 :
- 误差累积(Compounding Error):如果每次只预测单步动作,微小的预测误差会在多步执行后迅速放大。预测一个 Chunk(如 10 步),可以大幅减少模型推理次数,降低累积误差。
- 时间相关性(Temporal Correlation):机器人的动作在时间上是高度连续的。Chunking 强制模型在生成动作时考虑未来的时序依赖,使动作更平滑。
- Chunk size 的选择 :这是一个 Trade-off。
- 太大:模型难以预测长远的未来,导致 Chunk 后半段动作质量下降;且机器人对环境的突发变化反应迟钝(缺乏闭环反馈)。
- 太小:失去了减少误差累积的优势,退化为单步预测。
- 经验值:通常在 10 到 100 步之间(对应 0.5秒 - 5秒),具体取决于任务的控制频率和动态变化程度。
4. 简述 ACT (Action Chunking with Transformers) 的网络结构和 Loss 函数;解释 KL 散度在损失函数中的作用,如果 KL 散度太大或太小会导致什么问题?如何缓解?
- 考察点:前者是对 ACT 论文细节的掌握;KL散度问题则是对 VAE 底层数学原理及训练 Trick 的掌握(高频考点)
- 答题要点 :
- 结构 :ACT 本质上是一个条件变分自编码器(CVAE) 结合 Transformer。它包含一个 Encoder(处理观测)和一个 Decoder(生成动作 chunk)。引入了一个低维隐变量 z。
- 前向过程 :观测通过 Encoder 得到后验分布
,采样得到 z,z 加上位置编码后输入 Transformer Decoder,解码出动作 chunk。
- Loss 函数 :包含两部分。一是动作重建损失 (如 L1 Loss,计算预测动作与 GT 的差距);二是 KL 散度损失 (约束后验分布
接近先验分布
,保证隐空间的平滑性)。
- KL散度在损失函数中的作用 :KL 散度用于正则化隐空间,迫使 Encoder 输出的后验分布
接近先验分布
(通常是标准高斯分布),保证了推理时从
采样出的 z 是有效的。
- KL 太大 :模型会过度依赖先验
,而忽略观测 x 和真实动作 a 的信息,导致后验坍塌(Posterior Collapse),生成的动作变得模糊、缺乏细节。
- KL 太小:隐空间变得不连续,存在大量空洞。推理时从先验采样的 z 很容易落入空洞,导致 Decoder 生成无效或危险动作。
- 缓解方案 :
- KL 退火(KL Annealing) :训练初期将 KL 权重设为 0 或极小值,让模型先拟合数据(减小重建误差),然后随着训练进行,逐渐将 KL 权重增加到目标值(如
)。
- Free bits:限制 KL 散度的下限,防止其过小。
- KL 退火(KL Annealing) :训练初期将 KL 权重设为 0 或极小值,让模型先拟合数据(减小重建误差),然后随着训练进行,逐渐将 KL 权重增加到目标值(如
二、 算法对比与场景选择
5. ACT 和 Diffusion Policy 都使用了 Action Chunking,它们在生成动作的机制上有什么本质区别?
- 考察点:算法底层数学逻辑的对比。
- 答题要点 :
- ACT :基于 CVAE 架构 。通过一次前向传播(采样隐变量 z + Decoder 解码)直接输出动作 chunk。本质上是单步生成(非自回归),速度快,但多模态表达能力受限于隐变量 z 的维度。
- Diffusion Policy :基于 迭代去噪。从纯高斯噪声开始,经过 T 步(如 10-100 步)迭代逐步去噪生成动作。本质上多步生成,能够拟合极其复杂的多模态分布,但推理速度慢。
6. 在处理"多模态动作分布"(例如:障碍物在左边时可以从右边绕,在右边时可以从左边绕)时,两者分别是如何解决的?
- 考察点:对多模态(Multimodality)问题的深入理解。
- 答题要点 :
- ACT :通过隐变量 z 来捕获多模态。在推理时,从先验分布
中采样不同的 z,从而生成不同的动作轨迹。但如果 z 维度太低,无法覆盖所有模态;如果太高,又容易过拟合或导致动作不平滑。
- Diffusion Policy :扩散模型天生具有极强的多模态拟合能力。在推理时,从不同的初始噪声
出发,去噪过程会自然收敛到不同的数据模态上,不需要显式设计隐变量,能更好地覆盖长尾分布。
- ACT :通过隐变量 z 来捕获多模态。在推理时,从先验分布
7. Diffusion Policy 是如何将动作生成 建模为扩散过程的?条件(观测)是如何注入的?
- 考察点:对扩散模型在控制领域应用的理解。
- 答题要点 :
- 建模 :将动作序列
视为数据。前向过程逐步加入高斯噪声直到变成纯噪声
;反向过程训练一个神经网络
预测每一步加入的噪声。
- 条件注入 :将当前观测(图像、本体感觉)通过视觉/状态编码器提取特征,作为条件来引导去噪过程。条件注入方式通常有:*FiLM 层 (对特征进行仿射变换)、Cross-Attention (将观测特征作为 K/V,动作特征作为 Q)、或者直接 **Concat,*拼接后将条件特征注入到 U-Net/Transformer 的去噪网络中。
- 建模 :将动作序列
三、工程实现与调优 Trick
8. Diffusion Policy 的推理延迟较高,在实际机械臂控制(如要求 20Hz,即 50ms 内完成推理)中,有哪些加速方案?
答题要点:
- 减少采样步数 :放弃 DDPM,使用 DDIM 或更先进的 ODE 求解器(如 DPM-Solver++, UniPC),可以将采样步数从 100 步大幅压缩到 5-10 步。
- 动作分块(Action Chunking)+ 滑动窗口:一次预测较长的动作序列(如 16 步),执行时采用滑动窗口(如每次执行 8 步,保留 8 步作为下一步的先验),从而降低模型调用频率。
- 模型蒸馏 :
- 使用 Consistency Models(一致性模型) 技术,训练一个只需 1-2 步即可生成的蒸馏模型。
- 将 DP(教师)的知识蒸馏给一个轻量级的 MLP 或小型 Transformer(学生)。
- 工程加速:使用 TensorRT 进行算子融合和 FP16/INT8 量化;优化视觉编码器的推理(如使用更小的 ResNet 或 MobileViT)。
9. 手写 ACT 的 CVAE 重参数化 Trick
答题要点:
1) CVAE的重参数化引入:
CVAE 引入了条件 c (在 ACT 语境下,c 通常包含历史状态、观测,甚至动作 Action )。 重参数化 Trick 的核心思想是 :将随机性从参数中剥离出来,转移到一个固定的外部噪声上。
编码器输出的后验分布是一个高斯分布:,若直接让网络输出均值
和方差
,然后进行采样
,此时 z 的生成过程包含随机采样,梯度无法回传。
重参数化做法(可导):
引入一个外部辅助变量 ,让它服从标准正态分布
。然后通过一个确定性的数学变换来生成 z:
其中,⊙ 表示逐元素相乘。
为什么这样就解决了问题?
- 随机性外置 :现在的随机性来自于
,而
是从外部采样的,不依赖于网络参数
。
- 计算图连通 :z 变成了关于
、
和
的确定性函数 (只是简单的加法和乘法)。因此,梯度可以顺畅地通过 z 反向传播到
和
,进而更新编码器网络
的参数。
2)pytorch手写实现重参数化:
核心 5 行代码:重参数化 Trick,将不可导的采样操作转化为可导的确定性计算:
python
import torch
def reparameterize(mu, logvar):
"""
CVAE 核心重参数化 Trick
:param mu: 均值向量 (Batch, Latent_Dim)
:param logvar: 对数方差向量 (Batch, Latent_Dim),即 log(σ^2)
:return: 采样后的隐变量 z
"""
# 1. 计算标准差 σ = exp(0.5 * log(σ^2))
std = torch.exp(0.5 * logvar)
# 2. 采样标准正态分布噪声 ε ~ N(0, I)
eps = torch.randn_like(std)
# 3. 重参数化: z = μ + σ * ε
return mu + eps * std
# 计算 KL 散度 (解析解,不需要重参数化)
def kl_divergence(mu, log_var):
# -0.5 * sum(1 + log(sigma^2) - mu^2 - sigma^2)
return -0.5 * torch.sum(1 + log_var - mu.pow(2) - log_var.exp(), dim=-1)
# 越疆 x_trainer 平台的 kl 散度代码详解:https://chat.qwen.ai/c/6948d428-49dc-4680-9db9-ef976250e1fe
# mu 和 logvar 通常是 2D 张量 (batch_size, latent_dim)。
# 如果检测到是 4D 张量,使用 .view() 展平为 2D 张量 (batch_size, channels * height * width)。
def kl_divergence(mu, logvar):
batch_size = mu.size(0)
assert batch_size != 0
if mu.data.ndimension() == 4:
mu = mu.view(mu.size(0), mu.size(1))
if logvar.data.ndimension() == 4:
logvar = logvar.view(logvar.size(0), logvar.size(1))
# 计算的是每一个样本在每一个隐变量维度上的独立 KL 散度。
klds = -0.5 * (1 + logvar - mu.pow(2) - logvar.exp())
# 总 KL 散度 - 用于最终 Loss
total_kld = klds.sum(1).mean(0, True)
dimension_wise_kld = klds.mean(0)
mean_kld = klds.mean(1).mean(0, True)
return total_kld, dimension_wise_kld, mean_kld
注意:使用 logvar 而非 var 或 std (数值稳定性 Trick)
代码体现:std = torch.exp(0.5 * logvar)