Octo Documentation

repository·main·Indexed 23 days ago

https://github.com/octo-models/octo

A transformer-based diffusion policy for generalist robotic tasks. Octo can be trained on large-scale datasets like Open X-Embodiment (OXE) and finetuned for specific robot morphologies, sensors, and action spaces. The library supports multiple RGB camera inputs, language or goal-image instructions, and provides tools for inference, finetuning (head_only, head_mlp_only, or full), and pretraining from scratch using JAX.

Tokens
4.4K
Snippets
10
Records
20
Agent score
83%

What's inside Octo

  1. Understand observation masks: timestep_pad_mask and pad_mask_dict

    main

    When providing observations to Octo, two mask types are used to control attention:

    timestep_pad_mask

    Indicates which observations in the history window should be attended to. Octo is typically trained with a history window size of 2 (current + previous observation).

    • At the start of a trajectory: Since there is no previous observation, set timestep_pad_mask=False for the missing index.
    • Window size of 1: If using a window size of 1, timestep_pad_mask should always be [True].
    • Automation: If you use the HistoryWrapper from octo/utils/gym_wrappers.py, this mask is added to the observation dictionary automatically.

    pad_mask_dict

    Indicates which elements within a single timestep should be attended to. This is used for modalities that might be missing in a specific dataset.

    • Example (No language): pad_mask_dict["language_instruction"] = False.
    • Example (No wrist camera): pad_mask_dict["image_wrist"] = False.
    • Default behavior: If a key is missing from the pad_mask_dict, it is treated as False for that key.
  2. Understand Octo action chunking

    main

    Octo was pretrained with an action chunking size of 4, meaning model.sample_actions() predicts the next 4 actions simultaneously.

    When using these actions in an environment, you have several options:

    1. Execute all actions: Run the entire chunk of 4 actions before sampling again.
    2. Receding Horizon Control: Execute only the first action of the chunk, then sample new actions.
    3. Temporal Ensembling: A more advanced method available via the HistoryWrapper in octo/utils/gym_wrappers.py.
  3. Format Gym environment observations for Octo

    main

    To use a custom Gym environment with Octo, ensure that the step and reset functions return observation dictionaries containing the specific modalities the model expects (images, depth, and/or proprioception).

    Observations must be dictionaries where keys follow the pattern image_{key} or depth_{key}, where {key} corresponds to the observation keys specified in your model's training data loading configuration (commonly primary and/or wrist).

    If a required key is missing from the dictionary, the model will substitute it with padding.

    obs = {
        "image_primary": ..., 
        "image_wrist": ..., 
        "depth_primary": ..., 
        "depth_wrist": ..., 
        "proprio": ..., 
    }
  4. Load and use a pretrained Octo model

    main

    You can load a pretrained Octo model using OctoModel.load_pretrained(). The model supports multiple RGB camera inputs, various robot arms, and instructions via language or goal images.

    Basic Inference Example

    from octo.model.octo_model import OctoModel
    model = OctoModel.load_pretrained("hf://rail-berkeley/octo-base-1.5")
    print(model.get_pretty_spec())

    Running Actions

    To perform inference, create a task from text and sample actions using an observation:

    from octo.model import OctoModel
    import jax
    
    model = OctoModel.load_pretrained("hf://rail-berkeley/octo-small-1.5")
    task = model.create_tasks(texts=["pick up the spoon"])
    action = model.sample_actions(observation, task, rng=jax.random.PRNGKey(0))
  5. Install Octo

    main

    To install Octo, create a Conda environment with Python 3.10, install the package in editable mode, and install the required dependencies.

    GPU Installation

    If you are using a GPU, you must install the appropriate JAX version with CUDA support:

    pip install --upgrade "jax[cuda11_pip]==0.4.20" -f https://storage.googleapis.com/jax-releases/jax_cuda_releases.html

    TPU Installation

    For TPU support, install the JAX TPU version:

    pip install --upgrade "jax[tpu]==0.4.20" -f https://storage.googleapis.com/jax-releases/libtpu_releases.html

    Verify Installation

    You can verify the installation by running the finetuning script on the provided debug dataset:

    python scripts/finetune.py --config.pretrained_path=hf://rail-berkeley/octo-small-1.5 --debug
    conda create -n octo python=3.10
    conda activate octo
    pip install -e .
    pip install -r requirements.txt
  6. Finetune Octo models

    main

    Octo can be finetuned on small target domain datasets to adapt to new sensory inputs, action spaces, or morphologies.

    Finetuning Modes

    You can specify which parts of the model to freeze using one of three modes:

    • head_only: Only the readout heads are finetuned.
    • head_mlp_only: Only the head MLP is finetuned.
    • full: The entire model is finetuned.

    Task Types

    You can also specify the task type for finetuning:

    • image_conditioned
    • language_conditioned
    • multimodal

    Execution

    Use the scripts/finetune.py script. You can combine modes and task types in the config. For example, to finetune the full transformer with image inputs only:

    python scripts/finetune.py --config=finetune_config.py:full,image_conditioned

    To run advanced finetuning with a specific pretrained path:

    python scripts/finetune.py --config.pretrained_path=hf://rail-berkeley/octo-small-1.5
  7. Pretrain Octo from scratch

    main

    To reproduce Octo pretraining on the 800k robot trajectories, use the scripts/train.py script. You must provide a configuration file and specify the dataset directory and mix.

    python scripts/train.py --config scripts/configs/octo_pretrain_config.py:<size> --name=octo --config.dataset_kwargs.oxe_kwargs.data_dir=... --config.dataset_kwargs.oxe_kwargs.data_mix=oxe_magic_soup ...

    Note: The pre-processed Open X-Embodiment dataset is approximately 1.2TB. You can download it using the rlds_dataset_mod package and the prepare_open_x.sh script.

  8. Understand the structure of an Octo data batch

    main

    When using the Octo dataloader (especially with make_interleaved_dataset), the resulting batches contain several key dictionaries:

    • batch["observation"]: Contains sensor data. Keys like image_primary or image_wrist will have the shape (batch_size, window_size, height, width, channels). It also includes pad_mask_dict to indicate which modalities (like a wrist camera) are valid vs. padding (e.g., if a camera is black/missing).
    • batch["task"]: Contains task-specific information, such as image_primary (goal images) and language_instruction.
    • batch["action"]: Contains the actions, typically shaped (batch_size, window_size, action_horizon, action_dim) when using action chunking.
  9. Run inference on full trajectories

    main

    When running inference over a trajectory, you must feed inputs of the correct temporal window size.

    1. Create Task: Use model.create_tasks(goals=...) for goal-conditioned tasks or model.create_tasks(texts=...) for language-conditioned tasks.
    2. Prepare Observations: Stack a window of images to match the required WINDOW_SIZE. The observation dictionary must include image_primary and a timestep_pad_mask of the same temporal length.
    3. Unnormalize Actions: model.sample_actions returns normalized actions. You must unnormalize them using the statistics found in model.dataset_statistics["<dataset_name>">["action"] to get usable control values.
    WINDOW_SIZE = 2
    # ... load images and task ...
    
    for step in tqdm.trange(len(images) - (WINDOW_SIZE - 1)):
        # Stack images for the temporal window
        input_images = np.stack(images[step:step+WINDOW_SIZE])[None]
        
        observation = {
            'image_primary': input_images,
            'timestep_pad_mask': np.full((1, input_images.shape[1]), True, dtype=bool)
        }
    
        # Sample normalized actions
        actions = model.sample_actions(
            observation, 
            task, 
            unnormalization_statistics=model.dataset_statistics["bridge_dataset"]["action"], 
            rng=jax.random.PRNGKey(0)
        )
        actions = actions[0] # remove batch dim
  10. Load a single Open X-Embodiment (OXE) dataset

    main

    To load a single dataset from the Open X-Embodiment collection, use make_oxe_dataset_kwargs to generate configuration parameters and make_single_dataset to create the dataset object. The dataset can be sourced from local paths or cloud storage (e.g., Google Cloud Storage) supported by TFDS.

    Note that make_single_dataset yields entire trajectories. The shape of observation data (like images) typically follows (traj_len, window_size, height, width, channels), where window_size defaults to 1.

    from octo.data.oxe import make_oxe_dataset_kwargs
    from octo.data.dataset import make_single_dataset
    
    dataset_kwargs = make_oxe_dataset_kwargs(
        "austin_buds_dataset_converted_externally_to_rlds",
        "gs://gresearch/robotics",
    )
    dataset = make_single_dataset(dataset_kwargs, train=True)
    iterator = dataset.iterator()
    
    # To get a trajectory:
    traj = next(iterator)
  11. Create a mixed, training-ready OXE dataset

    main

    For realistic training, use make_interleaved_dataset to combine multiple datasets with specific weights. This method is more powerful than manual shuffling as it can handle interleaved datasets, trajectory transformations (like goal relabeling and windowing), and frame transformations (like image augmentation and resizing) in a single pipeline.

    Key configuration areas:

    • traj_transform_kwargs: Controls trajectory-level logic like goal_relabeling_strategy, window_size, action_horizon, and subsample_length.
    • frame_transform_kwargs: Controls frame-level logic like image_augment_kwargs, resize_size, and num_parallel_calls.
    • shuffle_buffer_size: Since make_interleaved_dataset shuffles JPEG-encoded images, you can often use a larger buffer than manual frame shuffling.
    from octo.data.oxe import make_oxe_dataset_kwargs_and_weights
    from octo.data.dataset import make_interleaved_dataset
    
    dataset_kwargs_list, sample_weights = make_oxe_dataset_kwargs_and_weights(
        "rtx",
        "gs://gresearch/robotics",
        load_camera_views=("primary", "wrist"),
    )
    
    dataset = make_interleaved_dataset(
        dataset_kwargs_list,
        sample_weights,
        train=True,
        shuffle_buffer_size=1000,
        batch_size=8,
        traj_transform_kwargs=dict(
            goal_relabeling_strategy="uniform",
            window_size=2,
            action_horizon=4,
            subsample_length=100,
        ),
        frame_transform_kwargs=dict(
            image_augment_kwargs=dict(
                primary=dict(
                    augment_order=["random_resized_crop", "random_brightness"],
                    random_resized_crop=dict(scale=[0.8, 1.0], ratio=[0.9, 1.1]),
                    random_brightness=[0.1],
                )
            ),
            resize_size=dict(
                primary=(256, 256),
                wrist=(128, 128),
            ),
            num_parallel_calls=64,
        ),
        traj_transform_threads=16,
        traj_read_threads=16,
    )
    
    iterator = dataset.iterator(prefetch=1)