diff --git a/docs/source/contrib.zuko.rst b/docs/source/contrib.zuko.rst
new file mode 100644
index 0000000000..c7f2dbe7e1
--- /dev/null
+++ b/docs/source/contrib.zuko.rst
@@ -0,0 +1,5 @@
+Zuko in Pyro
+============
+
+.. automodule:: pyro.contrib.zuko
+ :members:
diff --git a/docs/source/index.rst b/docs/source/index.rst
index 82b70e684f..a5104fb9bc 100644
--- a/docs/source/index.rst
+++ b/docs/source/index.rst
@@ -45,6 +45,7 @@ Pyro Documentation
contrib.randomvariable
contrib.timeseries
contrib.tracking
+ contrib.zuko
Indices and tables
diff --git a/pyro/contrib/zuko.py b/pyro/contrib/zuko.py
new file mode 100644
index 0000000000..232b773389
--- /dev/null
+++ b/pyro/contrib/zuko.py
@@ -0,0 +1,81 @@
+# Copyright Contributors to the Pyro project.
+# SPDX-License-Identifier: Apache-2.0
+
+"""
+This file contains helpers to use `Zuko `_-based
+normalizing flows within Pyro piplines.
+
+Accompanying tutorials can be found at `tutorial/svi_flow_guide.ipynb` and
+`tutorial/vae_flow_prior.ipynb`.
+"""
+
+import torch
+from torch import Size, Tensor
+
+import pyro
+
+
+class ZukoToPyro(pyro.distributions.TorchDistribution):
+ r"""Wraps a Zuko distribution as a Pyro distribution.
+
+ If ``dist`` has an ``rsample_and_log_prob`` method, like Zuko's flows, it will be
+ used when sampling instead of ``rsample``. The returned log density will be cached
+ for later scoring.
+
+ :param dist: A distribution instance.
+ :type dist: torch.distributions.Distribution
+
+ .. code-block:: python
+
+ flow = zuko.flows.MAF(features=5)
+
+ # flow() is a torch.distributions.Distribution
+
+ dist = flow()
+ x = dist.sample((2, 3))
+ log_p = dist.log_prob(x)
+
+ # ZukoToPyro(flow()) is a pyro.distributions.Distribution
+
+ dist = ZukoToPyro(flow())
+ x = dist((2, 3))
+ log_p = dist.log_prob(x)
+
+ with pyro.plate("data", 42):
+ z = pyro.sample("z", dist)
+ """
+
+ def __init__(self, dist: torch.distributions.Distribution):
+ self.dist = dist
+ self.cache = {}
+
+ @property
+ def has_rsample(self) -> bool:
+ return self.dist.has_rsample
+
+ @property
+ def event_shape(self) -> Size:
+ return self.dist.event_shape
+
+ @property
+ def batch_shape(self) -> Size:
+ return self.dist.batch_shape
+
+ def __call__(self, shape: Size = ()) -> Tensor:
+ if hasattr(self.dist, "rsample_and_log_prob"): # fast sampling + scoring
+ x, self.cache[x] = self.dist.rsample_and_log_prob(shape)
+ elif self.has_rsample:
+ x = self.dist.rsample(shape)
+ else:
+ x = self.dist.sample(shape)
+
+ return x
+
+ def log_prob(self, x: Tensor) -> Tensor:
+ if x in self.cache:
+ return self.cache[x]
+ else:
+ return self.dist.log_prob(x)
+
+ def expand(self, *args, **kwargs):
+ return ZukoToPyro(self.dist.expand(*args, **kwargs))
diff --git a/tests/contrib/test_zuko.py b/tests/contrib/test_zuko.py
new file mode 100644
index 0000000000..cee04c177b
--- /dev/null
+++ b/tests/contrib/test_zuko.py
@@ -0,0 +1,65 @@
+# Copyright Contributors to the Pyro project.
+# SPDX-License-Identifier: Apache-2.0
+
+
+import pytest
+import torch
+
+import pyro
+from pyro.contrib.zuko import ZukoToPyro
+from pyro.infer import SVI, Trace_ELBO
+from pyro.optim import Adam
+
+
+@pytest.mark.parametrize("multivariate", [True, False])
+@pytest.mark.parametrize("rsample_and_log_prob", [True, False])
+def test_ZukoToPyro(multivariate: bool, rsample_and_log_prob: bool):
+ # Distribution
+ if multivariate:
+ normal = torch.distributions.MultivariateNormal
+ mu = torch.zeros(3)
+ sigma = torch.eye(3)
+ else:
+ normal = torch.distributions.Normal
+ mu = torch.zeros(())
+ sigma = torch.ones(())
+
+ dist = normal(mu, sigma)
+
+ if rsample_and_log_prob:
+
+ def dummy(self, shape):
+ x = self.rsample(shape)
+ return x, self.log_prob(x)
+
+ dist.rsample_and_log_prob = dummy.__get__(dist)
+
+ # Sample
+ x1 = pyro.sample("x1", ZukoToPyro(dist))
+
+ assert x1.shape == dist.event_shape
+
+ # Sample within plate
+ with pyro.plate("data", 4):
+ x2 = pyro.sample("x2", ZukoToPyro(dist))
+
+ assert x2.shape == (4, *dist.event_shape)
+
+ # SVI
+ def model():
+ pyro.sample("a", ZukoToPyro(dist))
+
+ with pyro.plate("data", 4):
+ pyro.sample("b", ZukoToPyro(dist))
+
+ def guide():
+ mu_ = pyro.param("mu", mu)
+ sigma_ = pyro.param("sigma", sigma)
+
+ pyro.sample("a", ZukoToPyro(normal(mu_, sigma_)))
+
+ with pyro.plate("data", 4):
+ pyro.sample("b", ZukoToPyro(normal(mu_, sigma_)))
+
+ svi = SVI(model, guide, optim=Adam({"lr": 1e-3}), loss=Trace_ELBO())
+ svi.step()
diff --git a/tutorial/source/index.rst b/tutorial/source/index.rst
index 5d4c0cc12c..442cb74878 100644
--- a/tutorial/source/index.rst
+++ b/tutorial/source/index.rst
@@ -97,6 +97,7 @@ List of Tutorials
jit
svi_horovod
svi_lightning
+ svi_flow_guide
.. toctree::
:maxdepth: 1
@@ -106,7 +107,8 @@ List of Tutorials
vae
ss-vae
cvae
- normalizing_flows_i
+ normalizing_flows_intro
+ vae_flow_prior
dmm
air
cevae
diff --git a/tutorial/source/normalizing_flows_i.ipynb b/tutorial/source/normalizing_flows_intro.ipynb
similarity index 99%
rename from tutorial/source/normalizing_flows_i.ipynb
rename to tutorial/source/normalizing_flows_intro.ipynb
index 87284ba4b4..3617edc98e 100644
--- a/tutorial/source/normalizing_flows_i.ipynb
+++ b/tutorial/source/normalizing_flows_intro.ipynb
@@ -4,10 +4,12 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "# Normalizing Flows - Introduction (Part 1)\n",
+ "# Normalizing Flows - Introduction\n",
+ "\n",
+ "This tutorial introduces Pyro's built-in normalizing flows. It is independent of most of Pyro, but users may want to read about distribution shapes in the [Tensor Shapes Tutorial](http://pyro.ai/examples/tensor_shapes.html).\n",
+ "\n",
+ "> The development of Pyro's built-in flows has stopped in favor of external libraries, such as [Zuko](https://github.com/probabilists/zuko), [nflows](https://github.com/bayesiains/nflows), [normflows](https://github.com/VincentStimper/normalizing-flows) or [FlowTorch](https://flowtorch.ai/). Some of these libraries may have interfaces that are not directly compatible with Pyro. See the [SVI with flow guide](svi_flow_guide.ipynb) and [VAE with flow prior](vae_flow_prior.ipynb) tutorials for example usages of [Zuko](https://github.com/probabilists/zuko) within Pyro.\n",
"\n",
- "This tutorial introduces Pyro's normalizing flow library. It is independent of much of Pyro, but users may want to read about distribution shapes in the [Tensor Shapes Tutorial](http://pyro.ai/examples/tensor_shapes.html).\n",
- " \n",
"## Introduction\n",
"\n",
"In standard probabilistic modeling practice, we represent our beliefs over unknown continuous quantities with simple parametric distributions like the normal, exponential, and Laplacian distributions. However, using such simple forms, which are commonly symmetric and unimodal (or have a fixed number of modes when we take a mixture of them), restricts the performance and flexibility of our methods. For instance, standard variational inference in the Variational Autoencoder uses independent univariate normal distributions to represent the variational family. The true posterior is neither independent nor normally distributed, which results in suboptimal inference and simplifies the model that is learnt. In other scenarios, we are likewise restricted by not being able to model multimodal distributions and heavy or light tails.\n",
@@ -25,8 +27,7 @@
" \n",
"Normalizing Flows are a family of methods for constructing flexible distributions. Let's first restrict our attention to representing univariate distributions. The basic idea is that a simple source of noise, for example a variable with a standard normal distribution, $X\\sim\\mathcal{N}(0,1)$, is passed through a bijective (i.e. invertible) function, $g(\\cdot)$ to produce a more complex transformed variable $Y=g(X)$.\n",
"\n",
- "For a given random variable, we typically want to perform two operations: sampling and scoring. Sampling $Y$ is trivial. First, we sample $X=x$, then calculate $y=g(x)$. Scoring $Y$, or rather, evaluating the log-density $\\log(p_Y(y))$, is more involved. How does the density of $Y$ relate to the density of $X$? We can use the substitution rule of integral calculus to answer this. Suppose we want to evaluate the expectation of some function of $X$. Then,\n",
- "\n",
+ "For a given random variable, we typically want to perform two operations: sampling and scoring. Sampling $Y$ is trivial. First, we sample $X=x$, then calculate $y=g(x)$. Scoring $Y$, or rather, evaluating the log-density $\\log p_Y(y)$, is more involved. How does the density of $Y$ relate to the density of $X$? We can use the substitution rule of integral calculus to answer this. Suppose we want to evaluate the expectation of some function of $X$. Then,\n",
"\n",
"\\begin{align}\n",
"\\mathbb{E}_{p_X(\\cdot)}\\left[f(X)\\right] &= \\int_{\\text{supp}(X)}f(x)p_X(x)dx\\\\\n",
@@ -34,29 +35,22 @@
"&= \\mathbb{E}_{p_Y(\\cdot)}\\left[f(g^{-1}(Y))\\right],\n",
"\\end{align}\n",
"\n",
- "\n",
"where $\\text{supp}(X)$ denotes the support of $X$, which in this case is $(-\\infty,\\infty)$. Crucially, we used the fact that $g$ is bijective to apply the substitution rule in going from the first to the second line. Equating the last two lines we get,\n",
"\n",
- "\n",
"\\begin{align}\n",
- "\\log(p_Y(y)) &= \\log(p_X(g^{-1}(y)))+\\log\\left(\\left|\\frac{dx}{dy}\\right|\\right)\\\\\n",
- "&= \\log(p_X(g^{-1}(y)))-\\log\\left(\\left|\\frac{dy}{dx}\\right|\\right).\n",
+ "\\log p_Y(y) & = \\log p_X(g^{-1}(y)) + \\log\\left|\\frac{dx}{dy}\\right| \\\\\n",
+ "& = \\log p_X(g^{-1}(y)) - \\log\\left|\\frac{dy}{dx}\\right|.\n",
"\\end{align}\n",
"\n",
- "\n",
"Inituitively, this equation says that the density of $Y$ is equal to the density at the corresponding point in $X$ plus a term that corrects for the warp in volume around an infinitesimally small length around $Y$ caused by the transformation.\n",
"\n",
- "If $g$ is cleverly constructed (and we will see several examples shortly), we can produce distributions that are more complex than standard normal noise and yet have easy sampling and computationally tractable scoring. Moreover, we can compose such bijective transformations to produce even more complex distributions. By an inductive argument, if we have $L$ transforms $g_{(0)}, g_{(1)},\\ldots,g_{(L-1)}$, then the log-density of the transformed variable $Y=(g_{(0)}\\circ g_{(1)}\\circ\\cdots\\circ g_{(L-1)})(X)$ is\n",
- "\n",
+ "If $g$ is cleverly constructed (and we will see several examples shortly), we can produce distributions that are more complex than standard normal noise and yet have easy sampling and computationally tractable scoring. Moreover, we can compose such bijective transformations to produce even more complex distributions. By an inductive argument, if we have a sequence of $L$ transforms $(g_1, g_2, \\ldots, g_L)$ such that $Y = g(X) = g_L \\circ \\cdots g_2 \\circ g_1(X)$, then the log-density of $Y$ is\n",
"\n",
"\\begin{align}\n",
- "\\log(p_Y(y)) &= \\log\\left(p_X\\left(\\left(g_{(L-1)}^{-1}\\circ\\cdots\\circ g_{(0)}^{-1}\\right)\\left(y\\right)\\right)\\right)+\\sum^{L-1}_{l=0}\\log\\left(\\left|\\frac{dg^{-1}_{(l)}(y_{(l)})}{dy'}\\right|\\right),\n",
- "%\\left( g^{(l)}(y^{(l)})\n",
- "%\\right).\n",
+ "\\log p_Y(y) = \\log p_X(y_0) + \\sum^{L}_{l=1} \\log \\left| \\frac{dg^{-1}_{l}(y_l)}{dy_{l}} \\right|\n",
"\\end{align}\n",
"\n",
- "\n",
- "where we've defined $y_{(0)}=x$, $y_{(L-1)}=y$ for convenience of notation.\n",
+ "where $y_{l} = y$ and $y_{l-1} = g^{-1}_l(y_{l})$.\n",
"\n",
"In a latter section, we will see how to generalize this method to multivariate $X$. The field of Normalizing Flows aims to construct such $g$ for multivariate $X$ to transform simple i.i.d. standard normal noise into complex, learnable, high-dimensional distributions. The methods have been applied to such diverse applications as image modeling, text-to-speech, unsupervised language induction, data compression, and modeling molecular structures. As probability distributions are the most fundamental component of probabilistic modeling we will likely see many more exciting state-of-the-art applications in the near future."
]
@@ -71,13 +65,11 @@
"\n",
"Let us begin by showing how to represent and manipulate a simple transformed distribution,\n",
"\n",
- "\n",
"\\begin{align}\n",
"X &\\sim \\mathcal{N}(0,1)\\\\\n",
"Y &= \\text{exp}(X).\n",
"\\end{align}\n",
"\n",
- "\n",
"You may have recognized that this is by definition, $Y\\sim\\text{LogNormal}(0,1)$.\n",
"\n",
"We begin by importing the relevant libraries:"
@@ -122,14 +114,12 @@
"source": [
"The class [ExpTransform](https://pytorch.org/docs/master/distributions.html#torch.distributions.transforms.ExpTransform) derives from [Transform](https://pytorch.org/docs/master/distributions.html#torch.distributions.transforms.Transform) and defines the forward, inverse, and log-absolute-derivative operations for this transform,\n",
"\n",
- "\n",
"\\begin{align}\n",
"g(x) &= \\text{exp(x)}\\\\\n",
"g^{-1}(y) &= \\log(y)\\\\\n",
- "\\log\\left(\\left|\\frac{dg}{dx}\\right|\\right) &= x.\n",
+ "\\log \\left|\\frac{dg}{dx}\\right| &= x.\n",
"\\end{align}\n",
"\n",
- "\n",
"In general, a transform class defines these three operations, from which it is sufficient to perform sampling and scoring.\n",
"\n",
"The class [TransformedDistribution](https://pytorch.org/docs/master/distributions.html#torch.distributions.transformed_distribution.TransformedDistribution) takes a base distribution of simple noise and a list of transforms, and encapsulates the distribution formed by applying these transformations in sequence. We use it as:"
@@ -183,13 +173,11 @@
"source": [
"Our example uses a single transform. However, we can compose transforms to produce more expressive distributions. For instance, if we apply an affine transformation we can produce the general log-normal distribution,\n",
"\n",
- "\n",
"\\begin{align}\n",
"X &\\sim \\mathcal{N}(0,1)\\\\\n",
"Y &= \\text{exp}(\\mu+\\sigma X).\n",
"\\end{align}\n",
"\n",
- "\n",
"or rather, $Y\\sim\\text{LogNormal}(\\mu,\\sigma^2)$. In Pyro this is accomplished, e.g. for $\\mu=3, \\sigma=0.5$, as follows:"
]
},
@@ -282,13 +270,13 @@
"plt.show()\n",
"\n",
"plt.subplot(1, 2, 1)\n",
- "sns.distplot(X[:,0], hist=False, kde=True, \n",
+ "sns.distplot(X[:,0], hist=False, kde=True,\n",
" bins=None,\n",
" hist_kws={'edgecolor':'black'},\n",
" kde_kws={'linewidth': 2})\n",
"plt.title(r'$p(x_1)$')\n",
"plt.subplot(1, 2, 2)\n",
- "sns.distplot(X[:,1], hist=False, kde=True, \n",
+ "sns.distplot(X[:,1], hist=False, kde=True,\n",
" bins=None,\n",
" hist_kws={'edgecolor':'black'},\n",
" kde_kws={'linewidth': 2})\n",
@@ -356,7 +344,7 @@
" loss.backward()\n",
" optimizer.step()\n",
" flow_dist.clear_cache()\n",
- " \n",
+ "\n",
" if step % 200 == 0:\n",
" print('step: {}, loss: {}'.format(step, loss.item()))"
]
@@ -407,24 +395,24 @@
"plt.show()\n",
"\n",
"plt.subplot(1, 2, 1)\n",
- "sns.distplot(X[:,0], hist=False, kde=True, \n",
+ "sns.distplot(X[:,0], hist=False, kde=True,\n",
" bins=None,\n",
" hist_kws={'edgecolor':'black'},\n",
" kde_kws={'linewidth': 2},\n",
" label='data')\n",
- "sns.distplot(X_flow[:,0], hist=False, kde=True, \n",
+ "sns.distplot(X_flow[:,0], hist=False, kde=True,\n",
" bins=None, color='firebrick',\n",
" hist_kws={'edgecolor':'black'},\n",
" kde_kws={'linewidth': 2},\n",
" label='flow')\n",
"plt.title(r'$p(x_1)$')\n",
"plt.subplot(1, 2, 2)\n",
- "sns.distplot(X[:,1], hist=False, kde=True, \n",
+ "sns.distplot(X[:,1], hist=False, kde=True,\n",
" bins=None,\n",
" hist_kws={'edgecolor':'black'},\n",
" kde_kws={'linewidth': 2},\n",
" label='data')\n",
- "sns.distplot(X_flow[:,1], hist=False, kde=True, \n",
+ "sns.distplot(X_flow[:,1], hist=False, kde=True,\n",
" bins=None, color='firebrick',\n",
" hist_kws={'edgecolor':'black'},\n",
" kde_kws={'linewidth': 2},\n",
@@ -452,36 +440,30 @@
"\n",
"Sampling $Y$ is again trivial and involves evaluation of the forward pass of $g$. We can score $Y$ using the multivariate substitution rule of integral calculus,\n",
"\n",
- "\n",
"\\begin{align}\n",
"\\mathbb{E}_{p_X(\\cdot)}\\left[f(X)\\right] &= \\int_{\\text{supp}(X)}f(\\mathbf{x})p_X(\\mathbf{x})d\\mathbf{x}\\\\\n",
- "&= \\int_{\\text{supp}(Y)}f(g^{-1}(\\mathbf{y}))p_X(g^{-1}(\\mathbf{y}))\\det\\left|\\frac{d\\mathbf{x}}{d\\mathbf{y}}\\right|d\\mathbf{y}\\\\\n",
+ "&= \\int_{\\text{supp}(Y)}f(g^{-1}(\\mathbf{y}))p_X(g^{-1}(\\mathbf{y}))\\left|\\det\\frac{d\\mathbf{x}}{d\\mathbf{y}}\\right|d\\mathbf{y}\\\\\n",
"&= \\mathbb{E}_{p_Y(\\cdot)}\\left[f(g^{-1}(Y))\\right],\n",
"\\end{align}\n",
"\n",
- "\n",
- "where $d\\mathbf{x}/d\\mathbf{y}$ denotes the Jacobian matrix of $g^{-1}(\\mathbf{y})$. Equating the last two lines we get,\n",
- "\n",
+ "where $\\det \\frac{d\\mathbf{x}}{d\\mathbf{y}}$ denotes the determinant of the Jacobian matrix of $g^{-1}(\\mathbf{y})$. Equating the last two lines we get,\n",
"\n",
"\\begin{align}\n",
- "\\log(p_Y(y)) &= \\log(p_X(g^{-1}(y)))+\\log\\left(\\det\\left|\\frac{d\\mathbf{x}}{d\\mathbf{y}}\\right|\\right)\\\\\n",
- "&= \\log(p_X(g^{-1}(y)))-\\log\\left(\\det\\left|\\frac{d\\mathbf{y}}{d\\mathbf{x}}\\right|\\right).\n",
+ "\\log p_Y(y) &= \\log p_X(g^{-1}(y)) + \\log\\left|\\det\\frac{d\\mathbf{x}}{d\\mathbf{y}}\\right|\\\\\n",
+ "&= \\log p_X(g^{-1}(y)) - \\log\\left|\\det\\frac{d\\mathbf{y}}{d\\mathbf{x}}\\right|.\n",
"\\end{align}\n",
"\n",
"Inituitively, this equation says that the density of $Y$ is equal to the density at the corresponding point in $X$ plus a term that corrects for the warp in volume around an infinitesimally small volume around $Y$ caused by the transformation. For instance, in $2$-dimensions, the geometric interpretation of the absolute value of the determinant of a Jacobian is that it represents the area of a parallelogram with edges defined by the columns of the Jacobian. In $n$-dimensions, the geometric interpretation of the absolute value of the determinant Jacobian is that is represents the hyper-volume of a parallelepiped with $n$ edges defined by the columns of the Jacobian (see a calculus reference such as \\[7\\] for more details).\n",
"\n",
- "Similar to the univariate case, we can compose such bijective transformations to produce even more complex distributions. By an inductive argument, if we have $L$ transforms $g_{(0)}, g_{(1)},\\ldots,g_{(L-1)}$, then the log-density of the transformed variable $Y=(g_{(0)}\\circ g_{(1)}\\circ\\cdots\\circ g_{(L-1)})(X)$ is\n",
- "\n",
+ "Similar to the univariate case, we can compose such bijective transformations to produce even more complex distributions. By an inductive argument, if we have a sequence of $L$ transforms $(g_1, g_2, \\ldots, g_L)$ such that $Y = g(X) = g_L \\circ \\cdots g_2 \\circ g_1(X)$, then the log-density of $Y$ is\n",
"\n",
"\\begin{align}\n",
- "\\log(p_Y(y)) &= \\log\\left(p_X\\left(\\left(g_{(L-1)}^{-1}\\circ\\cdots\\circ g_{(0)}^{-1}\\right)\\left(y\\right)\\right)\\right)+\\sum^{L-1}_{l=0}\\log\\left(\\left|\\frac{dg^{-1}_{(l)}(y_{(l)})}{dy'}\\right|\\right),\n",
- "%\\left( g^{(l)}(y^{(l)})\n",
- "%\\right).\n",
+ "\\log p_Y(y) = \\log p_X(y_0) + \\sum^{L}_{l=1} \\log \\left| \\det \\frac{dg^{-1}_{l}(y_l)}{dy_{l}} \\right|\n",
"\\end{align}\n",
"\n",
- "where we've defined $y_{(0)}=x$, $y_{(L-1)}=y$ for convenience of notation.\n",
+ "where $y_{l} = y$ and $y_{l-1} = g^{-1}_l(y_{l})$.\n",
"\n",
- "The main challenge is in designing parametrizable multivariate bijections that have closed form expressions for both $g$ and $g^{-1}$, a tractable Jacobian whose calculation scales with $O(D)$ rather than $O(D^3)$, and can express a flexible class of functions."
+ "The main challenge is in designing parametrizable multivariate bijections that have closed form expressions for both $g$ and $g^{-1}$, a tractable Jacobian determinant whose calculation scales with $O(D)$ rather than $O(D^3)$, and can express a flexible class of functions."
]
},
{
@@ -571,7 +553,7 @@
" loss.backward()\n",
" optimizer.step()\n",
" flow_dist.clear_cache()\n",
- " \n",
+ "\n",
" if step % 500 == 0:\n",
" print('step: {}, loss: {}'.format(step, loss.item()))"
]
@@ -613,24 +595,24 @@
"plt.show()\n",
"\n",
"plt.subplot(1, 2, 1)\n",
- "sns.distplot(X[:,0], hist=False, kde=True, \n",
+ "sns.distplot(X[:,0], hist=False, kde=True,\n",
" bins=None,\n",
" hist_kws={'edgecolor':'black'},\n",
" kde_kws={'linewidth': 2},\n",
" label='data')\n",
- "sns.distplot(X_flow[:,0], hist=False, kde=True, \n",
+ "sns.distplot(X_flow[:,0], hist=False, kde=True,\n",
" bins=None, color='firebrick',\n",
" hist_kws={'edgecolor':'black'},\n",
" kde_kws={'linewidth': 2},\n",
" label='flow')\n",
"plt.title(r'$p(x_1)$')\n",
"plt.subplot(1, 2, 2)\n",
- "sns.distplot(X[:,1], hist=False, kde=True, \n",
+ "sns.distplot(X[:,1], hist=False, kde=True,\n",
" bins=None,\n",
" hist_kws={'edgecolor':'black'},\n",
" kde_kws={'linewidth': 2},\n",
" label='data')\n",
- "sns.distplot(X_flow[:,1], hist=False, kde=True, \n",
+ "sns.distplot(X_flow[:,1], hist=False, kde=True,\n",
" bins=None, color='firebrick',\n",
" hist_kws={'edgecolor':'black'},\n",
" kde_kws={'linewidth': 2},\n",
@@ -799,7 +781,7 @@
" optimizer.step()\n",
" dist_x1.clear_cache()\n",
" dist_x2_given_x1.clear_cache()\n",
- " \n",
+ "\n",
" if step % 500 == 0:\n",
" print('step: {}, loss: {}'.format(step, loss.item()))"
]
@@ -845,24 +827,24 @@
"plt.show()\n",
"\n",
"plt.subplot(1, 2, 1)\n",
- "sns.distplot(X[:,0], hist=False, kde=True, \n",
+ "sns.distplot(X[:,0], hist=False, kde=True,\n",
" bins=None,\n",
" hist_kws={'edgecolor':'black'},\n",
" kde_kws={'linewidth': 2},\n",
" label='data')\n",
- "sns.distplot(X_flow[:,0], hist=False, kde=True, \n",
+ "sns.distplot(X_flow[:,0], hist=False, kde=True,\n",
" bins=None, color='firebrick',\n",
" hist_kws={'edgecolor':'black'},\n",
" kde_kws={'linewidth': 2},\n",
" label='flow')\n",
"plt.title(r'$p(x_1)$')\n",
"plt.subplot(1, 2, 2)\n",
- "sns.distplot(X[:,1], hist=False, kde=True, \n",
+ "sns.distplot(X[:,1], hist=False, kde=True,\n",
" bins=None,\n",
" hist_kws={'edgecolor':'black'},\n",
" kde_kws={'linewidth': 2},\n",
" label='data')\n",
- "sns.distplot(X_flow[:,1], hist=False, kde=True, \n",
+ "sns.distplot(X_flow[:,1], hist=False, kde=True,\n",
" bins=None, color='firebrick',\n",
" hist_kws={'edgecolor':'black'},\n",
" kde_kws={'linewidth': 2},\n",
@@ -897,13 +879,6 @@
"9. Laurent Dinh, Jascha Sohl-Dickstein, Samy Bengio. [*Density estimation using Real-NVP*](https://arxiv.org/abs/1605.08803). Conference paper at ICLR 2017.\n",
"10. David Ha, Andrew Dai, Quoc V. Le. [*HyperNetworks*](https://arxiv.org/abs/1609.09106). Workshop contribution at ICLR 2017."
]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": []
}
],
"metadata": {
diff --git a/tutorial/source/svi_flow_guide.ipynb b/tutorial/source/svi_flow_guide.ipynb
new file mode 100644
index 0000000000..4b0fe1c89d
--- /dev/null
+++ b/tutorial/source/svi_flow_guide.ipynb
@@ -0,0 +1,238 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# SVI with a Normalizing Flow guide\n",
+ "\n",
+ "Thanks to their expressiveness, normalizing flows (see [normalizing flow introduction](normalizing_flows_intro.ipynb)) are great guide candidates for stochastic variational inference (SVI). This notebook demonstrates how to perform amortized SVI with a normalizing flow as guide.\n",
+ "\n",
+ "> In this notebook we use [Zuko](https://zuko.readthedocs.io/) to implement normalizing flows, but similar results can be obtained with other PyTorch-based flow libraries."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pyro\n",
+ "import torch\n",
+ "import zuko # pip install zuko\n",
+ "\n",
+ "from corner import corner, overplot_points # pip install corner\n",
+ "from pyro.contrib.zuko import ZukoToPyro\n",
+ "from pyro.optim import ClippedAdam\n",
+ "from pyro.infer import SVI, Trace_ELBO\n",
+ "from torch import Tensor"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Model\n",
+ "\n",
+ "We define a simple non-linear model $p(x | z)$ with a standard Gaussian prior $p(z)$ over the latent variables $z$."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "prior = pyro.distributions.Normal(torch.zeros(3), torch.ones(3)).to_event(1)\n",
+ "\n",
+ "def likelihood(z: Tensor):\n",
+ " mu = z[..., :2]\n",
+ " rho = z[..., 2].tanh() * 0.99\n",
+ "\n",
+ " cov = 1e-2 * torch.stack([\n",
+ " torch.ones_like(rho), rho,\n",
+ " rho, torch.ones_like(rho),\n",
+ " ], dim=-1).unflatten(-1, (2, 2))\n",
+ "\n",
+ " return pyro.distributions.MultivariateNormal(mu, cov)\n",
+ "\n",
+ "def model(x: Tensor):\n",
+ " with pyro.plate(\"data\", x.shape[1]):\n",
+ " z = pyro.sample(\"z\", prior)\n",
+ "\n",
+ " with pyro.plate(\"obs\", 5):\n",
+ " pyro.sample(\"x\", likelihood(z), obs=x)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We sample 64 reference latent variables and observations $(z^*, x^*)$. In practice, $z^*$ is unknown, and $x^*$ is your data."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "z_star = prior.sample((64,))\n",
+ "x_star = likelihood(z_star).sample((5,))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Guide\n",
+ "\n",
+ "We define the guide $q_\\phi(z | x)$ with a normalizing flow. We choose a conditional [neural spline flow](https://arxiv.org/abs/1906.04032) borrowed from the [Zuko](https://zuko.readthedocs.io/) library. Because Zuko distributions are very similar to Pyro distributions, a thin wrapper (`ZukoToPyro`) is sufficient to make Zuko and Pyro 100% compatible."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "flow = zuko.flows.NSF(features=3, context=10, transforms=1, hidden_features=(256, 256))\n",
+ "flow.transform = flow.transform.inv # inverse autoregressive flow (IAF) are fast to sample from\n",
+ "\n",
+ "def guide(x: Tensor):\n",
+ " pyro.module(\"flow\", flow)\n",
+ "\n",
+ " with pyro.plate(\"data\", x.shape[1]): # amortized\n",
+ " pyro.sample(\"z\", ZukoToPyro(flow(x.transpose(0, 1).flatten(-2))))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## SVI\n",
+ "\n",
+ "We train our guide with a standard stochastic variational inference (SVI) pipeline. We use 16 particles to reduce the variance of the ELBO and clip the norm of the gradients to make training more stable."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "(0) 209195.08367919922\n",
+ "(256) -25.225540161132812\n",
+ "(512) -99.09033203125\n",
+ "(768) -102.66302490234375\n",
+ "(1024) -138.8058319091797\n",
+ "(1280) -92.15625\n",
+ "(1536) -136.78167724609375\n",
+ "(1792) -87.76119995117188\n",
+ "(2048) -116.21714782714844\n",
+ "(2304) -162.0266571044922\n",
+ "(2560) -91.13175964355469\n",
+ "(2816) -164.86270141601562\n",
+ "(3072) -98.17607116699219\n",
+ "(3328) -102.58432006835938\n",
+ "(3584) -151.61912536621094\n",
+ "(3840) -77.94436645507812\n",
+ "(4096) -121.82719421386719\n"
+ ]
+ }
+ ],
+ "source": [
+ "pyro.clear_param_store()\n",
+ "\n",
+ "svi = SVI(model, guide, optim=ClippedAdam({\"lr\": 1e-3, \"clip_norm\": 10.0}), loss=Trace_ELBO(num_particles=16, vectorize_particles=True))\n",
+ "\n",
+ "for step in range(4096 + 1):\n",
+ " elbo = svi.step(x_star)\n",
+ "\n",
+ " if step % 256 == 0:\n",
+ " print(f'({step})', elbo)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Posterior predictive"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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",
+ "text/plain": [
+ "