ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

LeRobot训练与测试全流程指南:从数据检查到真机部署的避坑记录

LeRobot训练与测试全流程指南:从数据检查到真机部署的避坑记录 把第五篇数据采集那篇写完的时候我就猜到评论区一定有人等着看训练和测试这部分。毕竟lerobot这个开源项目数据采集只是入口真正让人又爱又恨的其实是训练链路——参数一改就玄学loss曲线一跑就心跳加速好不容易训完还得上真机检验这一套流程走下来才是完整的闭环。这篇操作记录我尽量把训练和测试过程中遇到的所有关键点都写清楚。包括训前怎么确认数据没问题、配置文件里那些参数到底在控制什么、训练命令怎么写、日志怎么读、loss曲线怎么分析、怎么恢复中断的训练、评估脚本怎么用、真机推理要注意哪些细节以及我在这个过程中实打实踩过的坑。最后还会把几个常见报错和排查思路整理出来这些都是文档里不会写的东西。如果你已经在前面几篇里搞定了环境配置和数据采集那这篇就是临门一脚。1. 训练前的硬性检查与数据格式确认1.1 先搞清楚你的数据集到底是什么格式很多朋友从网上clone了lerobot项目又照着别的教程采集了一批数据然后看都不看一眼就直接丢进训练脚本结果跑起来各种报错。这类问题九成都是数据集格式或者结构跟训练预期不匹配导致的。lerobot目前的数据格式主要有两代。老一代是HDF5格式整个数据集就是一个.h5文件内部按episode和frame组织读取依赖h5py库。新一代在2.0版本之后转向了MCAP格式这是一种更通用的机器人日志容器格式除了图像和动作数据还能把相机内参、时间戳、控制频率这些元信息一起塞进去。MCAP天然支持流式读取数据集大起来之后优势非常明显。训练之前我最习惯干的一件事就是先写个小脚本把数据集的基础信息打印出来from lerobot.common.datasets.lerobot_dataset import LeRobotDataset dataset LeRobotDataset(myuser/my_robot_dataset) print(数据条目数:, len(dataset)) print(episode数:, dataset.num_episodes) print(动作维度:, dataset.num_features[action]) print(图像特征:, dataset.num_features) print(meta信息:, dataset.meta)跑完之后重点看三个东西一是数据条目数每个episode的帧数是否正常如果有某个episode只有几十帧而其他都有几百帧那大概率是采集时断流了二是动作维度比如ALOHA双臂是14维单臂是6维或7维如果维度跟你预期的机械臂型号对不上后面训练出来的策略一定是废的三是meta信息里有没有fps和chunk_size之类的字段这些会影响训练时的时序逻辑。如果数据集是从HDF5老版本迁移过来的还要确认一下图像字段的命名。由于lerobot不同版本对图像列的命名有调整如果你用的是自定义采集脚本图像feature名称可能叫observation.image也可能是observation.images.cam_high这个不一致会让Transformer的视觉编码器直接报错。建议训练前专门确认这一步。1.2 GPU环境与依赖版本对齐数据没问题了接下来看环境。lerobot涉及torch、torchvision、h5py、mcap、transformers、tensorboard或wandb这些依赖版本之间不能差得太离谱尤其是torch和CUDA的对应关系。训练前先跑一遍nvidia-smi python -c import torch; print(torch.__version__, torch.version.cuda); print(torch.cuda.is_available())如果torch.cuda.is_available()是False那训练会直接退化到CPU上爬行。这种情况一般就是CUDA和cuDNN版本对不上或者torch是CPU版本装的。建议直接用官方要求的torch版本重装别在现有环境上打补丁越补越乱。另外如果配置里用了flash_attn加速要多留意一下这个库的编译。ACT和Diffusion Policy这些策略不是必须依赖flash attention但开了之后训练速度会有明显提升。Flash-attn的安装经常遇到gcc版本、CUDA arch list的问题如果编译总失败可以在配置里关掉不影响正确性只是训练慢一点。这里分享一个我自己的习惯每次训练前固定用一套虚拟环境不跟数据采集共用。因为数据采集阶段通常装了机器人厂商的SDK里面可能有特定版本的numpy或opencv放进训练环境容易产生依赖冲突。环境隔离这件事看起来麻烦实际能替你省掉很多半夜排查环境的痛苦。1.3 数据集放在本地还是直接走HuggingFace路径lerobot默认的数据集标识方式是把数据集作为一个HuggingFace仓库来引用。如果你把数据传到了HF上训练时直接填your_username/your_dataset就能拉取。但如果你跟我一样数据主要存在本地尤其是一百多G的原始数据那就没必要硬推HF直接用本地路径就行。本地数据集目录的常见结构大致是这样my_robot_dataset/ ├── meta/ │ ├── info.json │ └── episodes.json ├── data/ │ ├── chunk-00000.mcap │ ├── chunk-00001.mcap │ └── ... └── videos/ ├── ep0_cam_high.mp4 └── ...训练时把--dataset.repo_id换成实际路径例如--dataset.repo_id./data/my_robot_datasetlerobot会优先判断是否为本地路径。如果从这里拉取超时或很慢也可以直接指定本地路径避免下载带来的等待。硬要上传HF的好处是方便换机器训练、方便和朋友共享但前提是你网络环境稳定。就个人项目而言本地路径够用。2. 训练配置精读这些参数到底在控制什么2.1 策略选型ACT还是Diffusion Policy还是TDMPC打开lerobot的配置目录你会发现它支持好几种策略。很多人上来就问“哪个策略效果好”这个问题其实没有标准答案得看你的任务和数据量。我把主流几个策略的适配场景列一下策略核心思路数据量需求典型场景训练资源占用ACT动作分块 Transformer500条演示以上效果稳双臂操作、精密插拔中等Diffusion Policy扩散模型直接生成动作序列1000条以上更稳多模态动作分布偏高TDMPC隐式模型预测控制500条以上需要在线规划的任务偏高ACT是默认最常用的选择因为它结构相对简单训练稳定而且动作分块机制对真机部署特别友好。它在每个控制周期内预测一整段未来动作而不是单步动作天然起到了平滑作用。Diffusion Policy走的则是生成式路线它对多峰动作分布比如同一个物体可以从左边拿也可以从右边拿建模能力更强但训练迭代更慢、生成过程也更容易受噪声步数影响。如果任务轨迹高度一致数据量又有限ACT往往更快见效。所以我在这次操作里选的是ACT策略下面所有命令和参数也都是基于ACT来写。2.2 学习率、batch size与梯度累积的关系这些超参数是训练里影响最大的几个。很多人只把学习率当成一个“照着填就得了”的数字但如果任务失败建议把学习率、batch size、梯度累积一起看。先看有效batch size这个核心概念。你的显存决定了一次能塞进多少样本但实际训练希望用更大的batch来稳定梯度。当显存放不下大batch时就用梯度累积来近似。数学上等价于把多次小batch的梯度累加后再更新一次参数。有效batch size batch_size × gradient_accumulation_steps举个例子我希望有效batch是32但单张卡跑batch为8已经显存吃紧那就设置--gradient_accumulation_steps4。这样梯度累积4次再更新一次效果上接近batch32。训练日志里的step计数和参数更新频率也会相应发生变化这一点后面讲日志时会再提。学习率方面ACT常用的初始值是1e-4附近。如果你把batch从64缩小到8又没有改变梯度累积步数实际更新信号的方差会变大这时候可以考虑把学习率也稍微调低一些否则loss曲线容易剧烈抖动。学习率不是孤立参数必须结合batch设计和优化器一起看。2.3 视觉主干网络的预训练权重选择ACT这类策略的输入通常包含多路相机图像也就是说需要视觉编码器来提取特征。lerobot里视觉主干可选ResNet系列的变体常见的有resnet18、resnet34也可以换efficientnet、vit之类。选择主干网络时我的建议是先在任务复杂度上做判断如果只是桌面级简单抓取resnet18完全够用如果你的任务涉及细小物体、复杂纹理或高动态场景那加深到resnet34或更大模型也许更合适。很多人问我预训练权重重不重要。我的经验是重要但没有想象中那么重要。预训练权重能加速前期的特征收敛尤其在你数据量只有几百条时随机初始化的主干会花大量时间在“学会看图像”这件事上而不是“学会该怎么做动作”。但如果数据集本身和预训练域差别太大比如预训练用的ImageNet图像跟你的俯视桌面视角差距很大预训练权重带来的提升就可能被缩小。实际操作时我一般会先随便训一个很短的任务来确认链路是否通再用预训练权重跑正式实验。2.4 评估频率、保存频率与训练步数怎么编排eval_freq这里“评测频率”指每隔多少step跑一次评估。save_freq是多步保存checkpoint。num_steps是总训练步数。这三个参数看起来简单但编排不对会浪费大量时间。ACT跑pusht这种仿真任务官方默认通常是几万步比如50000步而真实任务因为数据质量没那么干净往往需要10万步以上才稳定。评估环节如果太频繁比如每1000步就评估一次光跑评估的时间可能比训练还多但如果太稀疏你可能中间过拟合了都没发现。我的习惯是训练初期让eval_freq和save_freq保持一致比如每5000步评估一次并保存一次这样任何一个checkpoint都能对应到同一批评估结果。等训练进入后期再把评估频率适当降低保存频率保持不变防止最后的checkpoint被自动覆盖掉。3. 训练实操启动命令、日志监控与损失曲线解读3.1 一行命令启动训练当数据、环境、配置都确认没问题之后就可以启动训练了。以ACT为例训练命令大概长这样python lerobot/scripts/train.py \ --policy.typeact \ --dataset.repo_id./data/my_robot_dataset \ --output_diroutputs/act_aloha_test01 \ --job_nameact_aloha_test01 \ --policy.vision_backboneresnet18 \ --policy.optimizer.lr1e-4 \ --policy.optimizer.weight_decay1e-2 \ --batch_size8 \ --gradient_accumulation_steps4 \ --num_steps100000 \ --eval_freq5000 \ --save_freq5000 \ --log_freq50 \ --num_workers4注意一下字段名可能会因为版本不同有小变动比如policy.optimizer.lr在部分版本里是policy.optimizer.lr在更早的版本可能是policy.lr或env.lr。建议先在lerobot/configs里查一下当前版本的yaml字段。关于output_dir和job_name我强烈建议每次实验都给一个有意义的名称比如act_aloha_teach01_lr1e-4_bs32。因为训练一跑就是几个小时等到三天后你再翻目录看outputs/act1这种名字根本想不起来当时用的什么参数而一个规范命名能让你从文件夹名直接读出实验配置。3.2 训练日志里到底在看什么启动训练后终端会滚动输出训练进度。它长这样step1000 | loss1.0234 | l1/state/action0.1345 | mse/state/action0.1234 | grad_norm0.5623 | lr1.0e-04 | data_time0.03s | step_time0.45s刚开始训练时很多人的目光全被总loss吸引住其实这里更应该关注的是分项指标。ACT训练里除了总loss还会输出l1/state/action和mse/state/action这类的动作误差指标。动作误差比总loss更能说明策略学没学到东西因为总loss里还包含了一堆辅助任务的损失项。如果开了wandb或tensorboard训练结束之后还可以翻出更完整的曲线。这里有一个值得关注的判断技巧训练初期动作error快速下降是正常的说明策略正在形成简单的输入输出映射但如果到中后期它还一直在降反而要警惕过拟合因为训练集的loss继续下降可能只是“背题”不代表生成能力变得更强。看曲线时我还习惯把grad_norm放进视野。如果梯度范数突然飙升到百位数甚至更多那就是梯度爆炸了通常表现为loss值变NaN或者走向失控。常见处理办法是打开梯度裁剪或者降低学习率重新跑。3.3 断点续训与checkpoint恢复训练跑着跑着断了是很常见的事尤其当你用SSH远程跑任务半夜网络一抖连接断了训练进程就跟着没了。所以训练脚本里通常会设定定期保存checkpoint。checkpoint目录一般是这个结构outputs/act_aloha_test01/ ├── checkpoints/ │ ├── 00005000/ │ │ ├── pretrained_model/ │ │ │ ├── config.json │ │ │ ├── model.safetensors │ │ │ └── ... │ │ └── training_state/ │ ├── 00010000/ │ └── last/ └── logs/注意last这个目录它通常指向最近一次保存的checkpoint不管训练是否自然结束只要保存过就能从这里恢复。恢复训练的方式是在训练命令里加--resumetruelerobot会自动找output_dir下面的last目录继续跑而不是从头开始。这里有一个很实用的小技巧如果你发现训练到后期loss已经收敛但还想再多跑一段但又不想从最近的checkpoint加载继续可以手动把checkpoints/00095000复制到checkpoints/last然后重新设置num_steps为剩余步数或者直接在命令里调整。这样可以避免从头开始损失时间。恢复训练时容易碰到的一个问题是随机状态恢复不完全导致训练曲线在恢复点出现小的抖动。这个影响通常不大不用太担心。真正要注意的是数据加载顺序变了有可能导致恢复后的一个eval结果跟恢复前差别较大如果看到这种跳变建议多观察几步再下结论。4. 模型测试评估脚本、可视化回放与真机推理4.1 先离线评估还是直接上真机训练结束之后最迫切的事情就是赶紧看看模型到底行不行。但我不建议直接把模型搬到真机上因为真机测试成本高、风险也高一旦动作发散轻则撞桌角重则扫掉桌上的东西甚至损坏设备。更稳妥的方法是在仿真环境里先跑一轮评估或者在采集好的测试集上做回放式验证。如果你用的是Pusht这类仿真环境评估命令很简单python lerobot/scripts/eval.py \ --policy.pathoutputs/act_aloha_test01/checkpoints/last/pretrained_model \ --env.typepusht \ --env.num_episodes50这条命令会加载你训练好的模型在环境中连续执行50个episode最后输出成功率、平均奖励这些指标。如果没有仿真环境也可以拿采集时拍的验证集来做输入看模型在相同图像输入下的动作预测和真实动作差异大不大。评估时我把成功率看作一个统计算法而不是一个绝对指标。单次成功并不能代表模型稳定建议最少跑50个episode再下结论。如果时间有限至少也要跑20个否则一个随机初始化模型偶尔也能撞出一次“成功”容易给你造成虚假的安全感。4.2 用测试脚本评估模型性能和可视化结果lerobot的eval.py不只是输出一个成功率数字它还会把预测的动作轨迹和实际执行轨迹记录下来。对仿真任务尤其方便的一点是脚本会生成可视化的gif或视频放在outputs/act_aloha_test01/eval/目录下。我每次都会去翻这些视频因为数值指标只能告诉你“成功还是失败”而视频能告诉你“为什么失败”。看可视化回放时我关注的重点是几个阶段。第一步看机械臂是否从一开始就朝目标方向运动还是动作乱甩第二步看在接近物体的过程中轨迹是否平滑有没有突然的抖动或震荡第三步也是最重要的看任务失败时是卡在哪个环节——是视觉识别不到目标还是手臂够不到还是接近后夹取位置不对。这三个环节对应的问题根源完全不同。实际看过就有体会数值指标优良但真机行为怪异的情况并不罕见因为仿真里动作正常换到真机上又有各种现实差异。这也是为什么最后必须上真机测试。4.3 真机推理部署与测试的注意事项真机测试时lerobot提供了一套推理脚本命令大概是python lerobot/scripts/eval.py \ --policy.pathoutputs/act_aloha_test01/checkpoints/last/pretrained_model \ --env.typereal \ --env.cameras[cam_high,cam_left_wrist,cam_right_wrist] \ --env.num_episodes10这段命令会加载模型通过机器人驱动库连接机械臂然后等待你手动引导任务起点模型就开始根据实时图像预测动作并执行。真机测试前我先强调一遍安全旁边一定要有急停开关刚开始测试时控制频率可以设低一点机械臂运行速度也不宜太快留出人工干预的余地。真机测试里最影响稳定性的几个因素如下。第一相机参数。训练时的图像分辨率、裁剪区域、内参校准如果和推理时有出入模型预测的坐标就全错位了。这一点强烈建议训练和推理都用完全相同的相机设置。第二控制频率。真机控制频率和训练数据的采集频率需要对齐。如果你采集时是30Hz推理时如果变成10Hz或者50Hz模型预测的动作节奏跟实际执行节奏不匹配动作就会忽快忽慢看起来像抽风。第三动作分块。ACT这类策略每个控制周期会预测未来一段动作然后逐段执行。如果把分块长度设得太短平滑作用被削弱设得太长响应延迟又变大。这个参数在采集时通常已经写进数据集meta里推理时不要随意改动。我这次真机测试前面几次都出现末端夹爪抖动排查半天发现是相机帧率和控制频率差了一截导致同一帧图像被重复推理了两次。对齐节奏之后抖动立刻消失。这个经验在后面避坑部分还会再提。5. 这次训练和测试里踩过的坑与解决记录5.1 CUDA显存爆掉梯度累积配置训练ACT时我最先遇到的就是CUDA Out of Memory报错信息大概是torch.cuda.OutOfMemoryError: CUDA out of memory. Tried to allocate 2.14 GiB首次遇到别急着换显卡先看当前batch size是多少。我的输入包含三路1080p图像视觉编码器又是resnet18哪怕batch size只有824G的卡也快吃不消了。解决办法有两个方向一是降低batch size到4或2二是打开梯度累积。如果你用的是24G显卡batch为4再加累积步数8有效batch就是32这在多数ACT任务里都是一个足够稳定的配置。但同时要注意梯度累积会让单个step的时间变长。因为同等batch下累积步数越多你看到的step增长越慢这是正常现象不代表训练变慢了——步数本身不代表训练时长只有“有效样本处理速度”才能说明吞吐量。还有个经验技巧如果OOM频繁出现且发生在数据加载阶段而不是模型前向阶段那多半是num_workers开太多导致内存被数据加载器占满了。把它从默认值调低到2或4问题可能直接消失。5.2 训练loss不下降先把数据拉出来看看在一次实验里我换了一个新采集的数据集结果训练了好几千步loss值一直在1.0上下飘几乎不降。我当时第一反应是调大学习率试了半天没用。后来冷静下来先把训练数据里的action字段拉出来看了看。from lerobot.common.datasets.lerobot_dataset import LeRobotDataset d LeRobotDataset(./data/problem_dataset) sample d[100] print(sample[action])结果发现动作序列里后一半全是0或者接近0的值。这意味着采集过程中机械臂在某一段时间完全没动或者记录程序在某个时刻掉了线。对这样的数据进行训练策略会学到“偷懒”输出一个偏0的动作因为这样能让平均loss更低。这就是典型的数据质量问题不是超参数能救回来的。排查顺序建议是先看动作数据分布是否合理再看每路相机的图像帧是否有黑屏、冻结、严重模糊最后看episode里有没有空片段。数据里有“鬼”模型就会学到“鬼”。5.3 真机测试动作抖动或动作延迟的排查链路真机测试时动作抖动是最常见的问题之一。下面是我的排查顺序仅供参考。第一步先确认控制频率和推理频率是否对齐。用日志或print把每次推理的时间戳和控制周期打印出来如果推理时间超过了控制周期说明模型来不及输出底层驱动会重复使用上一帧动作动作自然就抖动。解决方法是降低图像分辨率或者减少推理时的batch维度因为推理时我们通常只处理单帧但视觉编码器仍然可能对序列做批处理。第二步检查相机图像的曝光和白平衡是否固定。如果相机在自动曝光模式下图像亮度会随环境变化而波动视觉特征不稳定动作自然就哆嗦。把曝光时间和白平衡手动锁定能解决很大一部分抖动。第三步看动作分块长度。在ACT里如果被测任务本身的轨迹很平滑但动作频繁抖动试着把chunk size调大一点。但chunk size也不是越大越好过大会引入明显的滞后感。这个参数更像一个旋钮需要结合任务节奏找到合适的中间值。5.4 其他值得记录的零碎问题再补充几个经常会遇到的零碎问题。一是wandb初始化失败。如果你不在训练机器上配置wandb key脚本会在启动时卡住或报错。不炼丹时可以设置环境变量WANDB_MODEoffline或WANDB_DISABLEDtrue来跳过不影响训练。想可视化就用tensorboard因为它不需要联网认证。二是checkpoint文件很大。训练过程中每个checkpoint目录都会保存模型权重和训练状态动辄几百MB到几个G。如果你磁盘空间有限建议定期清理早期checkpoint只保留最近几个。训练结束后training_state目录其实可以删掉只留pretrained_model用于推理能省不少空间。三是eval.py在真机模式下对相机索引很敏感。如果你有多路相机但接入顺序变了模型的输入通道就对不上推理结果会完全混乱。测试前建议先跑一遍相机索引检查脚本确认三路相机分别对应的是哪个设备节点。这个检查非常关键上线前必须做。训练和测试之外的一点个人体会lerobot这套流程走下来我感觉最花时间的其实不是训练本身而是训练前对数据和训练后对结果的分析。数据干净、格式正确、配置合理训练跑起来往往非常顺利真正让人崩溃的都是那些在数据采集或处理阶段埋下的隐患最后在训练和测试阶段集中爆发。所以我个人的建议是每采集完一批数据先花时间做一次完整的数据检查把动作分布、图像质量、episode完整性都过一遍再开始训练。这个检查环节看似多花了一小时实际能帮你省掉好几个小时的无效训练和排错时间。这次记录的坑和排查思路希望对正在跑lerobot的朋友有所帮助也欢迎留言交流你自己的踩坑经验。
返回列表