(Lerobot)ACT算法模型理论与对应的代码分析
(Lerobot)ACT算法模型理论与对应的代码分析
理论解读
关于ACT算法的理论,网络上其实已经有太多太多的讲解。这里我也给出我自己的理解。只是自己才疏学浅,或许有不到位的理解,还请各位大佬指出。

ACT算法架构如上图所示,它的本质就是一个CVAE架构。提到CVAE架构,首先就要知道VAE架构和AE架构。
1.AE自编码器模型

1.1直观理解
AE架构如上图所示,他是一种无监督学习模型,主要用来学习输入数据的有效表示,即通过学习可以得到很好表示输入数据的“隐变量”。
该模型的运作逻辑是这样的:假设输入的是一张图片,通过编码器网络映射到一个低维的隐变量。这个隐变量再作为解码器的输入,通过解码器重新映射回原来的输入。即:模型输入为1张人脸,编码器的作用是“压缩”,解码器的作用是“还原”。输入是什么,输出就尽量是什么
所以,训练模型的损失函数就是
1.2数学证明
此外,我们也可以从最大似然估计的角度去推导损失函数:
假设在给定隐变量z的条件下,数据x服从以x'为均值、方差为σ²的高斯分布,即:
由于服从高斯分布,根据展开可以得到:
其中μ就是x',也就是模型的输出数据,最终可以等价为:
极大化似然函数,相当于最小化“负数的似然函数”,前面加一个负号,转化为损失函数。
AE编码器的特点:
- 模型的核心是“压缩和还原”。
- 编码器输出的低维隐向量在隐空间中往往不连续,不规则。随机采样一个隐变量,生成的图片是模糊不堪的。

如图片所示,假设输入的数据经过编码器形成隐变量,在一个二维的隐空间中呈现出蓝色的小点。可以看到它在隐空间的分布是极其没有规律,不连续的。此时如果从隐空间中随机采样一个隐变量(如图片中的红色点),生成出来的图片是很糟糕的。
2.VAE变分自编码器

VAE算是AE的一种变体,前面我们有提到:AE编码器生成的隐向量是不连续不规则的,那么有没有一个办法使得编码器压缩到的隐向量是连续并且规律的呢???
有的兄弟,有的!!如果我们编码器输出的不直接是隐向量,而是让编码器生成一个分布(假设为高斯分布),我们再从这个分布中采样隐变量z,那么我们得到的隐变量z就是规律的,连续的!!
2.1直观理解

现在编码器输出的已经一种高斯分布了,我们从隐空间中采样一个点。如果这个点恰好在两个分布的重叠处,那么生成出来的图片则会有2个分布对应数据的特征。如图片所示,红色箭头中我们采样到的隐变量恰好是2个分布的交接处,那么生成的图片就会存在二者特征。使得模型的生成泛化能力得到大大提升。
但是问题来了,我要怎么知道我应该往隐向量里面的哪个空间处采样呢,尽管我已经知道编码器输出是一个分布,但是每个训练样本对应的分布它的均值和方差都是不一样的,这些分布位于隐空间的哪个部分,我应该在哪里对隐变量进行采样??在隐空间里面,还会不会存在某些空间是没有被分布覆盖的??如果存在的话,我随机采样一个隐空间,是不是也会像VE那样生成糟糕的图片

VAE的解决方法如上,让每一个训练样本的高斯分布都尽量靠近多元标准正态分布(图片黄色处),这样一来,我们只要在隐空间的多元标准正态分布采样隐变量z,就可以解决上述的问题了。
总结一下——VAE编码器主要就做2点:
一个是让训练样本下的多元高斯分布靠近多元标准正态分布;
一个是让模型输出的图片尽可能与模型输入相似;
所以,我们的损失函数就可以这样定义:
其中,KL散度用来衡量训练样本下的多元高斯分布与多元标准正态分布的距离,这个距离我希望它越小越好。
后面的式子对应让模型输出的图片尽可能与模型输入相似,我希望它越大越好
2.2数学证明
前面已经提到,假设隐变量z服从标准正态分布(先验分布),即P(z) = N(0,1)
假设Q(z|x),P(x|z)同样服从正态分布,即P(x|z) = Q(z|x) = N(μ,σ²)
那么通过极大化似然的思想:
极大化似然,对应就是极小化负数的似然:
通过一系列数学推导(变分下届、jenson不等式),最后得到这两个式子。
接着分析KL散度:
假设q(z|x)服从多元高斯分布,且各个zi之间相互独立。即:
由于各个zi之间相互独立,所以:
我们得到了q(z|x)的表达式,再看p(z):
最终我们得到了KL散度的具体表达式:
下面3个式子分别进行化简:
式子1:
分析:随机变量zi²的期望就等于其均值的平方+方差的平方
式子2:
分析:由于式子是在q(z|x)下对方差进行求期望,但是要注意的是,这里的方差并不是zi的函数,而是输入x的函数,所以期望符号可以化简掉
(Lerobot)ACT算法模型理论与对应的代码分析
式子3:
分析:如果你知道D(z) = E[(z - E(x))²] = σ²的话,就可以化简为1
最后我们得到了KL散度最终表达式:

对于损失函数的第二个式子
其实可以这样理解,参考我在上一个部分讲的AE模型的损失函数可以发现P(x|z)是我们假设的多元高斯分布,通过最大化似然的思想,可以转化为模型输入输出的MSE损失。
VAE模型的特点:
- 编码器不再输出一个隐变量z,而是输出一个概率分布,z则是这个分布的采样值。好处是z是连续的规则的。
- VAE 是无条件生成,难以指定生成“某一类”样本;且重建往往偏模糊
3.CVAE模型
CVAE模型和VAE模型在数学原理上别无二致,只是在模型结构上,编码器和解码器格外增加了一个条件C输入。
4.ACT模型
了解完自编码器的家族史,我们再回过头来看ACT模型,它的本质其实和CVAE别无二致。

4.1Encoder

输入是CLS参数矩阵,嵌入后的电机姿态,嵌入后的动作序列,通过标准的transformer架构,控制模型的输出,只输出第一个。然后输出为高斯分布。
即:
其中,ot代表出去图像外的观测,只包括关节数据。在CVAE中扮演着条件C的角色
4.2Decoder

输入是(图像,嵌入后的电机姿态),隐变量z,通过标准的transformer-Encoder-Decoder架构后输出未来k时刻的动作序列
即:
其中,ot代表图像+关节数据,扮演CVAE中的条件C角色。
对应的目标函数为:
回过头来看CVAE的损失函数:

是不是一模一样呢!
源码分析
接下来我们分析一下Lerobot对ACT策略的封装。具体的代码可以在lerobot-main/src/lerobot/policies/act中查看:
一共有3个文件,我们一一来讲解

configuration_act.py
ACTConfig是 ACT 机器人控制策略的“控制面板”。它定义了模型架构的所有关键参数、数据格式、训练和推理的规则。它本身是 HuggingFace 风格的预训练配置类,继承了 PreTrainedConfig,便于模型的保存、加载和版本管理。
这个类的核心是集中管理并验证 ACT 模型的所有可配置项,包含以下几大块:
- 输入/输出结构
- 模型架构参数
- 推理行为控制
- 训练超参数
参数解析
A. 输入/输出与数据流 (Input/Output & Data Flow)
- n_obs_steps(int = 1)
作用:每次调用模型时,输入多少“帧”的观测数据。
说明:目前固定为1,仅使用当前时刻的观测。代码中已校验 (n_obs_steps != 1会报错),表明该功能尚未实现。
- chunk_size(int = 100)
作用:模型一次性预测的未来动作序列的长度。
重要性:这是 ACT 的核心思想。模型是“前瞻性”的,一次性规划出较长的动作轨迹。
- n_action_steps(int = 100)
作用:每次模型被调用后,实际执行的动作步数。
与 chunk_size的关系:必须 <= chunk_size。
典型工作流:模型预测100步 (chunk_size=100),但只执行前50步 (n_action_steps=50),然后重新预测,实现闭环控制与纠偏。
- normalization_mapping(dict)
作用:定义不同类型输入数据的标准化方式。
默认:
"VISUAL"(图像):均值-标准差归一化 (减去均值除以标准差)。
"STATE"(机器人状态) 和 "ACTION"(动作):均值-标准差归一化。
B. 模型架构 (Model Architecture)
视觉主干网络 (Vision Backbone)
-
vision_backbone(str = "resnet18"): 使用的 CNN 模型,用于从原始图像中提取特征。
-
pretrained_backbone_weights(str = "ResNet18_Weights.IMAGENET1K_V1"): 使用在 ImageNet 上预训练的权重初始化,可加速训练、提升效果。
Transformer 核心参数 (Transformer Core)
- dim_model(int = 512): Transformer 的核心隐藏维度,决定了模型的表征能力。
- n_heads(int = 8): 多头注意力机制中的“头”的数量,让模型从不同角度关注信息。
- dim_feedforward(int = 3200): Transformer 内部前馈网络层的维度,通常比 dim_model大。
- n_encoder_layers(int = 4), n_decoder_layers(int = 1):
Encoder 层数:处理环境观测的 Transformer 层数。
Decoder 层数:生成动作序列的 Transformer 层数。注意:原始 ACT 代码有Bug,实际只用一层,这里保持为1以复现。
变分自编码器 (Variational Auto-Encoder, VAE)
- use_vae(bool = True): 是否启用VAE 训练目标。开启时,模型在训练中会学习动作的概率分布,从而能生成更多样、更鲁棒的动作。
- latent_dim(int = 32): VAE 潜在空间的维度,是编码动作序列的“隐变量”大小。
- n_vae_encoder_layers(int = 4): VAE 编码器(将动作编码到潜在空间)的Transformer 层数。
C. 推理控制 (Inference Control)
- temporal_ensemble_coeff(float | None = None)
作用:时间集成的系数。None表示关闭。当设置为 0.01时,会对多次预测的动作进行指数加权平均,可以过滤噪声,使动作更平滑。
重要限制:开启时,n_action_steps必须为1,因为需要在每一步都进行模型预测来实现集成。
D. 训练与损失 (Training & Loss)
dropout(float = 0.1): Dropout 比例,防止模型过拟合。
kl_weight(float = 10.0): KL 散度损失的权重。当启用 VAE 时,总损失 = 重建损失 (L1) + kl_weight* KL 损失。这个值控制“动作精度”与“潜在空间规范性”之间的权衡。
optimizer_lr: 优化器(AdamW)的学习率。
重要的属性方法
- post_init()
作用:在对象初始化后自动调用,进行参数验证。
验证规则:
vision_backbone必须是 ResNet 系列。
如果启用时间集成 (temporal_ensemble_coeff不为 None),则 n_action_steps必须为1。
n_action_steps不能大于 chunk_size。
必须提供至少一种输入(图像或环境状态)。
- validate_features()
作用:校验输入特征。必须至少包含图像特征或环境状态特征。
- get_optimizer_preset()
作用:返回训练优化器(AdamW)的预设配置。
modeling_act.py
模型架构解读
这部分主要讲述模型的具体架构是怎样的:
Transformer
Used alone for inference
(acts as VAE decoder
during training)
┌───────────────────────┐
│ Outputs │
│ ▲ │
│ ┌─────►┌───────┐ │
┌──────┐ │ │ │Transf.│ │
│ │ │ ├─────►│decoder│ │
┌────┴────┐ │ │ │ │ │ │
│ │ │ │ ┌───┴───┬─►│ │ │
│ VAE │ │ │ │ │ └───────┘ │
│ encoder │ │ │ │Transf.│ │
│ │ │ │ │encoder│ │
└───▲─────┘ │ │ │ │ │
│ │ │ └▲──▲─▲─┘ │
│ │ │ │ │ │ │
inputs └─────┼──┘ │ image emb. │
│ state emb. │
└───────────────────────┘
架构和transformer架构一致,这里不多赘述
processor_act.py
主要功能:
创建预处理管道:
1、重命名观察值(虽然当前是空映射)
- 添加批次维度,使数据符合模型输入要求
- 将数据移动到指定设备(如 GPU)
- 对输入和输出特征进行归一化,提高模型训练和推理的稳定性
2、创建后处理管道:
- 对模型输出的动作进行反归一化,恢复到原始尺度
- 将数据移动回 CPU,方便后续处理或控制机器人

浙公网安备 33010602011771号