メインコンテンツまでスキップ

ACT (Action Chunking Transformer) モデルのファインチューニング

概要

ACT(Action Chunking Transformer)は、精密な操作タスク専用に設計されたエンドツーエンドの模倣学習モデルです。このモデルは、アクションチャンク(action chunks)を予測することで、従来の模倣学習における複合誤差問題を克服し、低コストハードウェアで高い成功率のロボット操作を実現します。

コア機能

  • アクションチャンキング予測:一度に複数の連続アクションを予測し、複合誤差を削減
  • Transformerアーキテクチャ:注意機構を利用してシーケンシャルデータを処理
  • エンドツーエンドトレーニング:生の観測から直接アクションを予測
  • 高成功率:精密な操作タスクで優れた性能を発揮
  • ハードウェアフレンドリー:コンシューマーグレードハードウェアで実行可能

前提条件

システム要件

  • オペレーティングシステム:Linux(Ubuntu 20.04+推奨)またはmacOS
  • Pythonバージョン:3.8+
  • GPU:NVIDIA GPU(RTX 3070以上推奨)、最低6GB VRAM
  • メモリ:最低16GB RAM
  • ストレージ容量:最低30GB利用可能容量

環境準備

1. LeRobotのインストール

# LeRobotリポジトリをクローン
git clone https://github.com/huggingface/lerobot.git
cd lerobot

# 仮想環境を作成
conda create -n lerobot python=3.10
conda activate lerobot

# 依存関係をインストール
pip install -e .

2. ACT固有の依存関係をインストール

# 追加パッケージをインストール
pip install einops
pip install timm
pip install wandb

# Weights & Biasesにログイン(オプション)
wandb login

ACTモデルアーキテクチャ

コアコンポーネント

  1. ビジョンエンコーダ:マルチビュー画像入力を処理
  2. 状態エンコーダ:ロボット状態情報を処理
  3. Transformerデコーダ:アクションシーケンスを生成
  4. アクションヘッド:最終的なアクション予測を出力

主要パラメータ

  • Chunk Size:一度に予測されるアクション数(通常50-100)
  • Context Length:履歴観測の長さ
  • Hidden Dimension:Transformerの隠れ次元
  • Number of Heads:注意ヘッドの数
  • Number of Layers:Transformerレイヤー数

データ準備

LeRobotフォーマットデータ

ACTはLeRobotフォーマットのデータセットを使用する必要があり、以下の構造を含みます:

your_dataset/
├── data/
│ ├── chunk-001/
│ │ ├── observation.images.cam_high.png
│ │ ├── observation.images.cam_low.png
│ │ ├── observation.images.cam_left_wrist.png
│ │ ├── observation.images.cam_right_wrist.png
│ │ ├── observation.state.npy
│ │ ├── action.npy
│ │ └── ...
│ └── chunk-002/
│ └── ...
├── meta.json
├── stats.safetensors
└── videos/
├── episode_000000.mp4
└── ...

データ品質要件

  • 最低50エピソード基本トレーニング用
  • 200+エピソード推奨最適な結果を得るため
  • 各エピソードは完全なタスク実行を含むべき
  • マルチビュー画像(最低2台のカメラ)
  • 高品質なアクションアノテーション

ファインチューニングトレーニング

重要なパラメータ制約

ACTモデルのn_action_stepschunk_size以下でなければなりません。両方を同じ値に設定することを推奨します(例:両方とも100に設定)。

  • chunk_size:モデルが一度に予測するアクションシーケンスの長さ
  • n_action_steps:実際に実行されるアクションステップ数

基本トレーニングコマンド

# 環境変数を設定
export HF_USER="your-huggingface-username"
export CUDA_VISIBLE_DEVICES=0

# ACTトレーニングを開始
lerobot-train \
--policy.type act \
--dataset.repo_id ${HF_USER}/your_dataset \
--batch_size 8 \
--steps 50000 \
--output_dir outputs/train/act_finetuned \
--job_name act_finetuning \
--policy.device cuda \
--policy.chunk_size 100 \
--policy.n_action_steps 100 \
--policy.n_obs_steps 1 \
--policy.optimizer_lr 1e-5 \
--policy.optimizer_weight_decay 1e-4 \
--policy.push_to_hub false \
--save_checkpoint true \
--save_freq 10000 \
--wandb.enable true

高度なトレーニング構成

マルチカメラ構成

# マルチカメラ設定でのACTトレーニング
lerobot-train \
--policy.type act \
--dataset.repo_id ${HF_USER}/your_dataset \
--batch_size 4 \
--steps 100000 \
--output_dir outputs/train/act_multicam \
--job_name act_multicam_training \
--policy.device cuda \
--policy.chunk_size 100 \
--policy.n_action_steps 100 \
--policy.n_obs_steps 2 \
--policy.vision_backbone resnet18 \
--policy.dim_model 512 \
--policy.dim_feedforward 3200 \
--policy.n_encoder_layers 4 \
--policy.n_decoder_layers 1 \
--policy.n_heads 8 \
--policy.optimizer_lr 1e-5 \
--policy.optimizer_weight_decay 1e-4 \
--policy.push_to_hub false \
--save_checkpoint true \
--wandb.enable true

メモリ最適化構成

# VRAMが小さいGPU向け
lerobot-train \
--policy.type act \
--dataset.repo_id io-ai-data/lerobot_data \
--batch_size 2 \
--steps 75000 \
--output_dir outputs/train/act_memory_opt \
--job_name act_memory_optimized \
--policy.device cuda \
--policy.chunk_size 100 \
--policy.n_action_steps 100 \
--policy.n_obs_steps 1 \
--policy.vision_backbone resnet18 \
--policy.dim_model 256 \
--policy.optimizer_lr 1e-5 \
--policy.use_amp true \
--num_workers 2 \
--policy.push_to_hub false \
--save_checkpoint true \
--wandb.enable true

パラメータ詳細説明

コアパラメータ

パラメータ意味推奨値説明
--policy.typeポリシータイプactACTモデルタイプ
--policy.pretrained_path事前学習済みモデルパスlerobot/actLeRobot公式ACTモデル(オプション)
--dataset.repo_idデータセットリポジトリID${HF_USER}/datasetあなたのHuggingFaceデータセット
--batch_sizeバッチサイズ8VRAMに応じて調整、RTX 3070は4-8推奨
--stepsトレーニングステップ数50000精密タスクは50000-100000ステップ推奨
--output_dir出力ディレクトリoutputs/train/act_finetunedモデル保存パス
--job_nameジョブ名act_finetuningログと実験追跡用(オプション)

ACT固有パラメータ

パラメータ意味推奨値説明
--policy.chunk_sizeアクションチャンクサイズ100毎回予測されるアクション数
--policy.n_action_steps実行アクションステップ100実際に実行されるアクション数
--policy.n_obs_steps観測ステップ1履歴観測の数
--policy.vision_backboneビジョンバックボーンresnet18画像特徴抽出ネットワーク
--policy.dim_modelモデル次元512Transformerメイン次元
--policy.dim_feedforwardフィードフォワード次元3200Transformerフィードフォワードレイヤー次元
--policy.n_encoder_layersエンコーダレイヤー数4Transformerエンコーダレイヤー数
--policy.n_decoder_layersデコーダレイヤー数1Transformerデコーダレイヤー数
--policy.n_heads注意ヘッド数8マルチヘッド注意のヘッド数
--policy.use_vaeVAEを使用true変分目的最適化

トレーニングパラメータ

パラメータ意味推奨値説明
--policy.optimizer_lr学習率1e-5ACTは小さな学習率を推奨
--policy.optimizer_weight_decay重み減衰0.0正則化パラメータ
--policy.optimizer_lr_backboneバックボーン学習率1e-5ビジョンエンコーダ学習率
--policy.use_amp混合精度trueVRAMを節約
--num_workersデータローディングスレッド数4CPUコア数に応じて調整
--policy.push_to_hubHubへプッシュfalseHuggingFaceへモデルをアップロードするか(repo_idが必要)
--save_checkpointチェックポイント保存trueトレーニングチェックポイントを保存するか
--save_freq保存頻度10000チェックポイント保存間隔

トレーニング監視とデバッグ

Weights & Biases統合

# 詳細なW&B構成
lerobot-train \
--policy.type act \
--dataset.repo_id your-name/your-dataset \
--batch_size 8 \
--steps 50000 \
--policy.push_to_hub false \
--wandb.enable true \
--wandb.project act_experiments \
--wandb.notes "ACT training with 4 cameras" \
# ... その他のパラメータ

主要メトリクス監視

トレーニング中に注目すべきメトリクス:

  • Total Loss:全体的な損失、安定して減少すべき
  • Action Loss:アクション予測損失(L1/L2損失)
  • Learning Rate:学習率変化曲線
  • Gradient Norm:勾配ノルム、勾配爆発を監視
  • GPU Memory:VRAM使用状況
  • Training Speed:1秒あたりに処理されるサンプル数

トレーニングログ分析

# log_analysis.py
import wandb
import matplotlib.pyplot as plt

def analyze_training_logs(project_name, run_name):
api = wandb.Api()
run = api.run(f"{project_name}/{run_name}")

# トレーニング指標を取得
history = run.history()

# 損失曲線をプロット
plt.figure(figsize=(12, 4))

plt.subplot(1, 3, 1)
plt.plot(history['step'], history['train/total_loss'])
plt.title('Total Loss')
plt.xlabel('Step')
plt.ylabel('Loss')

plt.subplot(1, 3, 2)
plt.plot(history['step'], history['train/action_loss'])
plt.title('Action Loss')
plt.xlabel('Step')
plt.ylabel('Loss')

plt.subplot(1, 3, 3)
plt.plot(history['step'], history['train/learning_rate'])
plt.title('Learning Rate')
plt.xlabel('Step')
plt.ylabel('LR')

plt.tight_layout()
plt.savefig('training_analysis.png')
plt.show()

if __name__ == "__main__":
analyze_training_logs("act_experiments", "act_v1_multicam")

モデル評価

オフライン評価

# offline_evaluation.py
import torch
import numpy as np
from lerobot.policies.act.modeling_act import ACTPolicy
from lerobot.datasets.lerobot_dataset import LeRobotDataset

def evaluate_act_model(model_path, dataset_path):
# モデルを読み込み
policy = ACTPolicy.from_pretrained(model_path, device="cuda")
policy.eval()

# テストデータセットを読み込み
dataset = LeRobotDataset(dataset_path, split="test")

total_l1_loss = 0
total_l2_loss = 0
num_samples = 0

with torch.no_grad():
for batch in dataset:
# モデル予測
prediction = policy(batch)

# 損失を計算
target_actions = batch['action']
predicted_actions = prediction['action']

l1_loss = torch.mean(torch.abs(predicted_actions - target_actions))
l2_loss = torch.mean((predicted_actions - target_actions) ** 2)

total_l1_loss += l1_loss.item()
total_l2_loss += l2_loss.item()
num_samples += 1

avg_l1_loss = total_l1_loss / num_samples
avg_l2_loss = total_l2_loss / num_samples

print(f"Average L1 Loss: {avg_l1_loss:.4f}")
print(f"Average L2 Loss: {avg_l2_loss:.4f}")

return avg_l1_loss, avg_l2_loss

if __name__ == "__main__":
model_path = "outputs/train/act_finetuned/checkpoints/last"
dataset_path = "path/to/your/test/dataset"
evaluate_act_model(model_path, dataset_path)

オンライン評価(ロボット環境)

# robot_evaluation.py
import torch
import numpy as np
from lerobot.policies.act.modeling_act import ACTPolicy

class ACTRobotController:
def __init__(self, model_path, camera_names):
self.policy = ACTPolicy.from_pretrained(model_path, device="cuda")
self.policy.eval()
self.camera_names = camera_names
self.action_queue = []

def get_action(self, observations):
# アクションキューが空の場合、新しいアクションチャンクを予測
if len(self.action_queue) == 0:
with torch.no_grad():
# 入力を構築
batch = self.prepare_observation(observations)

# アクションチャンクを予測
prediction = self.policy(batch)
actions = prediction['action'].cpu().numpy()[0] # [chunk_size, action_dim]

# アクションをキューに追加
self.action_queue = list(actions)

# キューから次のアクションを返す
return self.action_queue.pop(0)

def prepare_observation(self, observations):
batch = {}

# 画像観測を処理
for cam_name in self.camera_names:
image_key = f"observation.images.{cam_name}"
if image_key in observations:
image = observations[image_key]
# 画像を前処理(正規化、リサイズなど)
image_tensor = self.preprocess_image(image)
batch[image_key] = image_tensor.unsqueeze(0)

# 状態観測を処理
if "observation.state" in observations:
state = torch.tensor(observations["observation.state"], dtype=torch.float32)
batch["observation.state"] = state.unsqueeze(0)

return batch

def preprocess_image(self, image):
# 画像前処理ロジック
# トレーニング時に使用した前処理と一致させる必要がある
image_tensor = torch.tensor(image).permute(2, 0, 1).float() / 255.0
return image_tensor

# 使用例
if __name__ == "__main__":
controller = ACTRobotController(
model_path="outputs/train/act_finetuned/checkpoints/last",
camera_names=["cam_high", "cam_low", "cam_left_wrist", "cam_right_wrist"]
)

# ロボット制御ループをシミュレート
for step in range(100):
# 現在の観測を取得(実際のロボットから取得する必要がある)
observations = {
"observation.images.cam_high": np.random.randint(0, 255, (480, 640, 3)),
"observation.images.cam_low": np.random.randint(0, 255, (480, 640, 3)),
"observation.state": np.random.randn(7)
}

# アクションを取得
action = controller.get_action(observations)

# アクションを実行(ロボットに送信)
print(f"Step {step}: Action = {action}")

# 実際のロボットにアクションを送信すべき
# robot.execute_action(action)

デプロイと最適化

モデル量子化

# quantization.py
import torch
from lerobot.policies.act.modeling_act import ACTPolicy

def quantize_act_model(model_path, output_path):
# モデルを読み込み
policy = ACTPolicy.from_pretrained(model_path, device="cpu")
policy.eval()

# 動的量子化
quantized_policy = torch.quantization.quantize_dynamic(
policy,
{torch.nn.Linear},
dtype=torch.qint8
)

# 量子化モデルを保存
torch.save(quantized_policy.state_dict(), output_path)
print(f"Quantized model saved to {output_path}")

return quantized_policy

if __name__ == "__main__":
quantize_act_model(
"outputs/train/act_finetuned/checkpoints/last",
"outputs/act_quantized.pth"
)

推論最適化

# optimized_inference.py
import torch
import torch.jit
from lerobot.policies.act.modeling_act import ACTPolicy

class OptimizedACTInference:
def __init__(self, model_path, use_jit=True):
self.policy = ACTPolicy.from_pretrained(model_path, device="cuda")
self.policy.eval()

if use_jit:
# TorchScriptを使用して最適化
self.policy = torch.jit.script(self.policy)

# モデルをウォームアップ
self.warmup()

def warmup(self):
# ダミーデータでモデルをウォームアップ
dummy_batch = {
"observation.images.cam_high": torch.randn(1, 3, 224, 224, device="cuda"),
"observation.images.cam_low": torch.randn(1, 3, 224, 224, device="cuda"),
"observation.state": torch.randn(1, 7, device="cuda")
}

with torch.no_grad():
for _ in range(10):
_ = self.policy(dummy_batch)

@torch.no_grad()
def predict(self, observations):
# 高速推論
prediction = self.policy(observations)
return prediction['action'].cpu().numpy()

if __name__ == "__main__":
inference = OptimizedACTInference(
"outputs/train/act_finetuned/checkpoints/last"
)

# 推論速度をテスト
import time

observations = {
"observation.images.cam_high": torch.randn(1, 3, 224, 224, device="cuda"),
"observation.images.cam_low": torch.randn(1, 3, 224, 224, device="cuda"),
"observation.state": torch.randn(1, 7, device="cuda")
}

start_time = time.time()
for _ in range(100):
action = inference.predict(observations)
end_time = time.time()

avg_inference_time = (end_time - start_time) / 100
print(f"Average inference time: {avg_inference_time:.4f} seconds")
print(f"Inference frequency: {1/avg_inference_time:.2f} Hz")

ベストプラクティス

データ収集の推奨事項

  1. マルチビューデータ:複数のカメラを使用して豊富な視覚情報を取得
  2. 高品質なデモンストレーション:デモンストレーションデータの一貫性と正確性を確保
  3. タスクの多様性:異なる開始状態と目標構成を含める
  4. 失敗ケース:ロバスト性を向上させるために適切に失敗ケースを含める

トレーニング最適化の推奨事項

  1. アクションチャンクサイズ:タスクの複雑さに基づいてchunk_sizeを調整
  2. 学習率スケジューリング:コサインアニーリングまたはステップ減衰を使用
  3. 正則化:適切に重み減衰とドロップアウトを使用
  4. データ拡張:画像に適切な拡張を適用

デプロイ最適化の推奨事項

  1. モデル圧縮:量子化とプルーニング技術を使用してモデルサイズを削減
  2. 推論加速:TensorRTまたはONNXを使用して推論を最適化
  3. メモリ管理:アクションキューと観測キャッシュを適切に管理
  4. リアルタイム保証:推論頻度が制御要件を満たすことを確保

よくある質問(FAQ)

Q: ACTは他の模倣学習方法と比較してどのような利点がありますか?

A: ACTの主な利点には以下が含まれます:

  • 複合誤差の削減:アクションチャンクを予測することで誤差の蓄積を削減
  • 成功率の向上:精密な操作タスクで優れた性能を発揮
  • エンドツーエンドトレーニング:手作業で特徴を設計する必要がない
  • マルチモーダル融合:視覚と状態情報を効果的に融合

Q: 適切なchunk_sizeを選択するには?

A: chunk_sizeの選択はタスクの特性に依存します:

  • 高速タスク:chunk_size = 10-30
  • 中速タスク:chunk_size = 50-100
  • 低速タスク:chunk_size = 100-200
  • 一般的には50から試すことを推奨

Q: トレーニングにはどのくらい時間がかかりますか?

A: トレーニング時間は複数の要因に依存します:

  • データセットサイズ:100エピソードは約4-8時間(RTX 3070)
  • モデルの複雑さ:より大きなモデルはより多くの時間が必要
  • ハードウェア構成:より良いGPUはトレーニング時間を大幅に削減できる
  • 収束要件:通常50000-100000ステップが必要

Q: マルチカメラデータを処理するには?

A: マルチカメラ処理の推奨事項:

  • カメラ選択:情報が補完的なビューポイントを選択
  • 特徴融合:特徴レベルで融合
  • 注意機構:モデルに重要なビューポイントに注目することを学習させる
  • 計算リソース:マルチカメラは計算負荷を増加させることに注意

Q: モデルの汎化能力を向上させるには?

A: 汎化能力を向上させる方法:

  • データの多様性:異なる条件下でデータを収集
  • データ拡張:画像とアクションの拡張技術を使用
  • 正則化:適切な重み減衰とドロップアウト
  • ドメインランダム化:シミュレーションでドメインランダム化技術を使用
  • マルチタスク学習:複数の関連タスクで共同トレーニング

関連リソース

更新ログ

  • 2024-01: 初版リリース
  • 2024-02: マルチカメラサポートを追加
  • 2024-03: トレーニング効率と推論速度を最適化
  • 2024-04: モデル圧縮とデプロイ最適化を追加