目录

0.参考

Lerobot 中使用 SO100/101Arm 机器人手臂 | Seeed Studio Wiki
https://huggingface.co/blog/smolvla
SmolVLAを転移学習してLeRobot SO-101へ実機デプロイしたい! #基盤モデル - Qiita

本项目使用Lerobot v0.4.4,其他版本指令可能不一致。

概述

SmolVLAhttps://huggingface.co/lerobot/smolvla_base),这是一个轻量级(450M参数)的开源视觉-语言-动作(VLA)模型,专为机器人领域设计,并且可以在消费级硬件上运行。

  • 仅使用开源社区共享的数据集进行预训练,数据集标签为lerobot
  • SmolVLA-450M的表现优于许多更大的 VLA 模型,并且在仿真任务(LIBERO,Meta-World)和实际任务(SO100, SO101)上超过了强基线模型,如ACT
  • 支持异步推理,可提供30% 更快的响应2 倍的任务吞吐量
  • 足够小,可以在 CPU 上运行,单个消费级 GPU 上训练,甚至可以在 MacBook 上运行!
  • 训练使用的是公开的、社区共享的机器人数据
  • 发布时附带完整的训练和推理方案
  • 可以在非常经济的硬件上进行测试和部署(如 SO-100、SO-101、LeKiwi 等)

1.安装 LeRobot

conda create -y -n lerobot_vla python=3.10 && conda activate lerobot_vla
git clone https://github.com/Seeed-Projects/lerobot.git 
# 安装带有 feetech 电机依赖的 LeRobot:
cd lerobot
pip install -e ".[feetech]"

# 安装smolvla相关的库
pip install -e ".[smolvla]"

2.校准机械臂

首先,您需要授予接口权限,运行以下命令:

sudo chmod 666 /dev/ttyACM*

从动臂

拔掉其他的相机和机械臂,第一个插入从动臂,端口号就是 ttyACM0
第一步:移动到中间姿态
第二步:动态移动到最大值和最小值位置

lerobot-calibrate \
    --robot.type=so101_follower \
    --robot.port=/dev/ttyACM0 \
    --robot.id=my_awesome_follower_arm

注意:新版的校准和之前不一样了,新版是把机器人移动到中间位置和最大最小,这点需要格外注意。建议参考 Seeed的B站视频。

【SO-ARM机械臂Lerobot超详细上手教程:5校准及遥操作】 SO-ARM机械臂Lerobot超详细上手教程:5校准及遥操作_哔哩哔哩_bilibili

主动臂

继续插入主动臂的控制板,端口号为ttyACM1.

lerobot-calibrate \
    --teleop.type=so101_leader \
    --teleop.port=/dev/ttyACM1 \
    --teleop.id=my_awesome_leader_arm

遥操作

先对串口给予权限:

sudo chmod 666 /dev/ttyACM*

运行遥操作:

lerobot-teleoperate \
    --robot.type=so101_follower \
    --robot.port=/dev/ttyACM0 \
    --robot.id=my_awesome_follower_arm \
    --teleop.type=so101_leader \
    --teleop.port=/dev/ttyACM1 \
    --teleop.id=my_awesome_leader_arm

遥控操作命令将自动执行以下步骤:

  1. 识别任何缺失的校准文件并启动校准程序。
  2. 连接机器人和遥控设备,并开始遥控操作。

3.添加摄像头

要查找连接到您系统的摄像头的摄像头索引,请运行以下脚本:

lerobot-find-cameras opencv
  • 带摄像头的遥操作,只有这个运行成功之后,才能进行后续采集数据的实验。
  • 在正式采集之前,可以根据这个来调整相机的视角,确保正式采集时视角合理,机器人和物块在视野内。
lerobot-teleoperate \
    --robot.type=so100_follower \
    --robot.port=/dev/ttyACM0 \
    --robot.id=my_awesome_follower_arm \
    --robot.cameras="{ front: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30, fourcc: "MJPG"}, side: {type: opencv, index_or_path: 2, width: 640, height: 480, fps: 30, fourcc: "MJPG"}}" \
    --teleop.type=so100_leader \
    --teleop.port=/dev/ttyACM1 \
    --teleop.id=my_awesome_leader_arm \
    --display_data=tru

4.采集数据

采集数据的相关指令如下,但是需要注意的是:

  1. 这是VLA模型,所以 single_task 任务描述就是作为训练的自然语言,需要和实际任务匹配。需要针对你的应用进行修改
  2. 每次采集需要换不同的数据集名称 repo_id,否则会报错。
lerobot-record \
    --robot.type=so100_follower \
    --robot.port=/dev/ttyACM0 \
    --robot.id=my_awesome_follower_arm \
    --robot.cameras="{ front: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30, fourcc: "MJPG"}, side: {type: opencv, index_or_path: 2, width: 640, height: 480, fps: 30, fourcc: "MJPG"}}" \
    --teleop.type=so100_leader \
    --teleop.port=/dev/ttyACM1 \
    --teleop.id=my_awesome_leader_arm \
    --display_data=true \
    --dataset.repo_id=smolvla/greenbook \
    --dataset.num_episodes=10 \
    --dataset.single_task="put the cup on the green book" \
    --dataset.push_to_hub=false \
    --dataset.episode_time_s=30 \
    --dataset.reset_time_s=10
lerobot-record \
    --robot.type=so100_follower \
    --robot.port=/dev/ttyACM0 \
    --robot.id=my_awesome_follower_arm \
    --robot.cameras="{ front: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30, fourcc: "MJPG"}, side: {type: opencv, index_or_path: 2, width: 640, height: 480, fps: 30, fourcc: "MJPG"}}" \
    --teleop.type=so100_leader \
    --teleop.port=/dev/ttyACM1 \
    --teleop.id=my_awesome_leader_arm \
    --display_data=true \
    --dataset.repo_id=smolvla/redbook \
    --dataset.num_episodes=10 \
    --dataset.single_task="put the cup on the red book" \
    --dataset.push_to_hub=false \
    --dataset.episode_time_s=30 \
    --dataset.reset_time_s=10

这里提供一个测试场景:

  1. 把杯子放在红色的书上。put the cup on the red book
  2. 把杯子放在绿色的书上。put the cup on the green book

5.训练

  1. 训练的时候,会从huggingface拉取smolVLA的基础模型资源,但是国内访问huggingface会有问题,所以需要设置镜像站,以便于下载smolvla预训练模型。
export HF_ENDPOINT=https://hf-mirror.com

单一任务

  • 单一任务表现和模仿学习很类似,仅训练20k步效果还不错,也可以选择更大的步数。
lerobot-train \
--policy.path=lerobot/smolvla_base \
--policy.push_to_hub=false \
--dataset.repo_id=smolvla/redbook \
--batch_size=64 \
--steps=20000 \
--output_dir=outputs/train/redbook \
--job_name=my_smolvla_training \
--policy.device=cuda \
--wandb.enable=false \
--rename_map='{"observation.images.front": "observation.images.camera1", "observation.images.side": "observation.images.camera2"}' 

多个任务

注意:顺序训练的灾难性遗忘问题

我之前的训练方法是顺序微调,也就是先在数据集A上训练,然后在数据集B上训练,这样会导致B训练结束之后,把A全忘记了,也就是“灾难性遗忘”问题。对于多个数据集,需要先合并数据集,再训练。
具体可以查看附录。

  1. 假如之前采集了两组数据集,smolvla/redbook和smolvla/greenbook ,可以通过以下指令进行数据集的合并。
lerobot-edit-dataset \
    --repo_id smolvla/mixed_book \
    --operation.type merge \
    --operation.repo_ids "['smolvla/redbook', 'smolvla/greenbook']"
  1. 然后利用合并的数据集训练,这里的 dataset.repo_id指向 smolvla/mixed_book 。
 lerobot-train \
    --policy.path=lerobot/smolvla_base \
    --dataset.repo_id=smolvla/mixed_book \
    --policy.push_to_hub=false \
    --batch_size=64 \
    --steps=100000 \
    --output_dir=outputs/train/joint_books \
    --job_name=smolvla_joint_training \
    --policy.device=cuda \
    --wandb.enable=false \
    --rename_map='{"observation.images.front": "observation.images.camera1", "observation.images.side": "observation.images.camera2"}'

6.推理

  1. 注意这里的 --policy.path 选择你之前训练输出的地址,需要指向模型文件所在的文件夹。
  2. 由于每隔20k步,都会保存一个checkpoints,所以也可以选择中间训练得到的模型。
lerobot-record \
  --robot.type=so100_follower \
  --robot.port=/dev/ttyACM0 \
  --robot.id=my_awesome_follower_arm \
  --robot.cameras='{"camera1": {"type": "opencv", "index_or_path": 0, "width": 640, "height": 480, "fps": 30, "fourcc": "MJPG"}, "camera2": {"type": "opencv", "index_or_path": 2, "width": 640, "height": 480, "fps": 30, "fourcc": "MJPG"}}' \
  --dataset.single_task="put the cup on the green book" \
  --dataset.repo_id=smolvla/eval_1 \
  --dataset.episode_time_s=60 \
  --dataset.reset_time_s=10 \
  --dataset.push_to_hub=false \
  --dataset.num_episodes=10 \
  --policy.path=outputs/train/joint_books/checkpoints/040000/pretrained_model \
  --teleop.type=so100_leader \
  --teleop.port=/dev/ttyACM1 \
  --teleop.id=my_awesome_leader_arm 

7.实验结果

  1. 我把A、B数据集先合并起来,再训练,它就会同时从A、B数据集中学习经验。 最后的推理结果表示,机器人可以区分我的指令中的“on the red book” 和 “ on the green book”,能够把杯子放在正确颜色的书上。

  2. 如果我用白纸替换书本,把指令换成“put the cup on the white paper”,机器人也可以正确放置,表明它对于颜色有一定的泛化能力。

  3. 如果我放置一个棕色的快递盒,把指令换成 “put the cup on the brown box”,机器人就不能正确放置了。因为快递盒比书本厚的多,机器人并不会抬升到足够高的高度,而是直接撞上去。 也可能是侧面相机视角的原因,它对于高度的感知并不强。

  4. 如果从被抓取物体入手,把杯子换成一个红色的立方体,把指令换成“put the red cube on the green book”,机器人虽然有相应的抓取放置动作,但是并不能抓到方块,只是在空中执行动作。

附录

问题记录

1.灾难性遗忘

我在Lerobot中使用SmolVLA模型,我采集了两组数据,第一组将杯子放在红色的书上 数据集叫redbook,第二组将杯子放在绿色的书上,数据集叫greenbook。
我在smolvla_base的基础模型上训练 ,使用redbook数据集,训练20k次,得到预训练模型,然后再在预训练的基础上使用greenbook数据集训练,得到最终的模型。但是推理的时候,无论我给的指令是“put the cup on the red book ”还是“put the cup on the green book” ,都只会把杯子放在绿色的书上。 可能是什么原因?


这是一个经典的灾难性遗忘(Catastrophic Forgetting)问题,结合你的训练流程来分析:
你的训练流程是顺序微调(Sequential Fine-tuning)

smolvla_base → 训练redbook 20k → 预训练模型 → 训练greenbook → 最终模型

当你在greenbook上继续训练时,神经网络的权重被大幅更新以适应新任务,覆盖了之前学到的redbook相关知识。最终模型几乎"忘记"了如何响应red book指令,只记得最近训练的green book行为。

为什么语言指令没有起作用?

SmolVLA是视觉-语言-动作模型,语言指令理论上应该区分两个任务。但问题在于:

  1. 语言条件没有被充分学习:如果base模型本身对语言条件的动作控制较弱,微调时模型可能走了"捷径"——直接学习视觉特征→动作的映射,而忽略语言输入
  2. greenbook训练覆盖了语言-动作绑定:第二阶段训练让模型将所有动作都与"放书"场景绑定,无论指令内容
  3. 数据量不平衡:如果greenbook数据量远大于redbook,模型会强烈偏向green
什么是灾难性遗忘

灾难性遗忘是机器学习,尤其是神经网络领域的一个核心难题。
简单来说,它指的是:当一个神经网络在学习新任务时,会急剧、彻底地遗忘之前学过的旧任务。
这就像一个学生,为了通过周一的数学考试,把之前背熟的英语单词全忘光了。更麻烦的是,这种遗忘不是渐进式的,而是断崖式的——一旦开始学新东西,旧知识的准确率会从很高直接跌落到近乎随机猜测的水平。
这源于人工神经网络与生物大脑的本质不同。

  • 参数共享:神经网络的同一个“参数”(可以理解为神经连接的强度)必须同时服务于所有任务。学习新任务时,网络会调整这些参数来适应新数据,但这往往会覆盖掉原先对旧任务有用的参数配置。
  • 缺乏巩固机制:人脑在睡眠时,会通过重放白天的经历,将重要记忆从海马体(临时存储)转移到新皮层(长期存储),从而巩固记忆。而标准神经网络没有这种主动保护重要知识的能力。
  • 任务边界模糊:网络在学习新任务的数据时,无法自动识别“现在学的和以前是不同任务”,只会一味地降低当前任务的损失(即预测误差),从而无差别地修改参数。

这个问题严重限制了深度学习在现实世界中的应用:

  • 无法持续学习:AI不能像人类一样,通过终身学习不断积累技能。想让一个已训练好的AI学点新东西,往往需要用新旧数据混合起来重新训练整个模型,计算成本极高。
  • 多任务能力差:很难训练一个单一的、能同时完成数十上百个不同任务的通用模型。通常只能为每个任务单独训练模型。
  • 在线学习失效:在自动驾驶、机器人等需要根据新数据流不断实时更新模型的场景中,模型可能会因为学到新场景(如雪地)而突然忘记如何应对旧场景(如晴天)。

如果我有多个数据集,是不是不能采用顺序微调的方式,让它学习?

是的,如果你直接对同一个模型进行“顺序微调”(先在一个数据集上训练好,再在下一个数据集上继续训练),几乎必然会导致灾难性遗忘——模型会迅速丢失前一个数据集上学到的知识。

如果你确实有多个数据集,且希望模型最终能同时掌握所有任务,请避免简单的顺序微调,改用以下方法:

方案 做法 优点 缺点
联合训练 将所有数据集合并,打乱后一次性训练模型 无遗忘问题,效果通常最好 需要同时访问所有数据;内存和计算可能过大
持续学习方法 使用弹性权重巩固(EWC)记忆重放等技术,在顺序学习时保护旧知识 可以顺序学习,无需同时存储所有数据 实现复杂;仍有轻微遗忘;需要调参
多任务学习架构 设计共享主干 + 任务特定分支(如多头输出层) 隔离任务,互不干扰 需要知道任务身份;模型参数随任务数增加
具体建议:
  • 如果所有数据可以同时加载:直接联合训练。这是最安全、最简单的方法。
  • 如果数据不能同时加载(比如隐私、存储限制):使用经验重放(保留一小部分旧数据的样本,混在新数据中一起训练)或 EWC
方案:合并数据集

Dataset Manipulation Tools - LeRobot
https://github.com/huggingface/lerobot/blob/main/docs/source/using_dataset_tools.mdx

数据集必须包含:

  • 相同的帧率
  • 兼容功能(相同的键、数据类型、形状)
  • 同类型机器人(推荐)

  • 使用脚本合并
from lerobot.datasets.lerobot_dataset import LeRobotDataset
from lerobot.datasets.dataset_tools import merge_datasets

# 加载两个数据集
dataset1 = LeRobotDataset("smolvla/redbook")
dataset2 = LeRobotDataset("smolvla/greenbook")

# 合并数据集到本地
merged = merge_datasets(
    datasets=[dataset1, dataset2],
    output_repo_id="smolvla/mixed_book",
    output_dir="/home/imc/.cache/huggingface/lerobot/smolvla/mixed_book"
)

print(f"Merged dataset: {merged.num_episodes} episodes")
print(f"Total frames: {merged.num_frames}")
  • 使用命令行合并
lerobot-edit-dataset \
    --repo_id smolvla/mixed_book \
    --operation.type merge \
    --operation.repo_ids "['smolvla/redbook', 'smolvla/greenbook']"

  • 查看数据集meta文件,可以发现数据集按顺序排列了。
使用合并数据集训练
 lerobot-train \
    --policy.path=lerobot/smolvla_base \
    --dataset.repo_id=smolvla/mixed_book \
    --policy.push_to_hub=false \
    --batch_size=64 \
    --steps=100000 \
    --output_dir=outputs/train/joint_books \
    --job_name=smolvla_joint_training \
    --policy.device=cuda \
    --wandb.enable=false \
    --rename_map='{"observation.images.front": "observation.images.camera1", "observation.images.side": "observation.images.camera2"}'
Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐