LeRobot documentation

HIL-SERL 真实机器人训练工作流指南

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

HIL-SERL 真实机器人训练工作流指南

在本教程中,你将使用 LeRobot 完整体验 Human-in-the-Loop Sample-Efficient Reinforcement Learning (HIL-SERL) 工作流。你只需几个小时,即可掌握如何在真实机器人上使用 RL 训练策略。

HIL-SERL 是一种样本高效的强化学习算法,它将人类演示与在线学习及人类干预相结合。该方法从少量人类演示开始,利用这些演示训练一个奖励分类器,随后采用 actor-learner 架构,允许人类在策略执行期间进行干预,以引导探索并纠正不安全行为。在本教程中,你将使用游戏手柄在学习过程中提供干预并控制机器人。

它结合了三个关键要素:

  1. 离线演示与奖励分类器:少量人类遥操作片段加上基于视觉的成功检测器,为策略提供了经过塑形的初始点。

  2. 带有人工干预的机器人端执行器/学习器循环:分布式 Soft Actor Critic (SAC) 学习器更新策略,同时执行器在物理机器人上进行探索;人类可以随时介入,以纠正危险或无效的行为。

  3. 安全与效率工具:关节/末端执行器(EE)边界、感兴趣区域(ROI)裁剪预处理以及 Trackio 监控,确保数据可用且硬件安全。

这些要素共同使 HIL-SERL 达到了接近完美的任务成功率,并且比仅基于模仿的基线方法具有更快的循环时间。

HIL-SERL workflow

HIL-SERL 工作流,Luo 等人 2024

本指南提供了逐步说明,介绍如何使用 LeRobot 的 HilSerl 实现来训练机器人策略,并在真实机器人上进行训练。

我需要哪些内容?

  • 游戏手柄(推荐)或键盘,用于控制机器人
  • Nvidia GPU
  • 配备从动臂和主臂的真实机器人(如果使用键盘或游戏手柄,则为可选项)
  • 用于运动学包的机器人 URDF 文件(请查看 lerobot/model/kinematics.py)

我可以训练哪些类型的任务?

可以使用 HIL-SERL 来训练各种操作任务。以下是一些建议:

  • 从一个简单的任务开始,以了解系统的工作原理。
    • 将方块推至目标区域
    • 使用夹爪抓取并抬起立方体
  • 避免使用极长时间跨度的任务。请专注于可在 5 到 10 秒内完成的任务。
  • 在充分了解系统的工作原理后,您可以尝试更复杂的任务和更长的时间跨度。
    • 拾取并放置立方体
    • 双臂任务,使用两条机械臂抓取物体
    • Hand-over 任务用于将物体从一个机械臂传递到另一个机械臂
    • 尽情发挥吧!

使用 HIL-SERL 安装 LeRobot

要使用 HIL-SERL 安装 LeRobot,您需要安装 hilserl 附加组件。

pip install -e ".[hilserl]"

真实机器人训练工作流

理解配置

训练过程从为 HILSERl 环境进行适当配置开始。主配置类是 lerobot/rl/gym_manipulator.py 中的 GymManipulatorConfig,其中包含嵌套的 HILSerlRobotEnvConfig(定义于 lerobot/envs/configs.py)和 DatasetConfig。配置被组织为聚焦的嵌套子配置:

class GymManipulatorConfig:
    env: HILSerlRobotEnvConfig    # Environment configuration (nested)
    dataset: DatasetConfig    # Dataset recording/replay configuration (nested)
    mode: str | None = None    # "record", "replay", or None (for training)
    device: str = "cpu"    # Compute device

class HILSerlRobotEnvConfig(EnvConfig):
    robot: RobotConfig | None = None    # Main robot agent (defined in `lerobot/robots`)
    teleop: TeleoperatorConfig | None = None    # Teleoperator agent, e.g., gamepad or leader arm
    processor: HILSerlProcessorConfig    # Processing pipeline configuration (nested)
    name: str = "real_robot"    # Environment name
    task: str | None = None    # Task identifier
    fps: int = 30    # Control frequency

# Nested processor configuration
class HILSerlProcessorConfig:
    control_mode: str = "gamepad"    # Control mode
    observation: ObservationConfig | None = None    # Observation processing settings
    image_preprocessing: ImagePreprocessingConfig | None = None    # Image crop/resize settings
    gripper: GripperConfig | None = None    # Gripper control and penalty settings
    reset: ResetConfig | None = None    # Environment reset and timing settings
    inverse_kinematics: InverseKinematicsConfig | None = None    # IK processing settings
    reward_classifier: RewardClassifierConfig | None = None    # Reward classifier settings
    max_gripper_pos: float | None = 100.0    # Maximum gripper position

# Sub-configuration classes
class ObservationConfig:
    add_joint_velocity_to_observation: bool = False    # Add joint velocities to state
    add_current_to_observation: bool = False    # Add motor currents to state
    add_ee_pose_to_observation: bool = False    # Add end-effector pose to state
    display_cameras: bool = False    # Display camera feeds during execution

class ImagePreprocessingConfig:
    crop_params_dict: dict[str, tuple[int, int, int, int]] | None = None    # Image cropping parameters
    resize_size: tuple[int, int] | None = None    # Target image size

class GripperConfig:
    use_gripper: bool = True    # Enable gripper control
    gripper_penalty: float = 0.0    # Penalty for inappropriate gripper usage

class ResetConfig:
    fixed_reset_joint_positions: list[float] | None = None    # Joint positions for reset
    reset_time_s: float = 5.0    # Time to wait during reset
    control_time_s: float = 20.0    # Maximum episode duration
    terminate_on_success: bool = True    # Whether to terminate episodes on success detection

class InverseKinematicsConfig:
    urdf_path: str | None = None    # Path to robot URDF file
    target_frame_name: str | None = None    # End-effector frame name
    end_effector_bounds: dict[str, list[float]] | None = None    # EE workspace bounds
    end_effector_step_sizes: dict[str, float] | None = None    # EE step sizes per axis

class RewardClassifierConfig:
    pretrained_path: str | None = None    # Path to pretrained reward classifier
    success_threshold: float = 0.5    # Success detection threshold
    success_reward: float = 1.0    # Reward value for successful episodes

# Dataset configuration
class DatasetConfig:
    repo_id: str    # LeRobot dataset repository ID
    task: str    # Task identifier
    root: str | None = None    # Local dataset root directory
    num_episodes_to_record: int = 5    # Number of episodes for recording
    replay_episode: int | None = None    # Episode index for replay
    push_to_hub: bool = False    # Whether to push datasets to Hub

处理器流水线架构

HIL-SERL 采用模块化处理器流水线架构,通过一系列可组合的步骤来处理机器人的观测和动作。该流水线分为两个主要组件:

环境处理器流水线

环境处理器(env_processor)负责处理传入的观察结果和环境状态:

  1. VanillaObservationProcessorStep:将原始机器人观测数据转换为标准化格式
  2. JointVelocityProcessorStep(可选):向观测数据中添加关节速度信息
  3. MotorCurrentProcessorStep(可选):将电机电流读数添加到观测值中
  4. ForwardKinematicsJointsToEE(可选):根据关节位置计算末端执行器位姿
  5. ImageCropResizeProcessorStep(可选):裁剪并调整相机图像的大小
  6. TimeLimitProcessorStep(可选):强制实施回合时间限制
  7. GripperPenaltyProcessorStep(可选):对不当的夹爪使用施加惩罚
  8. RewardClassifierProcessorStep(可选):使用视觉模型进行自动奖励检测
  9. AddBatchDimensionProcessorStep:将数据转换为批处理格式,以便神经网络进行处理
  10. DeviceProcessorStep:将数据移动到指定的计算设备(CPU/GPU)

Action Processor 流水线

动作处理器(action_processor)负责处理发出的动作和人工干预:

  1. AddTeleopActionAsComplimentaryDataStep:捕获遥操作员的动作以用于日志记录
  2. AddTeleopEventsAsInfoStep:记录干预事件和回合控制信号
  3. InterventionActionProcessorStep:处理人工干预和回合终止
  4. Inverse Kinematics Pipeline (启用时):
    • MapDeltaActionToRobotActionStep:将增量动作转换为机器人动作格式
    • EEReferenceAndDelta:计算末端执行器的参考和增量运动
    • EEBoundsAndSafety:强制实施工作区安全边界
    • InverseKinematicsEEToJoints:将末端执行器动作转换为关节目标
    • GripperVelocityToJoint:处理夹爪控制命令

配置示例

基础观测处理:

{
  "env": {
    "processor": {
      "observation": {
        "add_joint_velocity_to_observation": true,
        "add_current_to_observation": false,
        "display_cameras": false
      }
    }
  }
}

图像处理:

{
  "env": {
    "processor": {
      "image_preprocessing": {
        "crop_params_dict": {
          "observation.images.front": [180, 250, 120, 150],
          "observation.images.side": [180, 207, 180, 200]
        },
        "resize_size": [128, 128]
      }
    }
  }
}

逆运动学设置:

{
  "env": {
    "processor": {
      "inverse_kinematics": {
        "urdf_path": "path/to/robot.urdf",
        "target_frame_name": "end_effector",
        "end_effector_bounds": {
          "min": [0.16, -0.08, 0.03],
          "max": [0.24, 0.2, 0.1]
        },
        "end_effector_step_sizes": {
          "x": 0.02,
          "y": 0.02,
          "z": 0.02
        }
      }
    }
  }
}

高级观察处理

HIL-SERL 框架支持额外的观测处理功能,可提升策略学习的效果:

联合速度处理

启用联合速度估计,为策略提供运动信息:

{
  "env": {
    "processor": {
      "observation": {
        "add_joint_velocity_to_observation": true
      }
    }
  }
}

此处理器:

  • 使用连续关节位置读数之间的有限差分来估计关节速度
  • 将速度信息添加到观测状态向量中
  • 适用于需要运动感知以处理动态任务的政策

电机电流处理

监控电机电流以检测接触力和负载条件:

{
  "env": {
    "processor": {
      "observation": {
        "add_current_to_observation": true
      }
    }
  }
}

此处理器:

  • 从机器人的控制系统中读取电机电流值
  • 将当前测量值添加到观测状态向量中
  • 有助于检测接触事件、物体重量和机械阻力
  • 适用于接触丰富的操作任务

组合观测处理

您可以同时启用多个观察处理功能:

{
  "env": {
    "processor": {
      "observation": {
        "add_joint_velocity_to_observation": true,
        "add_current_to_observation": true,
        "display_cameras": false
      }
    }
  }
}

注意:启用额外的观测特征会增加状态空间的维度,这可能需要调整策略网络架构,并可能需要收集更多的训练数据。

查找机器人工作空间边界

在收集演示数据之前,您需要确定机器人的合适操作边界。

这有助于从两个方面简化在真实机器人上进行学习的问题:1) 将机器人的操作空间限制在能够完成任务并避免不必要或不安全探索的特定区域内;2) 允许在末端执行器空间而非关节空间中进行训练。从经验上看,在操作任务中,针对关节空间进行强化学习通常是一个更具挑战性的问题——某些任务在关节空间中几乎无法学习,但当动作空间转换为末端执行器坐标时,它们就变得可以学习了。

使用 lerobot-find-joint-limits

该脚本可帮助您确定机器人末端执行器的安全操作范围。在拥有从臂和主臂的情况下,您可以使用此脚本来确定将在训练期间应用于从臂的范围。 限制动作空间可以减少智能体的冗余探索,并确保安全性。

lerobot-find-joint-limits \
  --robot.type=so100_follower \
  --robot.port=/dev/tty.usbmodem58760431541 \
  --robot.id=black \
  --teleop.type=so100_leader \
  --teleop.port=/dev/tty.usbmodem58760431551 \
  --teleop.id=blue \
  --urdf_path=SO-ARM100/Simulation/SO101/so101_new_calib.urdf \
  --target_frame_name=gripper

--urdf_path 为必填项:它指向机器人的 URDF 文件,脚本将使用该文件来计算末端执行器的位置。对于 SO-100/SO-101,请使用 git clone https://github.com/TheRobotStudio/SO-ARM100.git 克隆 SO-ARM100 仓库;此时 URDF 文件位于 SO-ARM100/Simulation/SO101/so101_new_calib.urdf。

工作流程

  1. 运行该脚本,并让机器人在空间中移动以解决任务

  2. 该脚本将记录末端执行器的最小和最大位置以及关节角度,并将其打印到控制台,例如:

    # End Effector Bounds (x, y, z):
    max_ee = [0.2417, 0.2012, 0.1027]
    min_ee = [0.1663, -0.0823, 0.0336]
    
    # Joint Position Limits (radians):
    max_pos = [...]
    min_pos = [...]
  3. 在环境配置中,将这些值用于 env.processor.inverse_kinematics.end_effector_bounds(参见 lerobot/envs/configs.py 中的 InverseKinematicsConfig)

示例配置

{
  "env": {
    "processor": {
      "inverse_kinematics": {
        "end_effector_bounds": {
          "max": [0.24, 0.2, 0.1],
          "min": [0.16, -0.08, 0.03]
        }
      }
    }
  }
}

收集演示

在定义了边界之后,您可以安全地收集用于训练的数据演示。使用离策略算法进行强化学习训练,使我们能够利用按顺序收集的离线数据集,从而提高学习过程的效率。

设置记录模式

本指南的示例配置文件位于 Hub 上的 lerobot/config_examples 数据集中。请将环境和训练配置下载到您的工作目录中:

hf download lerobot/config_examples rl/env_config.json rl/train_config.json --repo-type dataset --local-dir .

这会将它们保存到 rl/env_config.json 和 rl/train_config.json,即以下命令中使用的路径。编辑 rl/env_config.json 以记录演示:

  1. 在根级别将 mode 设置为 "record"
  2. 在 dataset 部分中,为您的数据集指定一个唯一的 repo_id(例如,“username/task_name”)
  3. 在 dataset 部分中,将 num_episodes_to_record 设置为您想要收集的演示数量
  4. 最初将 env.processor.image_preprocessing.crop_params_dict 设置为 {}(我们稍后确定裁剪区域)
  5. 在 env 部分中配置 env.robot、env.teleop 以及其他硬件设置

配置部分示例:

{
  "env": {
    "type": "gym_manipulator",
    "name": "real_robot",
    "fps": 10,
    "processor": {
      "control_mode": "gamepad",
      "observation": {
        "display_cameras": false
      },
      "image_preprocessing": {
        "crop_params_dict": {},
        "resize_size": [128, 128]
      },
      "gripper": {
        "use_gripper": true,
        "gripper_penalty": 0.0
      },
      "reset": {
        "reset_time_s": 5.0,
        "control_time_s": 20.0
      }
    },
    "robot": {
      // ... robot configuration ...
    },
    "teleop": {
      // ... teleoperator configuration ...
    }
  },
  "dataset": {
    "repo_id": "username/pick_lift_cube",
    "root": null,
    "task": "pick_and_lift",
    "num_episodes_to_record": 15,
    "replay_episode": 0,
    "push_to_hub": true
  },
  "mode": "record",
  "device": "cpu"
}

使用远程操作设备

除了您的机器人,您还需要一个遥操作设备来控制它,以便收集任务数据集并在在线训练期间进行干预。 我们支持使用游戏手柄、键盘或机器人的主臂。

HIL-Serl 在机器人的末端执行器空间中学习动作。因此,遥操作将控制末端执行器的 x、y、z 位移。

末端执行器变换由处理器流水线(InverseKinematicsRLStep、EEBoundsAndSafety、EEReferenceAndDelta、GripperVelocityToJoint)应用,该流水线在 env.processor.inverse_kinematics(InverseKinematicsConfig)以及 env.processor.gripper / env.processor.max_gripper_pos 下进行配置。与末端执行器空间相关的默认值如下:

class InverseKinematicsConfig:
    """Configuration for inverse kinematics processing."""

    urdf_path: str | None = None
    target_frame_name: str | None = None
    # bounds for the end-effector in x,y,z direction
    end_effector_bounds: dict[str, list[float]] | None = None
    # maximum step size for the end-effector in x,y,z direction
    end_effector_step_sizes: dict[str, float] | None = None

class HILSerlProcessorConfig:
    ...
    # maximum gripper position that the gripper will be open at
    max_gripper_pos: float | None = 100.0

Teleoperator 定义了遥操作设备。您可以在 lerobot/teleoperators 中查看可用的遥操作器列表。

设置游戏手柄

游戏手柄提供了一种非常便捷的方式来控制机器人和回合状态。

要设置游戏手柄,需要将 control_mode 设置为 "gamepad",并在配置文件中定义 teleop 部分。

{
  "env": {
    "teleop": {
      "type": "gamepad",
      "use_gripper": true
    },
    "processor": {
      "control_mode": "gamepad",
      "gripper": {
        "use_gripper": true
      }
    }
  }
}

Figure shows the control mappings on a Logitech gamepad.

用于机器人控制和回合管理的游戏手柄按键映射

设置 SO101 领导者

SO101 主臂配备了减速齿轮,使其能够在探索过程中移动并跟踪从臂。因此,与无齿轮的 SO100 相比,接管操作要顺畅得多。

要设置 SO101 主臂,需要将 control_mode 设置为 "leader",并在配置文件中定义 teleop 部分。

{
  "env": {
    "teleop": {
      "type": "so101_leader",
      "port": "/dev/tty.usbmodem585A0077921",
      "use_degrees": true
    },
    "processor": {
      "control_mode": "leader",
      "gripper": {
        "use_gripper": true
      }
    }
  }
}

为了标注回合的成功/失败,你需要使用键盘,按 s 表示成功,按 esc 表示失败。 在在线训练期间,按 space 接管策略,再次按 space 将控制权交还给策略。

Video: SO101 leader teleoperation

SO101 主从遥操作示例,主臂跟踪从臂,按 `space` 键进行干预

录制演示

使用上述编辑的环境配置开始录制流程:

python -m lerobot.rl.gym_manipulator --config_path rl/env_config.json

录制过程中:

  1. 机器人将重置为配置文件 env.processor.reset.fixed_reset_joint_positions 中定义的初始位置
  2. 成功完成任务
  3. 该回合在你按下“success”按钮时以奖励值 1 结束
  4. 如果达到时间限制,或者按下了失败按钮,该回合将以 0 奖励结束
  5. 您可以按“重新录制”按钮来重新录制剧集
  6. 该过程会自动继续到下一个回合
  7. 记录完所有回合后,数据集会被推送到 Hugging Face Hub(可选)并保存到本地

处理数据集

在收集完演示数据后,对其进行处理以确定最佳的相机裁剪区域。 强化学习对背景干扰较为敏感,因此将图像裁剪到相关的工作区域至关重要。

视觉强化学习算法直接从像素输入中学习,因此容易受到无关视觉信息的干扰。背景元素(如光照变化、阴影、移动的人员或工作区外的物体)可能会干扰学习过程。良好的 ROI 选择应满足以下条件:

  • 仅包含任务执行所需的核心工作区
  • 捕获机器人的末端执行器以及任务中涉及的所有物体
  • 排除不必要的背景元素和干扰

注意:如果您已经知道裁剪参数,可以跳过此步骤,直接在录制时于配置文件中设置 crop_params_dict。

确定裁剪参数

使用 crop_dataset_roi.py 脚本在相机图像中交互式地选择感兴趣区域:

python -m lerobot.rl.crop_dataset_roi --repo-id username/pick_lift_cube
  1. 对于每个相机视角,该脚本将显示第一帧
  2. 在相关的工作区周围绘制一个矩形
  3. 按 c 确认选择
  4. 对所有相机视角重复此操作
  5. 该脚本会输出裁剪参数并创建一个新的裁剪数据集

示例输出:

Selected Rectangular Regions of Interest (top, left, height, width):
observation.images.side: [180, 207, 180, 200]
observation.images.front: [180, 250, 120, 150]

用于选择感兴趣区域的交互式裁剪工具

更新配置

在您的训练配置中添加这些裁剪参数:

{
  "env": {
    "processor": {
      "image_preprocessing": {
        "crop_params_dict": {
          "observation.images.side": [180, 207, 180, 200],
          "observation.images.front": [180, 250, 120, 150]
        },
        "resize_size": [128, 128]
      }
    }
  }
}

推荐的图像分辨率

大多数基于视觉的策略均在 128×128(默认)或 64×64 像素的方形输入上进行了验证。因此,我们建议将 resize_size 参数设置为 [128, 128]——如果需要节省 GPU 内存和带宽,则设置为 [64, 64]。其他分辨率也可以使用,但尚未经过充分测试。

训练奖励分类器

奖励分类器在 HIL-SERL 工作流中发挥着重要作用,它通过自动化奖励分配和自动检测回合成功来发挥作用。无需为每个时间步手动定义奖励函数或依赖人类反馈,奖励分类器能够从视觉观测中学习预测成功或失败。这使得强化学习算法能够基于机器人的相机输入,通过提供一致且自动化的奖励信号来高效学习。

本指南介绍如何为 LeRobot 的人机协同强化学习实现训练奖励分类器。奖励分类器学习在给定状态的情况下预测奖励值,该值可用于强化学习环境中训练策略。

注意:训练奖励分类器是可选的。您可以使用游戏手柄或键盘设备手动标注成功,从而开始第一轮强化学习实验。

lerobot/rewards/classifier/modeling_classifier.py 中的奖励分类器实现使用预训练的视觉模型来处理图像。它可以输出单个值以预测二元奖励的成功/失败情况,也可以输出多个值用于多分类设置。

为奖励分类器收集数据集

在训练之前,您需要收集一个包含带标签示例的数据集。在配置中设置 mode: "record" 并运行 gym_manipulator.py,即可启动收集观测、动作和奖励数据集的流程。

要收集数据集,您需要基于 HILSerlRobotEnvConfig 修改环境配置中的某些参数。

python -m lerobot.rl.gym_manipulator --config_path rl/env_config.json

数据收集的关键参数

  • mode:将其设置为 "record" 以收集数据集(在根级别)
  • dataset.repo_id:"hf_username/dataset_name",数据集在 Hub 上的名称和仓库
  • dataset.num_episodes_to_record:要记录的回合数
  • env.processor.reset.terminate_on_success:是否在检测到成功时自动终止回合(默认值:true)
  • env.fps:每秒记录的帧数
  • dataset.push_to_hub:是否将数据集推送到 Hub

env.processor.reset.terminate_on_success 参数允许你控制回合的终止行为。当设置为 false 时,即使检测到成功,回合也会继续,从而让你能够收集更多带有 reward=1 标签的正样本。这对于训练奖励分类器至关重要,因为它能在数据集中提供更多成功状态的样本。当设置为 true(默认值)时,回合会在检测到成功时立即终止。

重要:对于奖励分类器训练,请将 terminate_on_success: false 设置为 terminate_on_success: false 以收集足够的正样本。对于常规的 HIL-SERL 训练,请保持为 true,以便在任务成功完成时自动终止回合。

用于数据收集的示例配置部分:

{
  "env": {
    "type": "gym_manipulator",
    "name": "real_robot",
    "fps": 10,
    "processor": {
      "reset": {
        "reset_time_s": 5.0,
        "control_time_s": 20.0,
        "terminate_on_success": false
      },
      "gripper": {
        "use_gripper": true
      }
    },
    "robot": {
      // ... robot configuration ...
    },
    "teleop": {
      // ... teleoperator configuration ...
    }
  },
  "dataset": {
    "repo_id": "hf_username/dataset_name",
    "root": "data/your_dataset",
    "task": "reward_classifier_task",
    "num_episodes_to_record": 20,
    "replay_episode": null,
    "push_to_hub": true
  },
  "mode": "record",
  "device": "cpu"
}

奖励分类器配置

奖励分类器通过lerobot/rewards/classifier/configuration_classifier.py进行配置。以下是关键参数:

  • model_name:基础模型架构(例如,我们主要使用 "helper2424/resnet10")
  • model_type:"cnn" 或 "transformer"
  • num_cameras:相机输入的数量
  • num_classes:输出类别的数量(对于二分类成功/失败,通常为 2)
  • hidden_dim:隐藏表示的大小
  • dropout_rate:正则化参数
  • learning_rate:优化器的学习率

用于训练奖励分类器的示例配置。将其保存为 reward_classifier_train_config.json:

{
  "dataset": {
    "repo_id": "hf_username/dataset_name",
    "root": null
  },
  "reward_model": {
    "type": "reward_classifier",
    "model_name": "helper2424/resnet10",
    "model_type": "cnn",
    "num_cameras": 2,
    "num_classes": 2,
    "hidden_dim": 256,
    "dropout_rate": 0.1,
    "learning_rate": 1e-4,
    "device": "cuda",
    "input_features": {
      "observation.images.front": {
        "type": "VISUAL",
        "shape": [3, 128, 128]
      },
      "observation.images.side": {
        "type": "VISUAL",
        "shape": [3, 128, 128]
      }
    },
    "push_to_hub": true,
    "repo_id": "hf_username/model_repo"
  },
  "batch_size": 16,
  "num_workers": 4,
  "steps": 5000,
  "log_freq": 10,
  "env_eval_freq": 1000,
  "save_freq": 1000,
  "save_checkpoint": true,
  "seed": 2,
  "resume": false,
  "optimizer": {
    "grad_clip_norm": 10.0
  },
  "trackio": {
    "enable": true,
    "project": "reward-classifier"
  },
  "job_name": "reward-classifier"
}

训练分类器

要训练分类器,请使用您的配置运行 train.py 脚本:

lerobot-train --config_path reward_classifier_train_config.json

部署和测试模型

要使用您训练好的奖励分类器,请配置 HILSerlRobotEnvConfig 以使用您的模型:

config = GymManipulatorConfig(
    env=HILSerlRobotEnvConfig(
        processor=HILSerlProcessorConfig(
            reward_classifier=RewardClassifierConfig(
                pretrained_path="path_to_your_pretrained_trained_model"
            )
        ),
        # Other environment parameters
    ),
    dataset=DatasetConfig(...),
    mode=None  # For training
)

或在 json 配置文件中设置该参数。

{
  "env": {
    "processor": {
      "reward_classifier": {
        "pretrained_path": "path_to_your_pretrained_model",
        "success_threshold": 0.7,
        "success_reward": 1.0
      },
      "reset": {
        "terminate_on_success": true
      }
    }
  }
}

运行 gym_manipulator.py 以测试模型。

python -m lerobot.rl.gym_manipulator --config_path rl/env_config.json

奖励分类器将根据机器人摄像头提供的视觉输入自动给出奖励。

训练奖励分类器的示例工作流

  1. 创建配置文件: 为奖励分类器和环境创建所需的 json 配置文件:上述示例中的 reward_classifier_train_config.json,以及已下载的 rl/env_config.json。

  2. 收集数据集:

    python -m lerobot.rl.gym_manipulator --config_path rl/env_config.json
  3. 训练分类器:

    lerobot-train --config_path reward_classifier_train_config.json
  4. 测试分类器:

    python -m lerobot.rl.gym_manipulator --config_path rl/env_config.json

使用 Actor-Learner 进行训练

LeRobot 系统采用分布式 actor-learner 架构进行训练。该架构将机器人交互与学习过程解耦,使二者能够并发运行而互不阻塞。actor 服务器负责处理机器人的观测与动作,并将交互数据发送至 learner 服务器。learner 服务器执行梯度下降,并定期更新 actor 的策略权重。您需要启动两个进程:一个 learner 和一个 actor。

配置设置

编辑您之前下载的训练配置文件 rl/train_config.json(示例见 此处)。该训练配置基于 lerobot/rl/train_rl.py 中的主类 TrainRLServerPipelineConfig。

  1. 配置策略设置(type="gaussian_actor"、device 等)
  2. 在顶层 algorithm 块下配置算法设置(type="sac"、学习率、折扣因子等,定义于 lerobot/rl/algorithms/sac/configuration_sac.py)。
  3. 将 dataset 设置为您裁剪后的数据集
  4. 使用裁剪参数配置环境设置
  5. 在 configuration_gaussian_actor.py 中查看与 Gaussian Actor 相关的其他参数。
  6. 验证 policy 配置是否正确,确保针对您的任务使用了正确的 input_features 和 output_features。

启动 Learner

首先,启动学习器服务器进程:

python -m lerobot.rl.learner --config_path rl/train_config.json

学习者:

  • 初始化策略网络
  • 准备重放缓冲区
  • 打开一个 gRPC 服务器以与 actor 进行通信
  • 处理转换并更新策略

启动 Actor

在另一个终端中,使用相同的配置启动 actor 进程:

python -m lerobot.rl.actor --config_path rl/train_config.json

演员:

  • 通过 gRPC 连接到学习器
  • 初始化环境
  • 执行策略的 rollout 以收集经验
  • 向学习者发送转换
  • 接收更新后的策略参数

训练流程

训练将自动进行:

  1. Actor 在环境中执行策略
  2. Transitions 会被收集并发送到 learner
  3. 学习者根据这些转移更新策略
  4. 更新后的策略参数被发送回 actor
  5. 该过程将持续进行,直到达到指定的步数上限

人在回路

  • 高效学习的关键在于通过人工干预提供纠正性反馈,并完成任务,以辅助策略学习和探索。
  • 要执行人工干预,您可以按下游戏手柄右上角的扳机键(或键盘上的 space 键)。这将暂停策略动作,并允许您接管控制。
  • 一次成功的实验是指人类在开始时需要进行干预,但随着策略的改进,干预次数逐渐减少。您可以在 Trackio 仪表板中监控干预率(trackio show --project <project>)。

Figure shows the control mappings on a Logitech gamepad.

展示人类干预如何随时间推移引导策略学习的示例

  • 该图展示了随交互步数变化的情节奖励曲线。该图展示了人类干预对策略学习的影响。
  • 橙色曲线代表没有任何人工干预的实验,而粉色和蓝色曲线则代表有人工干预的实验。
  • 我们可以观察到,当存在人工干预时,策略开始获得最大奖励的步数减少了四分之一。

监控与调试

如果配置中将 trackio.enable 设置为 true,您可以通过 Trackio 仪表盘(trackio show --project <project>)实时监控训练进度。

人类干预指南

学习过程对干预策略非常敏感。需要运行几次才能理解如何有效干预。以下是一些提示和建议:

  • 在训练开始时,允许策略探索几个回合。
  • 避免长时间不干预。当机器人偏离预期行为时,请尝试及时介入以纠正其行为。
  • 当策略开始能够完成任务时,即使它并不完美,你也可以将干预限制为简单的快速操作,例如简单的抓取指令。

理想情况下,如上图所示,您的干预率应在训练过程中逐渐下降。

Intervention rate

在拾取并抬起立方体任务训练过程中干预率的曲线图

需要调整的关键超参数

某些配置值对训练的稳定性和速度有着不成比例的影响:

  • temperature_init (algorithm.temperature_init) – SAC 中的初始熵温度。较高的值鼓励更多的探索;较低的值使策略在早期更加确定。一个好的起点是 1e-2。我们观察到,将其设置得过高可能会使人工干预失效并减慢学习速度。
  • policy_parameters_push_frequency (policy.actor_learner_config.policy_parameters_push_frequency) – 从 learner 向 actor 推送两次权重之间的间隔,单位为秒。默认值为 4 s。将其降低至 1-2 s 可提供更新的权重(代价是增加网络流量);仅当您的连接速度较慢时才应将其调高,因为这会降低样本效率。
  • storage_device (policy.storage_device) – 学习者保存策略参数所在的设备。如果有多余的 GPU 显存,请将其设置为 "cuda"(而不是默认的 "cpu")。将权重保留在 GPU 上可消除 CPU→GPU 传输开销,并可能显著提高每秒的学习者更新次数。

恭喜 🎉,你已完成本教程!

如果您有任何问题或需要帮助,请在 Discord 上联系我们。

论文引用:

@article{luo2024precise,
  title={Precise and Dexterous Robotic Manipulation via Human-in-the-Loop Reinforcement Learning},
  author={Luo, Jianlan and Xu, Charles and Wu, Jeffrey and Levine, Sergey},
  journal={arXiv preprint arXiv:2410.21845},
  year={2024}
}
Update on GitHub