From df262402cf31a8ad8e3d0bd0f87bb2427573c9f5 Mon Sep 17 00:00:00 2001 From: andrew-luo1 Date: Mon, 15 Apr 2024 08:12:43 +0200 Subject: [PATCH] add diagram for apg notebook --- doc/images/mjx/apg_diagram.png | Bin 0 -> 46785 bytes mjx/training_apg.ipynb | 102 +++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+) create mode 100644 doc/images/mjx/apg_diagram.png create mode 100644 mjx/training_apg.ipynb diff --git a/doc/images/mjx/apg_diagram.png b/doc/images/mjx/apg_diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..e23cfa5753ae3857d2e57360ec465548343281b0 GIT binary patch literal 46785 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 Y_g)yPN!p%kPvDQXrXDRz-O~U60Y4UXTmS$7 literal 0 HcmV?d00001 diff --git a/mjx/training_apg.ipynb b/mjx/training_apg.ipynb new file mode 100644 index 00000000..65133668 --- /dev/null +++ b/mjx/training_apg.ipynb @@ -0,0 +1,102 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Policy learning and Policy Gradients\n", + "\n", + "This is a recap of policy learning, and how it differs when one assumes a stochastic versus a deterministic model. If these concepts are unfamiliar to you, there are many great resources [online](https://spinningup.openai.com/en/latest/spinningup/rl_intro.html). This recap contextualizes how we can use MJX's differentiability for policy learning.\n", + "\n", + "The goal of policy learning is to learn a control policy $\\pi$ which outputs actions $a_t \\sim \\pi(\\cdot| x_t, \\theta)$ maximizing the total rewards $\\sum r_t$, where $r_t$ is shorthand for a reward function evaluated at the state and action of time t: $r_t = r(x_t, a_t)$. $\\theta$ are the parameters of the policy. In the common case that the policy is a neural network, $\\theta$ would be the weights. **Policy gradient methods** involve estimating the gradient of the policy with respect to the weights, and using this value in a first-order optimization algorithm such as Gradient Descent or [Adam](https://arxiv.org/abs/1412.6980).\n", + "\n", + "How you estimate the policy gradient depends on what state transition model you assume. \n", + "\n", + "#### Zeroth-Order Policy Gradients (ZoPG)\n", + "\n", + "Referring to mjx.step as the simulation function f, we borrowing some [terminology](https://arxiv.org/abs/2202.00817) to differentiate between zeroth-order gradients, which only depend on values of f, and first-order gradients, which depend on its jacobian.\n", + "\n", + "Reinforcement learning algorithms such as the standard [PPO](https://github.com/google/brax/blob/main/brax/training/agents/ppo/train.py) assume a stochastic state transition model $x_{t+1} \\sim P(\\cdot | x_t, a_t)$. This leads to a ZoPG of the form:\n", + "\n", + "$$\n", + "\\nabla_\\theta J(\\pi_\\theta) = \\mathbb{E}_{\\tau \\sim \\pi_\\theta}\\left[ \\sum \\nabla_\\theta \\log\\pi_\\theta (a_t | s_t) R(\\tau) \\right]\n", + "$$\n", + "\n", + "Despite this method's popularity and extensive research into its refinement, a fundamental shortcoming is that the gradient has high variance. This allows the optimizer to thoroughly explore the space of policies, leading to the robust and often surprisingly good policies that have been achieved. However, the variance comes at the cost of requiring many samples $(x_t, a_t)$ to converge.\n", + "\n", + "#### First-Order Policy Gradients (FoPG)\n", + "On the other hand, if you assume a deterministic state transition model $x_{t+1} = f(x_t, a_t)$, you end up with the first-order policy gradient. Unlike ZoPG methods, which models the state evolution as a probabilistic black box, the FoPG explicitly contains the jacobians of the simulation function f. For example, let's look at the gradient of $r_t$, in the case that it only depends on state.\n", + "$$\n", + "\\frac{\\partial r_t}{\\partial \\theta} = \\frac{\\partial r_t}{\\partial x_t}\\frac{\\partial x_t}{\\partial \\theta} \n", + "$$\n", + "\n", + "$$\n", + "\\frac{\\partial x_t}{\\partial \\theta} = \\textcolor{Navy}{\\frac{\\partial f(x_t, a_t)}{\\partial x_{t-1}}}\\frac{\\partial x_{t-1}}{\\partial \\theta} + \\textcolor{Navy}{\\frac{\\partial f(x_t, a_t)}{\\partial a_{t-1}}} \\frac{\\partial a_{t-1}}{\\partial \\theta}\n", + "$$\n", + "\n", + "The navy-colored terms in the above expression are enabled by MJX's differentiability and are the key difference between FoPG's and ZoPG's. An important consideration is what these jacobians look like near contact points. To see why certain gradients within the jacobian can be pathological, imagine a hard sphere falling toward a block of marble. How does its velocity change with respect to distance ($\\frac{\\partial \\dot{z}_t}{\\partial z_t}$, for $x_t$ = [$z_t, \\dot{z}_t$]), the instant before it touches the ground? This is the case of an **uninformative gradient**, due to **hard contact**. In practice however, the default contact settings in Mujoco are sufficiently soft for learning via FoPG's. Soft contacts would resolve the above scenario by modelling the ground as applying an increasing force on the ball as it penetrates it.\n", + "\n", + "A helpful way to think about FoPG's is via the chain rule, as illustrated below for how $r_2$ influences the parameter update, again for the case that the reward does not depend on action:\n", + "\"drawing\"\n", + "\n", + "Note that there three distinct gradient chains in this example. The red pathway does not use the simulator's differentiability. The blue path is the most intuitive usage of this feature, and captures how actions affect downstream rewards. The least intuitive may be the green chain, which shows how the reward depends on how actions depend on previous actions - experience shows that blocking this pathway via jax.lax.stop_grad can badly hinder policy learning. As the length of $x_t$ backbone increases, [gradient explosion](https://arxiv.org/abs/2111.05803) becomes a crucial consideration. In practice, this can be resolved via decaying downstream gradients or periodically truncating the gradient.\n", + "\n", + "**The Sharp bits of FoPG's**\n", + "\n", + "While FoPG's have been shown to be very sample efficient, especially as the [dimension of the state space increases](https://arxiv.org/abs/2204.07137), they can still struggle with wall-clock time. Because the gradients have low variance, they do not benefit significantly from massive parallelization of data collection - unlike [RL](https://arxiv.org/abs/2109.11978). Additionally, the policy gradient is typically calculated via autodifferentiation. This can be 3-5x slower than unrolling the simulation forward, and memory intensive, with memory requirements scaling with $O((m+n) \\cdot m \\cdot T)$, where m and n are the state and control dimensions and T is the number of steps propogated through.\n", + "\n", + "Due to the lower gradient variance, FoPG's also have less exploration power than ZoPG's and benefit from the practioner being more explicit in the problem formulation. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this tutorial, we hope to convey *when* to use FoPG's, and *how* to use them through three case studies:\n", + "\n", + "\n", + "| | | Case Study |\n", + "| --- | ----| --------------------------------- |\n", + "| 1 | | *Imitating Kinematics* |\n", + "| | a | 1 Hz Trot |\n", + "| | b | 3 Hz Trot |\n", + "| | c | 3 Hz Trot; PPO |\n", + "| 2 | | *Quadruped Locomotion Design* |\n", + "| | a | 0.75 m/s trot with long strides |\n", + "| | b | 1.5 m/s trot with short strides |\n", + "| | c | 0.75 m/s trot without reference |\n", + "\n", + "(TODO)\n", + "Study 1a demonstrates the sample efficiency and degree of refinement possible from a FoPG algorithm. Studies 1a, 2a and 2b show that FoPG algorithms excel when the reward is specified clearly. Study 3 shows that like for classical methods such as MPC and trajectory optimization, the learned policy benefits greatly from a good \"initial guess\"." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "mujoco", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}