{ "cells": [ { "cell_type": "markdown", "metadata": { "ExecuteTime": { "end_time": "2018-06-18T15:27:28.707896Z", "start_time": "2018-06-18T15:27:28.702766Z" } }, "source": [ "# Compound Steps in Sampling\n", "This notebook explains how the compound steps work in `pymc.sample` function when sampling multiple random variables. We are going to answer the following questions associated with compound steps:\n", "\n", "- How do compound steps work?\n", "- What happens when PyMC assigns step methods by default?\n", "- How to specify the step methods? What is the order to apply the step methods at each iteration? Is there a way to specify the order of the step methods? \n", "- What are the issues with mixing discrete and continuous samplers, especially with HMC/NUTS?\n", "- What happens to sample statistics that occur in multiple step methods?" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "ExecuteTime": { "end_time": "2018-07-28T21:53:54.050085Z", "start_time": "2018-07-28T21:53:52.045480Z" }, "execution": { "iopub.execute_input": "2022-01-09T19:27:05.186598Z", "iopub.status.busy": "2022-01-09T19:27:05.185597Z", "iopub.status.idle": "2022-01-09T19:27:09.141640Z", "shell.execute_reply": "2022-01-09T19:27:09.140637Z" } }, "outputs": [], "source": [ "import arviz as az\n", "import numpy as np\n", "import pymc as pm\n", "import pytensor\n", "import xarray" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "execution": { "iopub.execute_input": "2022-01-09T19:27:09.147639Z", "iopub.status.busy": "2022-01-09T19:27:09.146639Z", "iopub.status.idle": "2022-01-09T19:27:09.156640Z", "shell.execute_reply": "2022-01-09T19:27:09.156640Z" } }, "outputs": [], "source": [ "az.style.use(\"arviz-darkgrid\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Compound steps" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "When sampling a model with multiple free random variables, compound steps are needed in the `pm.sample` function. When compound steps are involved, the function takes a list of `step` to generate a list of `methods` for different random variables. For example in the following code:\n", "```python\n", "with pm.Model() as m:\n", " rv1 = ... # random variable 1 (continuous)\n", " rv2 = ... # random variable 2 (continuous)\n", " rv3 = ... # random variable 3 (categorical)\n", " #...\n", " step1 = pm.Metropolis([rv1, rv2])\n", " step2 = pm.CategoricalGibbsMetropolis([rv3])\n", " trace = pm.sample(..., step=[step1, step2])\n", "```\n", "The compound step now contains a list of `methods`. At each sampling step, it iterates over these methods, taking a `point` as input. In each step a new `point` is proposed as an output, if rejected by the Metropolis-Hastings criteria the original input `point` sticks around as the output." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Compound steps by default\n", "To conduct Markov chain Monte Carlo (MCMC) sampling to generate posterior samples in PyMC, we specify a step method object that corresponds to a particular MCMC algorithm, such as Metropolis, Slice sampling, or the No-U-Turn Sampler (NUTS). PyMC’s step_methods can be assigned manually, or assigned automatically by PyMC. Auto-assignment is based on the attributes of each variable in the model. In general:\n", "\n", "- Binary variables will be assigned to BinaryMetropolis\n", "- Discrete variables will be assigned to Metropolis\n", "- Continuous variables will be assigned to NUTS\n", "\n", "When we call `pm.sample(return_inferencedata=False)`, `PyMC` assigns the best step method to each of the free random variables. Take the following example" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "ExecuteTime": { "end_time": "2018-07-28T21:54:23.727052Z", "start_time": "2018-07-28T21:53:56.768369Z" }, "execution": { "iopub.execute_input": "2022-01-09T19:27:09.164638Z", "iopub.status.busy": "2022-01-09T19:27:09.163641Z", "iopub.status.idle": "2022-01-09T19:28:11.250420Z", "shell.execute_reply": "2022-01-09T19:28:11.248424Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "Multiprocess sampling (4 chains in 4 jobs)\n", "CompoundStep\n", ">NUTS: [p]\n", ">BinaryGibbsMetropolis: [ni]\n" ] }, { "data": { "text/html": [ "\n", "