tl;dr
- 前回(データを50→102本に増やして「動く範囲」を可視化した)の続き。ACT は「学習データを置いた位置」でしか掴めなかった
- 素朴な期待:大量のロボットデータで事前学習済みの VLA(SmolVLA)を fine-tune すれば、データを置いていない位置も掴めるのでは?
- 同じ 102 本・同じ 3×3 評価で、ACT(ゼロから学習)と SmolVLA(fine-tune)を比べた
- 結果、成功/失敗の境界は ACT とまったく同じ(左・中央=○、右=×)。SmolVLA も右のブロックには「左側を掴みにいって外す」系統的なズレを見せた
- おまけに SmolVLA は手元の Mac で ~3Hz(ACT の 1/10)。事前学習は「動く範囲」を広げることはなく、範囲を決めるのはやはりデータの被覆だった
前回までの話
このシリーズは SO-101 という双腕アームで模倣学習を回す記録です。前回までで分かったのは、
ACT(Action Chunking Transformer)は「学習した中で一番近い軌跡」を再生するだけなので、キューブを置いた位置でしか掴めない。机を 3×3 に区切って測ると、データを厚く置いた左・中央は 100%、置いていない右は 0% と、境界がくっきり出る。
でした。じゃあ範囲を広げるにはデータを足すしかないのか、というのが前回の結論。今回はここに別の仮説を提案します。
仮説:事前学習済み VLA なら分布外も掴めるのでは?
ACT はこのタスクのデータだけでゼロから学習したモデルです。一方、最近は大量の別ロボット・別タスクで事前学習された基盤モデルがあります。HuggingFace の SmolVLA はその一つで、Vision-Language-Action モデル(画像+言語指示→動作)。
「世界のロボットデータで一般常識を持っているなら、自分のデータが手薄な右側でも、そこそこ掴めるのでは?」——これを実機で検証しました。
SmolVLA を fine-tune する
やることは ACT と変える変数をポリシーだけにすること。データ(102本)も評価(3×3グリッド)も開始姿勢も同じにします。
学習は lerobot/smolvla_base を土台に fine-tune します(ゼロから学習ではなく、事前学習の重みを引き継ぐ)。
POLICY_BASE=lerobot/smolvla_base \
TRAIN_STEPS=30000 BATCH_SIZE=16 \
RENAME_MAP='{"observation.images.front":"observation.images.camera1","observation.images.wrist":"observation.images.camera2"}' \
./scripts/train.sh
ここでカメラ名の落とし穴が一つ。SmolVLA base は入力画像を camera1/2/3 という名前で期待しますが、うちのデータは front/wrist。そのままだと Feature mismatch で落ちます。lerobot のバリデーションは「データ側のカメラ集合がポリシー側の部分集合ならOK」なので、front→camera1, wrist→camera2 にリネームすれば通ります(3台目 camera3 は無くてよい)。
RTX 3090(24GB)で回して、約3.2時間・loss 0.035 で学習完了。学習可能パラメータは 100M(全450M、画像エンコーダは凍結)でした。
評価:Mac で動かすと ~3Hz という現実
学習済み SmolVLA を実機(Mac 接続)で動かします。ここで最大の壁が出ました。
Record loop is running slower (3.1 Hz) than the target FPS (30 Hz).
制御ループが ~3Hz。ACT(ResNet18, 数十MB)が 30Hz で回っていたのに対し、SmolVLA は 500M パラメータの VLM を毎推論で回すので、Mac(MPS)では 1/10 の速度でした。
ただし SO-101 は位置制御なので、遅くてもアームは正しい目標姿勢に向かいます。実際、エピソード時間を 30→120 秒に延ばしたら、ちゃんと掴んでカップに入れました。「掴めない」のではなく「遅いだけ」。とはいえリアルタイム性は無いので、実用には推論を GPU 機に分離する async 推論が要る、という課題も見えました。
分布内の位置での自律実行がこれです(fine-tune した SmolVLA が自分で掴んでカップに入れています。3Hz 収録なので実際はもっとゆっくりですが、圧縮して再生しています)。
(余談:eval 側では --rename_map が効きません。lerobot-record はリネーム前のメタ情報でポリシーを検証するため、eval ではロボットのカメラ名そのものを camera1/camera2 にする必要がありました。学習と推論で受け口が違う、という地味な罠です。)
結果:境界は ACT と完全に一致
同じ 3×3 グリッドで、ACT の時と同じ位置にキューブを置いて測りました。
| 指標 | ACT (ゼロ学習, 100k) | SmolVLA (fine-tune, 30k) |
|---|---|---|
| 分布内(左+中央) | 100%(7/7) | 100%(3/3) |
| 分布外(右・アーム土台側) | 0%(0/4) | 0%(0/2) |
| Mac 推論レート | ~30Hz | ~3Hz |
| モデル | 数十MB (ResNet18) | 450M (SmolVLM2-500M) |
左・中央は SmolVLA も 100%。そして右は SmolVLA も全滅。しかも面白いことに、右のブロックに対して SmolVLA は 「ブロックの左側を掴みにいって外す」 という挙動を繰り返しました。これは ACT が分布外で見せた「一番近い学習軌跡(=もっと左・中央側)を再生する」のとまったく同じ機序です。
分かったこと
事前学習済みの VLA でも、データを置いていない位置は掴めない。 少なくとも今回の規模の fine-tune では、SmolVLA の「世界のロボット知識」は右ゾーンを救ってくれませんでした。成功/失敗の境界は ACT とピクセル単位で同じ形になり、右のブロックには左に外す同じ癖まで出た。
つまり前回の結論はモデルを変えても揺らぎませんでした。
- 動く範囲を決めるのは、モデルの事前学習ではなくデータの被覆。 右を掴みたければ、賢いモデルを持ってくるより、右にキューブを置いたデータを録る方が確実。
- 事前学習が効いたのは学習の速さ(ACT 100k step / 10.7h に対し、SmolVLA は 30k step / 3.2h で分布内 100%)。ただし推論は重い(Mac で 3Hz)。「速く学習できるが実行が重い」VLA と、「学習は長いが実行が軽い」ACT、というトレードオフが実機で見えたのは収穫でした。
大規模モデルを持ってくれば分布外がなんとかなる、という期待は(少なくともこの手軽な fine-tune では)成立しませんでした。ロボットに「どこで動いてほしいか」は、やっぱり録画の中で教えるしかないようです。
次にやること
- 右ゾーンにデータを足して、両モデルで赤マスが緑になるか(データ被覆仮説の直接検証)
- async 推論で SmolVLA を GPU 機にオフロードし、30Hz で本気の速度比較
- fine-tune のステップ数・データ量をもっと増やしたら、事前学習の分布外への効きは変わるのか
参考
- SmolVLA (HuggingFace)
- LeRobot
- 前回:SO-101 模倣学習の続き:データを50→102本に増やして「動く範囲」を可視化した
- 作業リポジトリ:yutoAb/so101-lab(実験メモは
docs/experiments/smolvla-vs-act.md)

