paper_rob__ibrl
Imitation Bootstrapped Reinforcement Learning (IBRL) trains a BC policy on demonstrations, then uses it alongside an RL actor during online training: at each step, a learned Q-function selects whichever action (RL or BC) has higher value for both exploration and computing TD bootstrap targets. This creates an automatic curriculum where BC dominates early and RL gradually takes over, yielding strong sample efficiency on pixel-based and state-based manipulation tasks.
Paper Info
Method Overview
- Pretrain a BC policy on demonstration data (HDF5 format from Robomimic)
- Initialize RL actor, dual-Q critic, and target networks
- Warm up: collect episodes into the replay buffer using BC policy actions
- Online RL loop: at each step, obtain both RL and BC actions, use the critic to select the better one (IBRL selection) for environment interaction
- For TD target computation, apply the same Q-based selection on next-state actions (IBRL bootstrapping)
- Update critic with MSE loss on Bellman targets, update actor to maximize Q, soft-update targets
Key insight: By using the BC policy to propose alternative actions for Q-based selection in both exploration and bootstrapping, IBRL leverages high-quality demonstration knowledge from the start of training without requiring explicit scheduling or regularization.
Paper-Code Mapping
| Paper Concept |
Code Location |
Notes |
| IBRL action selection (hard) |
rl/q_agent.py:QAgent._act_ibrl |
argmax Q over {a_rl, a_bc}, eps-greedy support |
| IBRL action selection (soft) |
rl/q_agent.py:QAgent._act_ibrl_soft |
softmax(Q * beta) sampling over {a_rl, a_bc} |
| TD target with IBRL bootstrap |
rl/q_agent.py:QAgent.update_critic |
Calls _act_ibrl/_act_ibrl_soft with use_target=True |
| Critic update (dual-Q) |
rl/q_agent.py:QAgent.update_critic |
MSE loss, min(Q1, Q2) for target |
| Actor update |
rl/q_agent.py:QAgent.update_actor |
Maximize Q via policy gradient |
| RFT actor update with BC reg |
rl/q_agent.py:QAgent.update_actor_rft |
bc_loss_coef * ratio * bc_loss, dynamic ratio via Q-comparison |
| BC policy (pixel) |
bc/bc_policy.py:BcPolicy |
MultiViewEncoder -> MLP -> tanh |
| BC policy (state) |
bc/bc_policy.py:StateBcPolicy |
MLP with dropout -> tanh |
| RL actor (pixel) |
rl/actor.py:Actor |
Feature compress + MLP -> TruncatedNormal |
| RL actor (state) |
rl/actor.py:FcActor |
MLP with dropout -> TruncatedNormal |
| Dual-Q critic (pixel) |
rl/critic.py:Critic |
Two _QNet or SpatialEmbQNet heads |
| Multi-Q critic (state, RED-Q) |
rl/critic.py:MultiFcQ |
10 parallel Q-nets via _MultiLinear, sample k=2 for target |
| ViT encoder |
networks/encoder.py:VitEncoder |
MinVit, default patch=8, depth=3, embed=128 |
| ResNet encoder |
networks/encoder.py:ResNetEncoder |
Custom ResNet with configurable stem/downsample |
| ResNet96 encoder |
networks/encoder.py:ResNet96Encoder |
ResNet variant for 96x96 inputs |
| DrQ encoder |
networks/encoder.py:DrQEncoder |
4-layer conv, rescale to 84x84 |
| Multi-view fusion (BC) |
bc/multiview_encoder.py:MultiViewEncoder |
Per-camera ResNet + compress + cat/add/mult fusion |
| Spatial embedding (critic) |
rl/critic.py:SpatialEmbQNet |
Learned weighted sum over patch features fused with action |
| Spatial embedding (actor) |
rl/actor.py:SpatialEmb |
Learned weighted sum over patch features |
| Data augmentation |
rl/q_agent.py:QAgent.aug |
RandomShiftsAug(pad=4) — random shift crop |
| Replay buffer |
rl/replay.py:ReplayBuffer |
C++ rela.SingleStepTransitionReplay (pybind11), n-step returns |
| Exploration noise schedule |
common_utils/py/ibrl_utils.py:schedule |
linear(max, min, duration) decay |
| TruncatedNormal distribution |
common_utils/py/ibrl_utils.py:TruncatedNormal |
Clamped Gaussian with optional action norm clipping |
| Robomimic env wrapper |
env/robosuite_wrapper.py:PixelRobosuite |
Image extraction, resize, prop/state stacking |
| Meta-World env wrapper |
env/metaworld_wrapper.py:PixelMetaWorld |
Frame stacking, obs_stack support |
| Config system |
train_rl.py:MainConfig |
pyrallis dataclass, YAML + CLI overrides |
Setup
Dependencies
- Python 3.9
- PyTorch 2.1.0 (CUDA 12.1)
- MuJoCo 2.1 (mujoco210 binary in
~/.mujoco/mujoco210)
- mujoco-py 2.1.2.14
- Key packages:
robosuite (git), metaworld (git), pyrallis, h5py, wandb, einops, rich
Installation
# MuJoCo 2.1
wget https://mujoco.org/download/mujoco210-linux-x86_64.tar.gz
mkdir -p ~/.mujoco && tar -xzf mujoco210-linux-x86_64.tar.gz -C ~/.mujoco/
# Clone and setup
git clone --recursive https://github.com/hengyuan-hu/ibrl.git
cd ibrl
conda create -n ibrl python=3.9 && conda activate ibrl
source set_env.sh # sets PYTHONPATH, MUJOCO paths, OMP_NUM_THREADS=1
# Install packages
pip install torch==2.1.0 torchvision==0.16.0 --index-url https://download.pytorch.org/whl/cu121
pip install -r requirements.txt
# Compile C++ replay buffer (pybind11)
cd common_utils && make && cd ..
Pre-trained Weights & Data
Download from Google Drive, extract to release/:
release/
├── cfgs/ # YAML configs (shipped with repo)
├── data/ # HDF5 demo datasets
│ ├── robomimic/{can,square}/processed_data96.hdf5
│ └── metaworld/{Assembly,...}/dataset.hdf5
└── model/ # Pretrained BC checkpoints
├── robomimic/{can,square}/model0.pt
└── metaworld/path{Assembly,...}_*/model1.pt
Usage Scenarios
Train IBRL (pixel, Robomimic)
python train_rl.py --config_path release/cfgs/robomimic_rl/can_ibrl.yaml \
--save_dir exp/can_ibrl --use_wb 0
Train RLPD baseline
python train_rl.py --config_path release/cfgs/robomimic_rl/can_rlpd.yaml \
--save_dir exp/can_rlpd --use_wb 0
Train RFT baseline (two-step)
# Step 1: Pretrain RL actor with BC loss
python train_rl.py --config_path release/cfgs/robomimic_rl/can_rft.yaml \
--pretrain_only 1 --pretrain_num_epoch 5 --load_pretrained_agent None \
--save_dir exp/can_pretrain --use_wb 0
# Step 2: RL fine-tune with BC regularization
python train_rl.py --config_path release/cfgs/robomimic_rl/can_rft.yaml \
--load_pretrained_agent exp/can_pretrain/model0.pt \
--save_dir exp/can_rft --use_wb 0
Train on Meta-World
python mw_main/train_rl_mw.py \
--config_path release/cfgs/metaworld/ibrl_basic.yaml \
--bc_policy assembly --save_dir exp/mw_ibrl --use_wb 0
Key Config Flags
| Flag |
Default |
Description |
--config_path |
(required) |
YAML config file path |
--task_name |
"Lift" |
Robomimic task: Lift, PickPlaceCan, NutAssemblySquare, TwoArmTransport, ToolHang |
--bc_policy |
"" |
Path to pretrained BC model (or task name for Meta-World) |
--q_agent.act_method |
"rl" |
Action selection: "rl", "ibrl", "ibrl_soft" |
--q_agent.bootstrap_method |
same as act_method |
Bootstrap action selection (can differ from act_method) |
--q_agent.enc_type |
"vit" |
Encoder: "vit", "resnet", "resnet96", "drq" |
--use_state |
0 |
1 = state-based (no images), 0 = pixel-based |
--mix_rl_rate |
1.0 |
Fraction of RL data in batch; 0.5 = RLPD-style demo mixing |
--add_bc_loss |
0 |
1 = add BC regularization to actor loss (RFT) |
--num_train_step |
200000 |
Total environment steps |
--replay_buffer_size |
500 |
Max episodes in replay buffer |
--preload_num_data |
0 |
Number of demo episodes to preload |
--stddev_max/min/step |
1.0/0.1/500000 |
Exploration noise linear schedule |
--num_warm_up_episode |
50 |
BC-guided warm-up episodes |
--save_dir |
"exps/rl/run1" |
Output directory for logs, configs, model checkpoints |
--use_wb |
0 |
1 = log to Weights & Biases |
--mp_eval |
0 |
1 = parallel evaluation (10 processes) |
Code Integration Guide
Minimal Imports
import sys
sys.path.append("/path/to/ibrl")
from rl.q_agent import QAgent, QAgentConfig
from bc.bc_policy import BcPolicy, BcPolicyConfig
from networks.encoder import VitEncoder, VitEncoderConfig
Model Instantiation & Inference
import torch
from rl.q_agent import QAgent, QAgentConfig
# Create QAgent for pixel-based task
cfg = QAgentConfig()
cfg.act_method = "ibrl" # or "rl", "ibrl_soft"
cfg.enc_type = "vit"
cfg.use_prop = 1
cfg.vit.embed_style = "embed2"
cfg.vit.depth = 1
cfg.actor.dropout = 0.5
cfg.critic.spatial_emb = 1024
agent = QAgent(
use_state=False,
obs_shape=(3, 96, 96), # (C*obs_stack, H, W)
prop_shape=(27,), # prop_dim * prop_stack (9 * 3)
action_dim=7, # OSC_POSE: 6 EE + 1 gripper
rl_camera="robot0_eye_in_hand",
cfg=cfg,
)
# Load trained weights
agent.load_state_dict(torch.load("model0.pt"))
agent.eval()
# Inference: obs is dict with camera images and proprioception
# Images: uint8 [C, H, W], will be normalized internally (/255 - 0.5)
# Prop: float32 [prop_dim]
obs = {
"robot0_eye_in_hand": torch.randint(0, 255, (3, 96, 96)).cuda(),
"prop": torch.randn(27).cuda(),
}
with torch.no_grad():
action = agent.act(obs, eval_mode=True) # returns [7] tensor on CPU
Loading a Full Trained Model
import train_rl
agent, eval_env, eval_env_params = train_rl.load_model("path/to/model0.pt", "cuda")
# agent: QAgent with BC policy attached (if bc_policy was set in config)
# eval_env: PixelRobosuite ready for evaluation
Data Format
| Field |
Shape / Type |
Description |
| Camera obs |
(C, H, W) uint8 |
Per-camera image, C=3*obs_stack, H=W=96 (rl_image_size) |
prop |
(prop_dim,) float32 |
EE pos(3) + quat(4) + gripper(2) = 9, stacked prop_stack times |
state |
(state_dim,) float32 |
Full state (e.g. 19 for Lift), stacked state_stack times |
action |
(action_dim,) float32 |
OSC_POSE: 6D EE delta + 1 gripper, range [-1, 1] |
| HDF5 dataset |
data/demo_N/obs/{camera}_image, actions, rewards |
Robomimic format |
Integration Notes
- The repo must be on
PYTHONPATH due to absolute imports (import common_utils, from rl.q_agent import ...)
common_utils has a C++ pybind11 module (rela) that must be compiled with make before use
- The
QAgent owns separate optimizers internally; for custom training loops, access agent.encoder_opt, agent.critic_opt, agent.actor_opt
- BC policies are stored in
agent.bc_policies list and must be added via agent.add_bc_policy()
- Image observations must have pixel values > 5 (raw uint8 range); normalization is done inside the encoder
source set_env.sh is critical: it sets PYTHONPATH, MuJoCo paths, and OMP_NUM_THREADS=1 (needed for parallel eval)
Core Architecture
IBRL Training Loop
==================
Demonstrations (HDF5)
|
v
BC Policy Training (train_bc.py)
|
+-- BcPolicy: MultiViewEncoder(per-cam ResNet + compress + cat) -> MLP -> tanh
| or
+-- StateBcPolicy: MLP(dropout=0.5) -> tanh
|
v
RL Training (train_rl.py)
|
+-- QAgent (rl/q_agent.py)
| |
| +-- Encoder: VitEncoder / ResNetEncoder / DrQEncoder
| | - Input: [B, C, 96, 96] uint8 -> /255 - 0.5
| | - Output: [B, num_patch, patch_dim]
| |
| +-- Actor: feat -> compress(Linear+LN+ReLU or SpatialEmb) -> MLP -> TruncatedNormal
| | - dropout=0.5 on RL actor helps prevent overfitting
| |
| +-- Critic: dual-Q, feat+action -> _QNet or SpatialEmbQNet -> scalar
| | - Target: min(Q1_target, Q2_target)
| |
| +-- IBRL Selection (act + bootstrap):
| a_rl = Actor(s), a_bc = BCPolicy(s)
| a* = argmax_{a in {a_rl, a_bc}} Q_target(s, a) [hard]
| or: sample from softmax(Q * beta) [soft]
|
+-- Replay Buffer (C++ pybind11)
| - N-step returns (default n=3)
| - Separate BC replay for demo mixing (RLPD: mix_rl_rate=0.5)
|
+-- Data Augmentation: RandomShiftsAug(pad=4)
State-based variant:
Actor = FcActor(MLP, dropout=0.5)
Critic = MultiFcQ(10 Q-nets via _MultiLinear, RED-Q: sample k=2 for min)
Repo Structure
| Path |
Purpose |
train_rl.py |
Main RL training entry point: MainConfig, Workspace, training loop |
train_bc.py |
BC pretraining entry point: MainConfig, training loop, load_model() |
bc/bc_policy.py |
BcPolicy (pixel, MultiViewEncoder+MLP), StateBcPolicy (state, MLP) |
bc/multiview_encoder.py |
MultiViewEncoder: per-camera ResNet encoders with fusion (cat/add/mult) |
bc/dataset.py |
RobomimicDataset: HDF5 loading, DatasetConfig, sample_bc() |
rl/q_agent.py |
QAgent: core IBRL logic, _act_ibrl, _act_ibrl_soft, update_critic, update_actor, update_actor_rft |
rl/actor.py |
Actor (pixel, with SpatialEmb), FcActor (state) |
rl/critic.py |
Critic (dual-Q with _QNet/SpatialEmbQNet), MultiFcQ (multi-Q via _MultiLinear) |
rl/replay.py |
ReplayBuffer: wraps C++ rela.SingleStepTransitionReplay, BC replay, add_demos_to_replay() |
networks/encoder.py |
VitEncoder, ResNetEncoder, ResNet96Encoder, DrQEncoder |
networks/min_vit.py |
MinVit: minimal ViT implementation |
networks/resnet.py |
Custom ResNet with configurable stem/downsample |
networks/resnet_rl.py |
ResNet96 for 96x96 inputs |
env/robosuite_wrapper.py |
PixelRobosuite: robosuite env with image extraction, resize, obs stacking |
env/metaworld_wrapper.py |
PixelMetaWorld: Meta-World env wrapper |
mw_main/train_rl_mw.py |
Meta-World RL training (IBRL/RLPD/RFT), BC_POLICIES and BC_DATASETS dicts |
mw_main/train_bc_mw.py |
Meta-World BC training |
mw_main/mw_replay.py |
Meta-World replay buffer |
evaluate/eval.py |
Single-process evaluation: run_eval() |
evaluate/multi_process_eval.py |
Multi-process evaluation: run_eval_mp() |
common_utils/py/ibrl_utils.py |
TruncatedNormal, eval_mode, soft_update_params, schedule(), orth_weight_init |
common_utils/py/data_aug.py |
RandomShiftsAug |
common_utils/ |
C++ pybind11 replay buffer (rela module), logging, saving utilities |
release/cfgs/ |
YAML configs for all methods: robomimic_rl/, robomimic_bc/, metaworld/ |
set_env.sh |
Environment setup: PYTHONPATH, MuJoCo paths, OMP_NUM_THREADS=1 |
Three Training Paradigms
| Method |
Mechanism |
Key Config |
| IBRL |
Q-based selection between RL & BC actions for both exploration and bootstrapping |
act_method: "ibrl", bc_policy: path/to/model.pt |
| RLPD |
Mix demonstration data into replay buffer (50/50 by default) |
act_method: "rl", mix_rl_rate: 0.5, preload_num_data: N |
| RFT |
Pretrain RL actor with BC loss, then fine-tune with BC regularization |
act_method: "rl", add_bc_loss: 1, bc_loss_coef: 0.1, load_pretrained_agent: path |
Tips & Gotchas
- C++ compilation required:
cd common_utils && make is mandatory; requires cmake, gcc, and pybind11 (included as submodule). If you see GLIBCXX_3.4.30 not found, symlink system libstdc++ into conda env
source set_env.sh: must run once per shell; sets PYTHONPATH=$PWD, MuJoCo paths, and OMP_NUM_THREADS=1 (critical for parallel eval performance)
- MuJoCo 2.1 specifically: the repo uses
mujoco-py which requires the old MuJoCo 2.1 binary (not the newer mujoco pip package alone)
- GPU memory: pixel-based ViT training uses ~16GB VRAM; ResNet/DrQ encoders use less
- Warm-up phase: the first 50 episodes use BC policy actions to fill the replay buffer; ensure
bc_policy path is valid
- Actor dropout: 0.5 dropout on the RL actor is important for IBRL; it prevents overfitting to demonstration-heavy early data. During critic target computation,
actor_target.training is asserted True (dropout active)
assert False at end: both train_rl.py and train_bc.py deliberately crash at the end (assert False) to signal completion; this is intentional
- Image normalization: encoders expect raw pixel values (>5), normalization
/255 - 0.5 happens inside the encoder forward pass
- Evaluation parallelism:
--mp_eval 1 spawns 10 processes; requires OMP_NUM_THREADS=1 to avoid thread contention
- Config system: pyrallis supports YAML file + CLI overrides; nested fields use dots:
--q_agent.actor.dropout 0.3
- Action space: Robomimic uses OSC_POSE (6D end-effector delta + 1 gripper), actions clamped to [-1, 1] via
Tanh output
- HDF5 data format: demos stored as
data/demo_N/obs/{camera}_image, data/demo_N/actions, data/demo_N/rewards
- Meta-World task names: use short names (
assembly, boxclose, coffeepush, stickpull) which map to BC_POLICIES and BC_DATASETS dicts in mw_main/train_rl_mw.py
update_freq: 2: RL update happens every 2 env steps; critic updates num_critic_update times, actor updates only on the last critic iteration (RED-Q style)
1---2name: paper-rob-ibrl3description: IBRL uses Q-based selection between RL and BC actions for exploration and bootstrapping to achieve sample-efficient robotic manipulation.4---56# paper_rob__ibrl78Imitation Bootstrapped Reinforcement Learning (IBRL) trains a BC policy on demonstrations, then uses it alongside an RL actor during online training: at each step, a learned Q-function selects whichever action (RL or BC) has higher value for both exploration and computing TD bootstrap targets. This creates an automatic curriculum where BC dominates early and RL gradually takes over, yielding strong sample efficiency on pixel-based and state-based manipulation tasks.910## Paper Info1112| Field | Value |13|-------|-------|14| Title | Imitation Bootstrapped Reinforcement Learning |15| Authors | Hengyuan Hu, Suvir Mirchandani, Dorsa Sadigh |16| Year | 2023 |17| Venue | arXiv (cs.LG) |18| Paper | https://arxiv.org/abs/2311.02198 |19| Code | https://github.com/hengyuan-hu/ibrl |20| Website | https://ibrl.hengyuanhu.com/ |21| Data/Weights | [Google Drive](https://drive.google.com/file/d/1F2yH84Iqv0qRPmfH8o-kSzgtfaoqMzWE/view?usp=sharing) |2223## Method Overview24251. Pretrain a BC policy on demonstration data (HDF5 format from Robomimic)262. Initialize RL actor, dual-Q critic, and target networks273. Warm up: collect episodes into the replay buffer using BC policy actions284. Online RL loop: at each step, obtain both RL and BC actions, use the critic to select the better one (IBRL selection) for environment interaction295. For TD target computation, apply the same Q-based selection on next-state actions (IBRL bootstrapping)306. Update critic with MSE loss on Bellman targets, update actor to maximize Q, soft-update targets3132Key insight: By using the BC policy to propose alternative actions for Q-based selection in both exploration and bootstrapping, IBRL leverages high-quality demonstration knowledge from the start of training without requiring explicit scheduling or regularization.3334## Paper-Code Mapping3536| Paper Concept | Code Location | Notes |37|---------------|---------------|-------|38| IBRL action selection (hard) | `rl/q_agent.py:QAgent._act_ibrl` | argmax Q over {a_rl, a_bc}, eps-greedy support |39| IBRL action selection (soft) | `rl/q_agent.py:QAgent._act_ibrl_soft` | softmax(Q * beta) sampling over {a_rl, a_bc} |40| TD target with IBRL bootstrap | `rl/q_agent.py:QAgent.update_critic` | Calls `_act_ibrl`/`_act_ibrl_soft` with `use_target=True` |41| Critic update (dual-Q) | `rl/q_agent.py:QAgent.update_critic` | MSE loss, min(Q1, Q2) for target |42| Actor update | `rl/q_agent.py:QAgent.update_actor` | Maximize Q via policy gradient |43| RFT actor update with BC reg | `rl/q_agent.py:QAgent.update_actor_rft` | `bc_loss_coef * ratio * bc_loss`, dynamic ratio via Q-comparison |44| BC policy (pixel) | `bc/bc_policy.py:BcPolicy` | MultiViewEncoder -> MLP -> tanh |45| BC policy (state) | `bc/bc_policy.py:StateBcPolicy` | MLP with dropout -> tanh |46| RL actor (pixel) | `rl/actor.py:Actor` | Feature compress + MLP -> TruncatedNormal |47| RL actor (state) | `rl/actor.py:FcActor` | MLP with dropout -> TruncatedNormal |48| Dual-Q critic (pixel) | `rl/critic.py:Critic` | Two `_QNet` or `SpatialEmbQNet` heads |49| Multi-Q critic (state, RED-Q) | `rl/critic.py:MultiFcQ` | 10 parallel Q-nets via `_MultiLinear`, sample k=2 for target |50| ViT encoder | `networks/encoder.py:VitEncoder` | MinVit, default patch=8, depth=3, embed=128 |51| ResNet encoder | `networks/encoder.py:ResNetEncoder` | Custom ResNet with configurable stem/downsample |52| ResNet96 encoder | `networks/encoder.py:ResNet96Encoder` | ResNet variant for 96x96 inputs |53| DrQ encoder | `networks/encoder.py:DrQEncoder` | 4-layer conv, rescale to 84x84 |54| Multi-view fusion (BC) | `bc/multiview_encoder.py:MultiViewEncoder` | Per-camera ResNet + compress + cat/add/mult fusion |55| Spatial embedding (critic) | `rl/critic.py:SpatialEmbQNet` | Learned weighted sum over patch features fused with action |56| Spatial embedding (actor) | `rl/actor.py:SpatialEmb` | Learned weighted sum over patch features |57| Data augmentation | `rl/q_agent.py:QAgent.aug` | `RandomShiftsAug(pad=4)` — random shift crop |58| Replay buffer | `rl/replay.py:ReplayBuffer` | C++ `rela.SingleStepTransitionReplay` (pybind11), n-step returns |59| Exploration noise schedule | `common_utils/py/ibrl_utils.py:schedule` | `linear(max, min, duration)` decay |60| TruncatedNormal distribution | `common_utils/py/ibrl_utils.py:TruncatedNormal` | Clamped Gaussian with optional action norm clipping |61| Robomimic env wrapper | `env/robosuite_wrapper.py:PixelRobosuite` | Image extraction, resize, prop/state stacking |62| Meta-World env wrapper | `env/metaworld_wrapper.py:PixelMetaWorld` | Frame stacking, obs_stack support |63| Config system | `train_rl.py:MainConfig` | pyrallis dataclass, YAML + CLI overrides |6465## Setup6667### Dependencies6869- Python 3.970- PyTorch 2.1.0 (CUDA 12.1)71- MuJoCo 2.1 (mujoco210 binary in `~/.mujoco/mujoco210`)72- mujoco-py 2.1.2.1473- Key packages: `robosuite` (git), `metaworld` (git), `pyrallis`, `h5py`, `wandb`, `einops`, `rich`7475### Installation7677```bash78# MuJoCo 2.179wget https://mujoco.org/download/mujoco210-linux-x86_64.tar.gz80mkdir -p ~/.mujoco && tar -xzf mujoco210-linux-x86_64.tar.gz -C ~/.mujoco/8182# Clone and setup83git clone --recursive https://github.com/hengyuan-hu/ibrl.git84cd ibrl85conda create -n ibrl python=3.9 && conda activate ibrl86source set_env.sh # sets PYTHONPATH, MUJOCO paths, OMP_NUM_THREADS=18788# Install packages89pip install torch==2.1.0 torchvision==0.16.0 --index-url https://download.pytorch.org/whl/cu12190pip install -r requirements.txt9192# Compile C++ replay buffer (pybind11)93cd common_utils && make && cd ..94```9596### Pre-trained Weights & Data9798Download from [Google Drive](https://drive.google.com/file/d/1F2yH84Iqv0qRPmfH8o-kSzgtfaoqMzWE/view?usp=sharing), extract to `release/`:99```100release/101├── cfgs/ # YAML configs (shipped with repo)102├── data/ # HDF5 demo datasets103│ ├── robomimic/{can,square}/processed_data96.hdf5104│ └── metaworld/{Assembly,...}/dataset.hdf5105└── model/ # Pretrained BC checkpoints106 ├── robomimic/{can,square}/model0.pt107 └── metaworld/path{Assembly,...}_*/model1.pt108```109110## Usage Scenarios111112### Train IBRL (pixel, Robomimic)113114```bash115python train_rl.py --config_path release/cfgs/robomimic_rl/can_ibrl.yaml \116 --save_dir exp/can_ibrl --use_wb 0117```118119### Train RLPD baseline120121```bash122python train_rl.py --config_path release/cfgs/robomimic_rl/can_rlpd.yaml \123 --save_dir exp/can_rlpd --use_wb 0124```125126### Train RFT baseline (two-step)127128```bash129# Step 1: Pretrain RL actor with BC loss130python train_rl.py --config_path release/cfgs/robomimic_rl/can_rft.yaml \131 --pretrain_only 1 --pretrain_num_epoch 5 --load_pretrained_agent None \132 --save_dir exp/can_pretrain --use_wb 0133134# Step 2: RL fine-tune with BC regularization135python train_rl.py --config_path release/cfgs/robomimic_rl/can_rft.yaml \136 --load_pretrained_agent exp/can_pretrain/model0.pt \137 --save_dir exp/can_rft --use_wb 0138```139140### Train on Meta-World141142```bash143python mw_main/train_rl_mw.py \144 --config_path release/cfgs/metaworld/ibrl_basic.yaml \145 --bc_policy assembly --save_dir exp/mw_ibrl --use_wb 0146```147148### Key Config Flags149150| Flag | Default | Description |151|------|---------|-------------|152| `--config_path` | (required) | YAML config file path |153| `--task_name` | `"Lift"` | Robomimic task: Lift, PickPlaceCan, NutAssemblySquare, TwoArmTransport, ToolHang |154| `--bc_policy` | `""` | Path to pretrained BC model (or task name for Meta-World) |155| `--q_agent.act_method` | `"rl"` | Action selection: `"rl"`, `"ibrl"`, `"ibrl_soft"` |156| `--q_agent.bootstrap_method` | same as act_method | Bootstrap action selection (can differ from act_method) |157| `--q_agent.enc_type` | `"vit"` | Encoder: `"vit"`, `"resnet"`, `"resnet96"`, `"drq"` |158| `--use_state` | `0` | 1 = state-based (no images), 0 = pixel-based |159| `--mix_rl_rate` | `1.0` | Fraction of RL data in batch; 0.5 = RLPD-style demo mixing |160| `--add_bc_loss` | `0` | 1 = add BC regularization to actor loss (RFT) |161| `--num_train_step` | `200000` | Total environment steps |162| `--replay_buffer_size` | `500` | Max episodes in replay buffer |163| `--preload_num_data` | `0` | Number of demo episodes to preload |164| `--stddev_max/min/step` | `1.0/0.1/500000` | Exploration noise linear schedule |165| `--num_warm_up_episode` | `50` | BC-guided warm-up episodes |166| `--save_dir` | `"exps/rl/run1"` | Output directory for logs, configs, model checkpoints |167| `--use_wb` | `0` | 1 = log to Weights & Biases |168| `--mp_eval` | `0` | 1 = parallel evaluation (10 processes) |169170## Code Integration Guide171172### Minimal Imports173174```python175import sys176sys.path.append("/path/to/ibrl")177178from rl.q_agent import QAgent, QAgentConfig179from bc.bc_policy import BcPolicy, BcPolicyConfig180from networks.encoder import VitEncoder, VitEncoderConfig181```182183### Model Instantiation & Inference184185```python186import torch187from rl.q_agent import QAgent, QAgentConfig188189# Create QAgent for pixel-based task190cfg = QAgentConfig()191cfg.act_method = "ibrl" # or "rl", "ibrl_soft"192cfg.enc_type = "vit"193cfg.use_prop = 1194cfg.vit.embed_style = "embed2"195cfg.vit.depth = 1196cfg.actor.dropout = 0.5197cfg.critic.spatial_emb = 1024198199agent = QAgent(200 use_state=False,201 obs_shape=(3, 96, 96), # (C*obs_stack, H, W)202 prop_shape=(27,), # prop_dim * prop_stack (9 * 3)203 action_dim=7, # OSC_POSE: 6 EE + 1 gripper204 rl_camera="robot0_eye_in_hand",205 cfg=cfg,206)207208# Load trained weights209agent.load_state_dict(torch.load("model0.pt"))210agent.eval()211212# Inference: obs is dict with camera images and proprioception213# Images: uint8 [C, H, W], will be normalized internally (/255 - 0.5)214# Prop: float32 [prop_dim]215obs = {216 "robot0_eye_in_hand": torch.randint(0, 255, (3, 96, 96)).cuda(),217 "prop": torch.randn(27).cuda(),218}219with torch.no_grad():220 action = agent.act(obs, eval_mode=True) # returns [7] tensor on CPU221```222223### Loading a Full Trained Model224225```python226import train_rl227228agent, eval_env, eval_env_params = train_rl.load_model("path/to/model0.pt", "cuda")229# agent: QAgent with BC policy attached (if bc_policy was set in config)230# eval_env: PixelRobosuite ready for evaluation231```232233### Data Format234235| Field | Shape / Type | Description |236|-------|-------------|-------------|237| Camera obs | `(C, H, W)` uint8 | Per-camera image, C=3*obs_stack, H=W=96 (rl_image_size) |238| `prop` | `(prop_dim,)` float32 | EE pos(3) + quat(4) + gripper(2) = 9, stacked prop_stack times |239| `state` | `(state_dim,)` float32 | Full state (e.g. 19 for Lift), stacked state_stack times |240| `action` | `(action_dim,)` float32 | OSC_POSE: 6D EE delta + 1 gripper, range [-1, 1] |241| HDF5 dataset | `data/demo_N/obs/{camera}_image`, `actions`, `rewards` | Robomimic format |242243### Integration Notes244245- The repo must be on `PYTHONPATH` due to absolute imports (`import common_utils`, `from rl.q_agent import ...`)246- `common_utils` has a C++ pybind11 module (`rela`) that must be compiled with `make` before use247- The `QAgent` owns separate optimizers internally; for custom training loops, access `agent.encoder_opt`, `agent.critic_opt`, `agent.actor_opt`248- BC policies are stored in `agent.bc_policies` list and must be added via `agent.add_bc_policy()`249- Image observations must have pixel values > 5 (raw uint8 range); normalization is done inside the encoder250- `source set_env.sh` is critical: it sets `PYTHONPATH`, MuJoCo paths, and `OMP_NUM_THREADS=1` (needed for parallel eval)251252## Core Architecture253254```255IBRL Training Loop256==================257258Demonstrations (HDF5)259 |260 v261BC Policy Training (train_bc.py)262 |263 +-- BcPolicy: MultiViewEncoder(per-cam ResNet + compress + cat) -> MLP -> tanh264 | or265 +-- StateBcPolicy: MLP(dropout=0.5) -> tanh266 |267 v268RL Training (train_rl.py)269 |270 +-- QAgent (rl/q_agent.py)271 | |272 | +-- Encoder: VitEncoder / ResNetEncoder / DrQEncoder273 | | - Input: [B, C, 96, 96] uint8 -> /255 - 0.5274 | | - Output: [B, num_patch, patch_dim]275 | |276 | +-- Actor: feat -> compress(Linear+LN+ReLU or SpatialEmb) -> MLP -> TruncatedNormal277 | | - dropout=0.5 on RL actor helps prevent overfitting278 | |279 | +-- Critic: dual-Q, feat+action -> _QNet or SpatialEmbQNet -> scalar280 | | - Target: min(Q1_target, Q2_target)281 | |282 | +-- IBRL Selection (act + bootstrap):283 | a_rl = Actor(s), a_bc = BCPolicy(s)284 | a* = argmax_{a in {a_rl, a_bc}} Q_target(s, a) [hard]285 | or: sample from softmax(Q * beta) [soft]286 |287 +-- Replay Buffer (C++ pybind11)288 | - N-step returns (default n=3)289 | - Separate BC replay for demo mixing (RLPD: mix_rl_rate=0.5)290 |291 +-- Data Augmentation: RandomShiftsAug(pad=4)292293State-based variant:294 Actor = FcActor(MLP, dropout=0.5)295 Critic = MultiFcQ(10 Q-nets via _MultiLinear, RED-Q: sample k=2 for min)296```297298## Repo Structure299300| Path | Purpose |301|------|---------|302| `train_rl.py` | Main RL training entry point: `MainConfig`, `Workspace`, training loop |303| `train_bc.py` | BC pretraining entry point: `MainConfig`, training loop, `load_model()` |304| `bc/bc_policy.py` | `BcPolicy` (pixel, MultiViewEncoder+MLP), `StateBcPolicy` (state, MLP) |305| `bc/multiview_encoder.py` | `MultiViewEncoder`: per-camera ResNet encoders with fusion (cat/add/mult) |306| `bc/dataset.py` | `RobomimicDataset`: HDF5 loading, `DatasetConfig`, `sample_bc()` |307| `rl/q_agent.py` | `QAgent`: core IBRL logic, `_act_ibrl`, `_act_ibrl_soft`, `update_critic`, `update_actor`, `update_actor_rft` |308| `rl/actor.py` | `Actor` (pixel, with `SpatialEmb`), `FcActor` (state) |309| `rl/critic.py` | `Critic` (dual-Q with `_QNet`/`SpatialEmbQNet`), `MultiFcQ` (multi-Q via `_MultiLinear`) |310| `rl/replay.py` | `ReplayBuffer`: wraps C++ `rela.SingleStepTransitionReplay`, BC replay, `add_demos_to_replay()` |311| `networks/encoder.py` | `VitEncoder`, `ResNetEncoder`, `ResNet96Encoder`, `DrQEncoder` |312| `networks/min_vit.py` | `MinVit`: minimal ViT implementation |313| `networks/resnet.py` | Custom `ResNet` with configurable stem/downsample |314| `networks/resnet_rl.py` | `ResNet96` for 96x96 inputs |315| `env/robosuite_wrapper.py` | `PixelRobosuite`: robosuite env with image extraction, resize, obs stacking |316| `env/metaworld_wrapper.py` | `PixelMetaWorld`: Meta-World env wrapper |317| `mw_main/train_rl_mw.py` | Meta-World RL training (IBRL/RLPD/RFT), `BC_POLICIES` and `BC_DATASETS` dicts |318| `mw_main/train_bc_mw.py` | Meta-World BC training |319| `mw_main/mw_replay.py` | Meta-World replay buffer |320| `evaluate/eval.py` | Single-process evaluation: `run_eval()` |321| `evaluate/multi_process_eval.py` | Multi-process evaluation: `run_eval_mp()` |322| `common_utils/py/ibrl_utils.py` | `TruncatedNormal`, `eval_mode`, `soft_update_params`, `schedule()`, `orth_weight_init` |323| `common_utils/py/data_aug.py` | `RandomShiftsAug` |324| `common_utils/` | C++ pybind11 replay buffer (`rela` module), logging, saving utilities |325| `release/cfgs/` | YAML configs for all methods: `robomimic_rl/`, `robomimic_bc/`, `metaworld/` |326| `set_env.sh` | Environment setup: PYTHONPATH, MuJoCo paths, `OMP_NUM_THREADS=1` |327328## Three Training Paradigms329330| Method | Mechanism | Key Config |331|--------|-----------|------------|332| **IBRL** | Q-based selection between RL & BC actions for both exploration and bootstrapping | `act_method: "ibrl"`, `bc_policy: path/to/model.pt` |333| **RLPD** | Mix demonstration data into replay buffer (50/50 by default) | `act_method: "rl"`, `mix_rl_rate: 0.5`, `preload_num_data: N` |334| **RFT** | Pretrain RL actor with BC loss, then fine-tune with BC regularization | `act_method: "rl"`, `add_bc_loss: 1`, `bc_loss_coef: 0.1`, `load_pretrained_agent: path` |335336## Tips & Gotchas337338- **C++ compilation required**: `cd common_utils && make` is mandatory; requires cmake, gcc, and pybind11 (included as submodule). If you see `GLIBCXX_3.4.30 not found`, symlink system libstdc++ into conda env339- **`source set_env.sh`**: must run once per shell; sets `PYTHONPATH=$PWD`, MuJoCo paths, and `OMP_NUM_THREADS=1` (critical for parallel eval performance)340- **MuJoCo 2.1 specifically**: the repo uses `mujoco-py` which requires the old MuJoCo 2.1 binary (not the newer `mujoco` pip package alone)341- **GPU memory**: pixel-based ViT training uses ~16GB VRAM; ResNet/DrQ encoders use less342- **Warm-up phase**: the first 50 episodes use BC policy actions to fill the replay buffer; ensure `bc_policy` path is valid343- **Actor dropout**: 0.5 dropout on the RL actor is important for IBRL; it prevents overfitting to demonstration-heavy early data. During critic target computation, `actor_target.training` is asserted `True` (dropout active)344- **`assert False` at end**: both `train_rl.py` and `train_bc.py` deliberately crash at the end (`assert False`) to signal completion; this is intentional345- **Image normalization**: encoders expect raw pixel values (>5), normalization `/255 - 0.5` happens inside the encoder forward pass346- **Evaluation parallelism**: `--mp_eval 1` spawns 10 processes; requires `OMP_NUM_THREADS=1` to avoid thread contention347- **Config system**: pyrallis supports YAML file + CLI overrides; nested fields use dots: `--q_agent.actor.dropout 0.3`348- **Action space**: Robomimic uses OSC_POSE (6D end-effector delta + 1 gripper), actions clamped to [-1, 1] via `Tanh` output349- **HDF5 data format**: demos stored as `data/demo_N/obs/{camera}_image`, `data/demo_N/actions`, `data/demo_N/rewards`350- **Meta-World task names**: use short names (`assembly`, `boxclose`, `coffeepush`, `stickpull`) which map to `BC_POLICIES` and `BC_DATASETS` dicts in `mw_main/train_rl_mw.py`351- **`update_freq: 2`**: RL update happens every 2 env steps; critic updates `num_critic_update` times, actor updates only on the last critic iteration (RED-Q style)