LeRobot入门教程 15:LeRobot 强化学习 (SAC)

目录:00_LeRobot入门教程_目录.md

1. 模仿学习和强化学习的区别

前面几册的内容(数据集、策略、微调)都属于模仿学习:照着人的演示学。它的天花板是演示数据的水平——人做不到的,模型也做不到。

强化学习(RL)换了个思路:不看演示,自己试,做对了给奖励。理论上能超过人类演示,代价是样本效率极低,真机上要几万次尝试。

模仿学习强化学习
数据人的演示自己采的轨迹 + 奖励
奖励信号不需要必须有(真机靠奖励模型)
优点快、稳、易复现能超过演示水平
缺点上限受演示限制慢、不稳定、真机有风险

2. SAC 是什么

SAC(Soft Actor-Critic)是连续控制里最常用的 off-policy 算法之一,三个角色:

角色类作用
ActorGaussianActorPolicy输出动作的高斯分布,边学边探索
Critic算法内部估计「这个状态动作值多少」,SAC 用双 Q 网络缓解高估
经验池ReplayBuffer存历史 (s, a, r, s'),反复采样学习

「Soft」指的是在目标里加了熵项:鼓励策略保持一定随机性,别过早收敛到局部最优。

3. 一段最小接线演示

下面这段不是真训练,是「把管线接起来看能不能跑」的最小例子:随机数据的经验池 + 5 次更新。

import torch
from lerobot.configs.types import FeatureType, PolicyFeature
from lerobot.policies.gaussian_actor.configuration_gaussian_actor import GaussianActorConfig
from lerobot.policies.gaussian_actor.modeling_gaussian_actor import GaussianActorPolicy
from lerobot.rl import ReplayBuffer, RLTrainer, OnlineOfflineMixer, make_algorithm, make_algorithm_config
from lerobot.utils.constants import ACTION, OBS_STATE

cfg = GaussianActorConfig(device="cuda")
cfg.input_features = {OBS_STATE: PolicyFeature(type=FeatureType.STATE, shape=(8,))}
cfg.output_features = {ACTION: PolicyFeature(type=FeatureType.ACTION, shape=(7,))}
policy = GaussianActorPolicy(cfg).to("cuda")

sac = make_algorithm_config("sac")
sac.policy_config = cfg
algo = make_algorithm(cfg=sac, policy=policy)

rb = ReplayBuffer(capacity=2000, device="cuda", state_keys=[OBS_STATE], use_drq=False)
for _ in range(500):
    rb.add(state={OBS_STATE: torch.randn(1, 8)}, action=torch.rand(1, 7) * 2 - 1, reward=0.0,
           next_state={OBS_STATE: torch.randn(1, 8)}, done=False, truncated=False)

trainer = RLTrainer(algo, OnlineOfflineMixer(online_buffer=rb, online_ratio=1.0), batch_size=32)
for s in range(5):
    st = trainer.training_step()
    print(f"step {s}: critic_loss={st.losses['loss_critic']:.2f}")
step 0: critic_loss=35.86
step 1: critic_loss=29.99
step 2: critic_loss=20.88
step 3: critic_loss=15.41
step 4: critic_loss=9.47

4. 逐段解释

定义 actor 的输入输出:

cfg.input_features  = {OBS_STATE: PolicyFeature(type=FeatureType.STATE, shape=(8,))}
cfg.output_features = {ACTION:    PolicyFeature(type=FeatureType.ACTION, shape=(7,))}

这里的 8 和 7 就是 08 册《数据集》里 observation.state 和 action 的维度。LeRobot 用 PolicyFeature 显式声明特征类型和形状,好处是同一个 actor 类能适配不同机器人。

造算法:

sac = make_algorithm_config("sac"); sac.policy_config = cfg
algo = make_algorithm(cfg=sac, policy=policy)

make_algorithm_config 按名字取算法配置(还支持 tdmpc 等),把 actor 配置塞进去,再实例化——这样 critic、目标网络、优化器都由算法自己建。

经验池:

rb = ReplayBuffer(capacity=2000, device="cuda", state_keys=[OBS_STATE], use_drq=False)
  • capacity=2000:最多存 2000 条转移;
  • device="cuda":经验池放在显存里,采样不经过 CPU,快很多;
  • state_keys=[OBS_STATE]:告诉它状态字典里哪些键是状态(图像观测时这里会有多个键);
  • use_drq=False:DRQ 是图像增强技巧,这里用低维状态就不需要。

接着往里塞 500 条随机数据:状态是 randn(1, 8),动作是 rand(1,7)*2-1(映射到 [-1,1]),奖励全 0。这些数据没有任何物理意义,只是为了把 buffer 填起来。

训练:

trainer = RLTrainer(algo, OnlineOfflineMixer(online_buffer=rb, online_ratio=1.0), batch_size=32)
for s in range(5):
    st = trainer.training_step()

OnlineOfflineMixer 是「在线 + 离线数据混合采样」的封装,online_ratio=1.0 表示全部用在线数据。真机上常见做法是混一部分离线演示数据,缓解冷启动。

5. critic loss 从 35.86 降到 9.47 说明什么

step 0: critic_loss=35.86
step 1: critic_loss=29.99
step 2: critic_loss=20.88
step 3: critic_loss=15.41
step 4: critic_loss= 9.47

6. 真机 HIL-SERL

LeRobot 的真机 RL 走的是 HIL-SERL(Human-In-the-Loop SERL)路线:机器自己练,人偶尔接管纠正。它分两个进程:

python -m lerobot.rl.learner --config_path=train_config_hilserl_so100.json
python -m lerobot.rl.actor   --config_path=train_config_hilserl_so100.json
进程跑在哪干什么
learner训练机(可以是有 GPU 的服务器)从经验池采样、更新 actor/critic
actor连着机器人的那台读相机、发动作、往经验池写数据

两者通过队列/网络通信,所以训练和控制在物理上可以分开,这对真机很重要:机器人那台机器只需要跑推理,不需要扛训练负载。

train_config_hilserl_so100.json 里要配的东西包括:机器人型号和串口、相机、奖励模型、学习率、buffer 大小、人工介入的开关方式。第一次跑之前务必先用仿真验证整套配置。

7. 真跑 RL 的前提

  1. 一个能用的奖励信号:仿真用真值,真机用 14 册的奖励模型,并且验证过它的排序和人类判断一致;
  2. 安全边界:动作限幅、工作空间限制、急停;
  3. 足够的时间:真机 RL 常以「小时」为单位计;
  4. 检查点策略:定期存,RL 训崩是常态;
  5. 先仿真后真机:同一个配置先在 LIBERO 里跑到能收敛,再上真机。