LeRobot documentation
Имитационное обучение на реальных роботах
Имитационное обучение на реальных роботах
В этом руководстве объясняется, как обучить нейронную сеть автономно управлять реальным роботом.
Вы узнаете:
- Как записать и визуализировать ваш набор данных.
- Как обучить политику на ваших данных и подготовить её к оценке.
- Как оценить вашу политику и визуализировать результаты.
Следуя этим шагам, вы сможете воспроизводить задачи, такие как подбор кубика Lego и его размещение в контейнере, с высокой вероятностью успеха, как показано в видео ниже.
Video: pickup lego block task
Этот учебный материал не привязан к конкретному роботу: мы последовательно разбираем команды и фрагменты API, которые можно адаптировать под любую поддерживаемую платформу.
При сборе данных вы используете устройство «телеуправления», например ведущую манипуляторную руку или клавиатуру, чтобы дистанционно управлять роботом и записывать траектории его движения.
Когда вы соберёте достаточно траекторий, вы обучите нейронную сеть имитировать эти траектории и развернёте обученную модель, чтобы ваш робот мог выполнять задачу автономно.
Если на каком-либо этапе возникнут проблемы, загляните в наше сообщество Discord за поддержкой.
Хотите быстро получить нужные команды для вашей конфигурации? Ноутбук для быстрого старта
позволяет настроить робота один раз и сгенерировать все перечисленные ниже команды, готовые к вставке.
Настройка и калибровка
Если вы ещё не настроили и не откалибровали робота и устройство телеуправления, выполните это, следуя руководству для вашего робота, например SO-101, OpenArm, Koch или LeKiwi. Все поддерживаемые роботы перечислены в разделе Robots на боковой панели.
Телеуправление
В этом примере мы покажем, как управлять роботом SO101 дистанционно. Для каждой команды мы также приводим соответствующий пример использования API.
Обратите внимание, что id, связанный с роботом, используется для хранения файла калибровки. Важно использовать один и тот же id при телеуправлении, записи и оценке, если используется одна и та же конфигурация.
lerobot-teleoperate \
--robot.type=so101_follower \
--robot.port=/dev/tty.usbmodem58760431541 \
--robot.id=my_awesome_follower_arm \
--teleop.type=so101_leader \
--teleop.port=/dev/tty.usbmodem58760431551 \
--teleop.id=my_awesome_leader_armfrom lerobot.teleoperators.so_leader import SO101Leader, SO101LeaderConfig
from lerobot.robots.so_follower import SO101Follower, SO101FollowerConfig
robot_config = SO101FollowerConfig(
port="/dev/tty.usbmodem5AB90687491",
id="my_follower_arm",
)
teleop_config = SO101LeaderConfig(
port="/dev/tty.usbmodem5AB90689011",
id="my_leader_arm",
)
robot = SO101Follower(robot_config)
teleop_device = SO101Leader(teleop_config)
robot.connect()
teleop_device.connect()
while True:
action = teleop_device.get_action()
robot.send_action(action)Команда teleoperate автоматически:
- Определите отсутствующие калибровки и запустите процедуру калибровки.
- Подключите робота и устройство телеуправления и начните телеоперацию.
Камеры
Чтобы добавить камеры в вашу конфигурацию, следуйте этому руководству.
Телеуправление с помощью камер
С помощью rerun можно снова выполнять телеуправление, одновременно визуализируя видеопоток с камер и положения суставов. В этом примере используются две камеры, wrist и top; мы сохраняем такую же конфигурацию камер на протяжении всего остального туториала.
lerobot-teleoperate \
--robot.type=so101_follower \
--robot.port=/dev/tty.usbmodem5AB90687491 \
--robot.id=my_follower_arm \
--robot.cameras="{ wrist: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30}, top: {type: opencv, index_or_path: 1, width: 640, height: 480, fps: 30}}" \
--teleop.type=so101_leader \
--teleop.port=/dev/tty.usbmodem5AB90689011 \
--teleop.id=my_leader_arm \
--display_data=trueimport time
from lerobot.teleoperators.so_leader import SO101Leader, SO101LeaderConfig
from lerobot.robots.so_follower import SO101Follower, SO101FollowerConfig
from lerobot.cameras.opencv import OpenCVCameraConfig
from lerobot.utils.visualization_utils import init_visualization, log_visualization_data, shutdown_visualization
robot_config = SO101FollowerConfig(
port="/dev/tty.usbmodem5AB90687491",
id="my_follower_arm",
cameras={
"wrist": OpenCVCameraConfig(index_or_path=0, width=640, height=480, fps=30),
"top": OpenCVCameraConfig(index_or_path=1, width=640, height=480, fps=30)
}
)
teleop_config = SO101LeaderConfig(
port="/dev/tty.usbmodem5AB90689011",
id="my_leader_arm",
)
init_visualization("rerun", session_name="teleoperation") # pass "foxglove" to stream to Foxglove instead
robot = SO101Follower(robot_config)
teleop_device = SO101Leader(teleop_config)
robot.connect()
teleop_device.connect()
TARGET_HZ = 30
TIME_PER_FRAME = 1.0 / TARGET_HZ
while True:
start_time = time.perf_counter()
observation = robot.get_observation()
action = teleop_device.get_action()
robot.send_action(action)
log_visualization_data("rerun", observation=observation, action=action)
elapsed_time = time.perf_counter() - start_time
sleep_time = TIME_PER_FRAME - elapsed_time
if sleep_time > 0:
time.sleep(sleep_time)Запись набора данных
Когда вы освоите телеуправление, вы сможете записать свой первый набор данных.
Мы используем возможности Hugging Face hub для загрузки вашего набора данных. Если вы ранее не пользовались Hub, убедитесь, что вы можете войти через cli с токеном, предоставляющим права на запись; этот токен можно сгенерировать в настройках Hugging Face.
Добавьте токен в CLI, выполнив эту команду:
hf auth login --token ${HUGGINGFACE_TOKEN} --add-to-git-credentialЗатем сохраните имя вашего репозитория Hugging Face в переменную:
HF_USER=$(NO_COLOR=1 hf auth whoami | awk -F': *' 'NR==1 {print $2}')
echo $HF_USERТеперь вы можете записать датасет. Чтобы записать 5 эпизодов и загрузить ваш датасет на хаб, адаптируйте код ниже под вашего робота и выполните команду или пример API.
lerobot-record \
--robot.type=so101_follower \
--robot.port=/dev/tty.usbmodem585A0076841 \
--robot.id=my_awesome_follower_arm \
--robot.cameras="{ front: {type: opencv, index_or_path: 0, width: 1920, height: 1080, fps: 30}}" \
--robot.cameras="{ wrist: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30}, top: {type: opencv, index_or_path: 1, width: 640, height: 480, fps: 30}}" \
--teleop.type=so101_leader \
--teleop.port=/dev/tty.usbmodem58760431551 \
--teleop.id=my_awesome_leader_arm \
--display_data=true \
--dataset.repo_id=${HF_USER}/record-test \
--dataset.num_episodes=5 \
--dataset.single_task="Grab the black cube" \
--dataset.streaming_encoding=true \
--dataset.encoder_threads=2
# Optional: --dataset.rgb_encoder.vcodec=autofrom lerobot.cameras.opencv import OpenCVCameraConfig
from lerobot.datasets.lerobot_dataset import LeRobotDataset
from lerobot.utils.feature_utils import hw_to_dataset_features
from lerobot.robots.so_follower import SO101Follower, SO101FollowerConfig
from lerobot.teleoperators.so_leader.config_so_leader import SO101LeaderConfig
from lerobot.teleoperators.so_leader.so_leader import SO101Leader
from lerobot.common.control_utils import init_keyboard_listener
from lerobot.utils.utils import log_say
from lerobot.utils.visualization_utils import init_visualization
from lerobot.scripts.lerobot_record import record_loop
from lerobot.processor import make_default_processors
NUM_EPISODES = 5
FPS = 30
EPISODE_TIME_SEC = 60
RESET_TIME_SEC = 10
TASK_DESCRIPTION = "My task description"
def main():
# Create robot configuration
robot_config = SO101FollowerConfig(
port="/dev/tty.usbmodem5AB90687491",
id="my_follower_arm",
cameras={
"wrist": OpenCVCameraConfig(index_or_path=0, width=640, height=480, fps=30),
"top": OpenCVCameraConfig(index_or_path=1, width=640, height=480, fps=30)
}
)
teleop_config = SO101LeaderConfig(
port="/dev/tty.usbmodem5AB90689011",
id="my_leader_arm",
)
# Initialize the robot and teleoperator
robot = SO101Follower(robot_config)
teleop = SO101Leader(teleop_config)
# Configure the dataset features
action_features = hw_to_dataset_features(robot.action_features, "action")
obs_features = hw_to_dataset_features(robot.observation_features, "observation")
dataset_features = {**action_features, **obs_features}
# Create the dataset
dataset = LeRobotDataset.create(
repo_id="<hf_username>/<dataset_repo_id>",
fps=FPS,
features=dataset_features,
robot_type=robot.name,
use_videos=True,
image_writer_threads=4,
)
# Initialize the keyboard listener and rerun visualization
_, events = init_keyboard_listener()
init_visualization("rerun", session_name="recording")
# Connect the robot and teleoperator
robot.connect()
teleop.connect()
# Create the required processors
teleop_action_processor, robot_action_processor, robot_observation_processor = make_default_processors()
episode_idx = 0
while episode_idx < NUM_EPISODES and not events["stop_recording"]:
log_say(f"Recording episode {episode_idx + 1} of {NUM_EPISODES}")
record_loop(
robot=robot,
events=events,
fps=FPS,
teleop_action_processor=teleop_action_processor,
robot_action_processor=robot_action_processor,
robot_observation_processor=robot_observation_processor,
teleop=teleop,
dataset=dataset,
control_time_s=EPISODE_TIME_SEC,
single_task=TASK_DESCRIPTION,
display_data=True,
)
# Reset the environment if not stopping or re-recording
if not events["stop_recording"] and (episode_idx < NUM_EPISODES - 1 or events["rerecord_episode"]):
log_say("Reset the environment")
record_loop(
robot=robot,
events=events,
fps=FPS,
teleop_action_processor=teleop_action_processor,
robot_action_processor=robot_action_processor,
robot_observation_processor=robot_observation_processor,
teleop=teleop,
control_time_s=RESET_TIME_SEC,
single_task=TASK_DESCRIPTION,
display_data=True,
)
if events["rerecord_episode"]:
log_say("Re-recording episode")
events["rerecord_episode"] = False
events["exit_early"] = False
dataset.clear_episode_buffer()
continue
dataset.save_episode()
episode_idx += 1
# finalize dataset
log_say("Finalizing dataset...")
dataset.finalize()
# Clean up
log_say("Stop recording")
robot.disconnect()
teleop.disconnect()
dataset.push_to_hub()
if __name__ == "__main__":
main()Имена камер, которые вы выбираете (здесь wrist и top), становятся ключами датасета observation.images.wrist и observation.images.top. Политика, обученная на этом датасете, ожидает те же имена камер и разрешение при её развёртывании, поэтому используйте то же значение --robot.cameras на каждом шаге этого руководства. Если имена должны отличаться, см. Rename Map.
lerobot-recordдобавляет дату и время сессии в конец--dataset.repo_id, поэтому каждая запись получает уникальное имя:${HF_USER}/record-testсохраняется как${HF_USER}/record-test_YYYYMMDD_HHMMSS(например,record-test_20260929_143012). Полное имя можно найти на вашем профиле Hugging Face или с помощьюls ~/.cache/huggingface/lerobot/${HF_USER}и использовать его везде, где в командах ниже указаноrecord-test_YYYYMMDD_HHMMSS. Чтобы сохранить точное переданное имя, добавьте--dataset.no_stamp=true.
Загрузка набора данных
Локально ваш набор данных хранится в этой папке: ~/.cache/huggingface/lerobot/{repo-id}. По завершении записи данных ваш набор данных будет загружен на вашу страницу Hugging Face (например, https://huggingface.co/datasets/${HF_USER}/record-test_YYYYMMDD_HHMMSS), которую можно получить, выполнив:
echo https://huggingface.co/datasets/${HF_USER}/record-test_YYYYMMDD_HHMMSSВаш набор данных будет автоматически помечен тегом LeRobot, чтобы сообщество могло легко его найти, а также вы можете добавить собственные теги, например --dataset.tags='["tutorial"]'.
Вы можете найти другие наборы данных LeRobot на хабе, поискав по тегам LeRobot tags.
Вы также можете вручную загрузить локальный датасет в Hub, выполнив:
hf upload ${HF_USER}/record-test_YYYYMMDD_HHMMSS ~/.cache/huggingface/lerobot/${HF_USER}/record-test_YYYYMMDD_HHMMSS --repo-type datasetФункция записи
lerobot-record предоставляет набор инструментов для захвата и управления данными во время работы робота:
1. Хранение данных
- Данные сохраняются в формате
LeRobotDatasetи записываются на диск в процессе записи. - По умолчанию после записи датасет загружается на вашу страницу Hugging Face.
- Чтобы отключить загрузку, используйте
--dataset.push_to_hub=False.
- Чтобы отключить загрузку, используйте
2. Создание контрольных точек и возобновление
- Точки контрольных точек автоматически создаются во время записи.
- Если возникла проблема или вы хотите записать дополнительные эпизоды в тот же набор данных, вы можете продолжить, повторно выполнив ту же команду с
--resume=true. Укажите полное имя набора данных, включая его метку времени (--dataset.repo_id=${HF_USER}/record-test_YYYYMMDD_HHMMSS). При возобновлении записи значение--dataset.num_episodesдолжно быть равно количеству дополнительных эпизодов, которые нужно записать, а не целевому общему числу эпизодов в наборе данных! Убедитесь, что вы также задали--dataset.root="local_path": это локальный путь для сохранения новой части набора данных, и он обязателен для возобновления. - Повторное выполнение команды без
--resume=trueзапускает новый датасет с новым временным меткой. Если вы используете--dataset.no_stamp=true, сначала удалите существующий каталог датасета.
3. Параметры записи
Настройте поток записи данных с помощью аргументов командной строки:
--dataset.episode_time_s=60Длительность каждого эпизода записи данных (по умолчанию: 60 секунд).--dataset.reset_time_s=60Длительность сброса окружения после каждого эпизода (по умолчанию: 60 секунд).--dataset.num_episodes=50Общее количество эпизодов для записи (по умолчанию: 50).
4. Управление с клавиатуры во время записи
Управляйте потоком записи данных с помощью горячих клавиш:
- Нажмите стрелку вправо (
→) илиn: досрочно завершить текущий эпизод или сбросить время и перейти к следующему. - Нажмите стрелку влево (
←) илиr: отмените текущий эпизод и запишите его заново. - Нажмите Escape (
ESC) илиq: немедленно остановите сессию, закодируйте видео и загрузите набор данных.
Эти способы управления потоком работают в сессиях X11, Wayland и headless/SSH. Если глобальный бэкенд клавиатуры недоступен (Wayland, headless-машина или macOS без разрешения Accessibility),
lerobot-recordавтоматически считывает те же клавиши из терминала — запускайте его из интерактивного терминала и держите его в фокусе. Также можно использовать буквенные эквивалентыn(следующий, то же, что→),r(перезаписать, то же, что←) иq(выход, то же, чтоESC). Настройка$DISPLAYне требуется.Это относится только к потоку управления записью. Телеуправление с клавиатуры teleoperation (управление роботом с помощью клавиатуры) по-прежнему требует глобального бэкенда клавиш, поэтому работает только в сессии X11, на рабочем столе Windows или в macOS с предоставленными правами Accessibility/Input Monitoring — но не в Wayland или безголовых сессиях.
Советы по сбору данных
Когда вы освоите запись данных, можно создать более крупный датасет для обучения. Хорошей стартовой задачей является захват объекта в разных точках и размещение его в контейнере. Мы рекомендуем записать не менее 50 эпизодов, из них 10 на каждую точку. Держите камеры неподвижными и сохраняйте последовательное поведение при захвате на протяжении всей записи. Также убедитесь, что объект, с которым вы работаете, виден на камерах. Хорошее правило: вы должны быть способны выполнить задачу, глядя только на изображения с камер.
В следующих разделах вы будете обучать свою нейросеть. После того как вы добьётесь стабильного качества захвата, можно начать вводить больше вариаций при сборе данных, например, дополнительные точки захвата, различные техники захвата и изменение позиций камер.
Избегайте слишком быстрого добавления большого количества вариаций, так как это может ухудшить результаты.
Если вы хотите углубиться в эту важную тему, вы можете ознакомиться с нашей статьей в блоге о том, что делает датасет хорошим.
Отчётность по частоте
lerobot-record задаёт ритм цикла по значению --dataset.fps и сообщает о фактически достигнутом: однострочная сводка для каждого сохранённого эпизода и блок для всей сессии при завершении записи — в том числе при нажатии Ctrl-C.
Cadence (episode 0): 29.88 Hz vs 30 Hz target · 600 ticks, 20.0 s measured · 8/599 ticks over the 33.3 ms budget (work mean 18.4 ms, worst 45.1 ms)
Cadence (episode 1): 29.88 Hz vs 30 Hz target · 600 ticks, 20.0 s measured · 8/599 ticks over the 33.3 ms budget (work mean 18.4 ms, worst 45.1 ms)
Cadence summary — whole run, 2 episodes · target 30 Hz (33.3 ms budget per tick): 1200 ticks, 1198 judged
effective cadence: 29.88 Hz over 40.1 s measured
ticks over the 33.3 ms work budget: 16/1198 (1.3%) — work mean 18.4 ms, worst 45.1 ms
loop-body steps (share of measured work):
observe mean 13.65 ms · worst 40.20 ms · 74.4% of work · 1200 calls
process_obs mean 0.30 ms · worst 0.30 ms · 1.6% of work · 1200 calls
teleop mean 1.80 ms · worst 1.80 ms · 9.8% of work · 1200 calls
send mean 0.90 ms · worst 0.90 ms · 4.9% of work · 1200 calls
record mean 1.70 ms · worst 1.90 ms · 9.3% of work · 1200 calls
pacing headroom: 15.1 ms slept per tick on average (max 16.7 ms) — near zero means the loop is saturatedСтоит прочитать это перед обучением на датасете. Метка времени кадра вычисляется на основе его индекса, поэтому сессия, записанная с частотой 25 Гц, всё равно формирует датасет, который заявляет 30 Гц — записанное движение просто быстрее реального. Выше observe занимает 74% работы цикла, а его worst составляет 40 мс при бюджете 33,3 мс: именно камеры привели к тому, что 16 тиков вышли за рамки. Запас по тактированию близок к нулю, что означает отсутствие резерва для поглощения медленного тика.
Фазы сброса между эпизодами так же регулируются по темпу, но намеренно не входят в эти показатели, поскольку они ничего не записывают. lerobot-teleoperate и lerobot-replay отчитываются аналогичным образом, а lerobot-rollout добавляет специфичные для интерполяции строки, описанные в Отчёт о темпе.
Устранение неполадок:
- В Linux клавиши управления записью (стрелки, Escape) работают в сессиях X11, Wayland и headless/SSH, если
lerobot-recordзапущен в интерактивном терминале — настройка$DISPLAYне требуется. Если клавиши не срабатывают, убедитесь, что вы находитесь в интерактивном (TTY) терминале, а не в сессии с перенаправлением ввода/вывода (non-TTY), и что терминал в фокусе; также работают буквенные эквивалентыn/r/q. Клавиатурное телеуправление (в отличие от управления записью) по-прежнему требует глобального бэкенда клавиатуры — сессии X11, рабочего стола Windows или macOS с предоставленными правами Accessibility/Input Monitoring — и недоступно в Wayland или headless-средах. См. ограничения pynput.
Визуализация набора данных
По умолчанию ваш датасет загружается на Hub (если вы не передали --dataset.push_to_hub=False), поэтому вы можете сразу открыть его в LeRobot Dataset Visualizer: введите идентификатор репозитория на главной странице или перейдите прямо к первому эпизоду по ссылке, которую выводит команда:
echo "https://huggingface.co/spaces/lerobot/visualize_dataset?path=/${HF_USER}/record-test_YYYYMMDD_HHMMSS/episode_0"Войдите в визуализатор, чтобы открыть частный набор данных. См. Просмотр набора данных в браузере для пошагового руководства.
Повторить эпизод
Полезной функцией является replay, которая позволяет воспроизвести любой записанный вами эпизод или эпизоды из любого доступного датасета. Эта функция помогает проверить воспроизводимость действий вашего робота и оценить переносимость между роботами одной модели.
Вы можете воспроизвести первый эпизод на вашем роботе с помощью команды ниже или с помощью примера API:
lerobot-replay \
--robot.type=so101_follower \
--robot.port=/dev/tty.usbmodem58760431541 \
--robot.id=my_awesome_follower_arm \
--dataset.repo_id=${HF_USER}/record-test_YYYYMMDD_HHMMSS \
--dataset.episode=0 # choose the episode you want to replayimport time
from lerobot.datasets import LeRobotDataset
from lerobot.robots.so_follower import SO101Follower, SO101FollowerConfig
from lerobot.utils.robot_utils import precise_sleep
from lerobot.utils.utils import log_say
episode_idx = 0
robot_config = SO101FollowerConfig(port="/dev/tty.usbmodem5AB90687491", id="my_follower_arm")
robot = SO101Follower(robot_config)
robot.connect()
dataset = LeRobotDataset("<hf_username>/<dataset_repo_id>", episodes=[episode_idx])
actions = dataset.select_columns("action")
log_say(f"Replaying episode {episode_idx}")
for idx in range(dataset.num_frames):
t0 = time.perf_counter()
action = {
name: float(actions[idx]["action"][i]) for i, name in enumerate(dataset.features["action"]["names"])
}
robot.send_action(action)
precise_sleep(max(1.0 / dataset.fps - (time.perf_counter() - t0), 0.0))
robot.disconnect()Ваш робот должен воспроизводить движения, похожие на те, что вы записали. Например, посмотрите это видео, где мы используем replay на роботе ALOHA от Trossen Robotics.
Обучение политики
Чтобы обучить политику для управления вашим роботом, используйте скрипт lerobot-train. Требуется передать несколько аргументов. Пример команды:
lerobot-train \
--dataset.repo_id=${HF_USER}/record-test_YYYYMMDD_HHMMSS \
--policy.type=act \
--output_dir=outputs/train/act_so101_test \
--job_name=act_so101_test \
--policy.device=cuda \
--trackio.enable=true \
--policy.repo_id=${HF_USER}/my_policyРазберём команду:
- Мы передали ранее записанный набор данных в качестве аргумента с помощью
--dataset.repo_id=${HF_USER}/record-test_YYYYMMDD_HHMMSS(используйте полное имя вашего набора данных, включая метку времени). - Мы передали политику с параметром
policy.type=act. Это загружает конфигурации изconfiguration_act.py. Важно, что эта политика автоматически адаптируется к количеству моторных состояний, моторных действий и камер вашего робота (например,wristиtop), которые сохранены в вашем наборе данных. - Мы указали
policy.device=cuda, так как обучаем модель на GPU Nvidia, но для обучения на Apple silicon можно использоватьpolicy.device=mps. - Мы передали
trackio.enable=true, чтобы использовать Trackio для визуализации графиков обучения. Это необязательно. Запуститеtrackio show --project lerobot, чтобы открыть дашборд, или передайте--trackio.space_id=<user>/<space>, чтобы синхронизировать запуск с Hugging Face Space. - Мы не задали
--steps, поэтому обучение выполняется по умолчанию 100 000 шагов. Обычно для небольшого набора данных этого слишком много: имитационное обучение, как правило, сходится за 5–10 эпох. См. Руководство по вычислениям и оборудованию, чтобы перевести количество эпох в значение--stepsдля размера вашего набора данных и размера батча.
Обучение должно занять несколько часов. Вы найдёте контрольные точки в outputs/train/act_so101_test/checkpoints.
Чтобы возобновить обучение из контрольной точки, ниже приведён пример команды для возобновления с последней контрольной точки last политики act_so101_test:
lerobot-train \
--config_path=outputs/train/act_so101_test/checkpoints/last/pretrained_model/train_config.json \
--resume=true--config_path также принимает идентификатор репозитория Hub: если в ходе запуска чекпоинты были загружены в Hub (с флагом --save_checkpoint_to_hub=true), можно возобновить обучение прямо из репозитория — будет скачан его последний чекпоинт, и обучение продолжится с восстановлением оптимизатора, планировщика, счётчика шагов и порядка данных:
lerobot-train --config_path=${HF_USER}/my_policy --resume=trueЕсли вы не хотите загружать модель на хаб после обучения, используйте --policy.push_to_hub=false.
Кроме того, вы можете указать дополнительные tags или задать license для вашей модели, а также сделать репозиторий модели private, добавив следующее: --policy.private=true --policy.tags=\[so101,tutorial\] --policy.license=mit
Обучение с помощью Google Colab
Если на вашем локальном компьютере нет мощной GPU, вы можете использовать Google Colab для обучения модели, следуя инструкциям в ноутбуке для обучения ACT.
Обучение с помощью Hugging Face Jobs
Hugging Face Jobs позволяет легко выбрать оборудование и запустить обучение в облаке. Поэтому, если у вас нет мощного GPU, вам нужно больше VRAM или вы просто хотите обучить модель значительно быстрее, используйте HF Jobs! Оплата производится по факту использования: вы платите за каждую секунду работы. Тарифы и дополнительную информацию можно найти здесь.
lerobot-train по умолчанию выполняется локально. Чтобы запустить его на GPU HuggingFace, передайте --job.target с именем типа оборудования:
lerobot-train \
--dataset.repo_id=${HF_USER}/record-test_YYYYMMDD_HHMMSS \
--policy.type=act \
--policy.repo_id=${HF_USER}/my_policy \
--job.target=a10g-smallПолучите список доступных конфигураций и цен с помощью hf jobs hardware. При запуске логи транслируются в ваш терминал; нажмите Ctrl-C, чтобы отключиться (задача продолжит выполняться в облаке). Повторно подключиться или отменить задачу можно с помощью:
hf jobs logs <job-id>
hf jobs cancel <job-id>Если ваш датасет существует только локально (ещё не на Hub), он автоматически загружается в приватный репозиторий Hub, чтобы задание могло скачать его по repo_id (ничего не публикуется). Обученная модель загружается в репозиторий модели в конце выполнения. Чтобы также загружать каждый промежуточный чекпоинт на Hub по мере его сохранения (чтобы вы могли отслеживать прогресс во время выполнения), добавьте --save_checkpoint_to_hub=true — для этого требуется образ среды выполнения, поддерживающий эту функцию.
Каждая задача (и любой датасет, загруженный в ходе выполнения) получает тег lerobot, что упрощает их поиск на Hub. Свои теги можно добавить с помощью --job.tags '["my-tag"]'.
По умолчанию время выполнения задания ограничено 2d (48 ч). Это значение можно переопределить строкой длительности HF Jobs, например, --job.timeout=4h для более быстрого завершения или --job.timeout=7d для более длительного выполнения.
Примечание: репозиторий модели создаётся заранее (он содержит конфигурацию обучения, подготовленную для запуска задачи). Если запуск завершается с ошибкой до того, как модель будет загружена, репозиторий остаётся на Hub, чтобы вы могли его проверить — он не удаляется автоматически, поэтому при повторяющихся сбоях могут остаться пустые репозитории. Удалите его с помощью
hf repos delete <repo-id>.
Предварительные требования: выполните hf auth login перед отправкой. Для Trackio передайте --trackio.space_id=<user>/<space> — Space будет создан, если отсутствует, а HF_TOKEN задания будет передан автоматически.
Возобновление на задаче. Добавление --job.target к команде возобновления запускает процесс в облаке — одна и та же команда работает как локально, так и удалённо. Репозиторий контрольных точек является источником истины, а новые контрольные точки продолжают линию в том же репозитории:
# resume a Hub run on a job (its checkpoints are already on the Hub)
lerobot-train --config_path=${HF_USER}/my_policy --resume=true --job.target=a10g-small
# resume a LOCAL run on a job — the checkpoint is uploaded to a private Hub repo first,
# then the job resumes from it (a local-only dataset is uploaded the same way)
lerobot-train \
--config_path=outputs/train/act_so101_test/checkpoints/last/pretrained_model/train_config.json \
--resume=true \
--job.target=a10g-smallНастройки задания берутся из текущей команды, поэтому при необходимости переопределяйте --job.target, --job.timeout и т. д.; чтобы возобновлённый запуск сам мог быть возобновлён позже, сохраняйте --save_checkpoint_to_hub=true.
Загрузка контрольных точек политики
Когда обучение завершено, загрузите последнюю контрольную точку с помощью:
hf upload ${HF_USER}/act_so101_test \
outputs/train/act_so101_test/checkpoints/last/pretrained_modelВы также можете загрузить промежуточные контрольные точки с помощью:
CKPT=010000
hf upload ${HF_USER}/act_so101_test${CKPT} \
outputs/train/act_so101_test/checkpoints/${CKPT}/pretrained_modelЗапустите инференс и оцените вашу политику
Используйте lerobot-rollout для развёртывания обученной политики на вашем роботе. Вы можете выбрать различные стратегии в зависимости от ваших потребностей.
Используйте тот же --robot.id (чтобы была найдена калибровка), те же --robot.cameras и то же описание задачи, что и в записанном вами датасете. Датасеты, записанные с помощью lerobot-rollout, должны иметь имя, начинающееся с rollout_, и, как и lerobot-record, к этому имени добавляется метка времени.
Приведённые ниже примеры загружают модель из --policy.path. Чтобы зафиксировать конкретную опубликованную версию — это полезно, когда --save_checkpoint_to_hub=true закоммитил несколько контрольных точек, — добавьте --policy.pretrained_revision с хэшем коммита, веткой или тегом. Каждая опубликованная контрольная точка помечается её шагом (например, --policy.pretrained_revision=010000), поэтому вы можете восстановить контрольную точку по шагу, не выясняя её sha-хэш коммита.
lerobot-rollout \
--strategy.type=base \
--policy.path=${HF_USER}/my_policy \
--robot.type=so101_follower \
--robot.port=/dev/tty.usbmodem5AB90687491 \
--robot.id=my_follower_arm \
--robot.cameras="{ wrist: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30}, top: {type: opencv, index_or_path: 1, width: 640, height: 480, fps: 30}}" \
--task="Grab the black cube" \
--duration=60lerobot-rollout \
--strategy.type=sentry \
--strategy.upload_every_n_episodes=5 \
--policy.path=${HF_USER}/my_policy \
--robot.type=so101_follower \
--robot.port=/dev/tty.usbmodem5AB90687491 \
--robot.id=my_follower_arm \
--robot.cameras="{ wrist: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30}, top: {type: opencv, index_or_path: 1, width: 640, height: 480, fps: 30}}" \
--dataset.repo_id=${HF_USER}/rollout_so101_test \
--dataset.single_task="Grab the black cube" \
--duration=600Флаг --strategy.type выбирает режим выполнения:
base: Автономный прогон без записи данных (полезен для быстрой оценки)sentry: Непрерывная запись с автоматической загрузкой (полезно для оценки в больших масштабах)highlight: Запись в кольцевой буфер с сохранением по нажатию клавиши (полезно для фиксации интересных событий)dagger: Сбор данных с участием человека (см. HIL Data Collection)episodic: Запись политики, ориентированной на эпизоды, с фазами сброса между эпизодами
Все стратегии поддерживают --inference.type=rtc для плавного выполнения с медленными VLA-моделями (Pi0, Pi0.5, SmolVLA). См. Развёртывание политик для всех стратегий и их флагов.