We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
TransformedDistribution's event_shape forwards to incorrect base distribution's method
Probably a typo:

https://github.com/uber/pyro/blob/51a2ccfe9445c7072c3150c4abe1ab1d2ac17246/pyro/distributions/transformed_distribution.py#L62

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pyro/distributions/transformed_distribution.py`
Content:
```
1 from __future__ import absolute_import, division, print_function
2 
3 import torch
4 import torch.nn as nn
5 from torch.autograd import Variable
6 
7 from pyro.distributions.distribution import Distribution
8 from pyro.nn import AutoRegressiveNN
9 
10 
11 class TransformedDistribution(Distribution):
12     """
13     Transforms the base distribution by applying a sequence of `Bijector`s to it.
14     This results in a scorable distribution (i.e. it has a `log_pdf()` method).
15 
16     :param base_distribution: a (continuous) base distribution; samples from this distribution
17         are passed through the sequence of `Bijector`s to yield a sample from the
18         `TransformedDistribution`
19     :type base_distribution: pyro.distribution.Distribution
20     :param bijectors: either a single Bijector or a sequence of Bijectors wrapped in a nn.ModuleList
21     :returns: the transformed distribution
22     """
23 
24     def __init__(self, base_distribution, bijectors, *args, **kwargs):
25         super(TransformedDistribution, self).__init__(*args, **kwargs)
26         self.reparameterized = base_distribution.reparameterized
27         self.base_dist = base_distribution
28         if isinstance(bijectors, Bijector):
29             self.bijectors = nn.ModuleList([bijectors])
30         elif isinstance(bijectors, nn.ModuleList):
31             for bijector in bijectors:
32                 assert isinstance(bijector, Bijector), \
33                     "bijectors must be a Bijector or a nn.ModuleList of Bijectors"
34             self.bijectors = bijectors
35 
36     def sample(self, *args, **kwargs):
37         """
38         :returns: a sample y
39         :rtype: torch.autograd.Variable
40 
41         Sample from base distribution and pass through bijector(s)
42         """
43         x = self.base_dist.sample(*args, **kwargs)
44         next_input = x
45         for bijector in self.bijectors:
46             y = bijector(next_input)
47             if bijector.add_inverse_to_cache:
48                 bijector._add_intermediate_to_cache(next_input, y, 'x')
49             next_input = y
50         return next_input
51 
52     def batch_shape(self, x=None, *args, **kwargs):
53         """
54         Ref: :py:meth:`pyro.distributions.distribution.Distribution.batch_shape`
55         """
56         return self.base_dist.batch_shape(x, *args, **kwargs)
57 
58     def event_shape(self, *args, **kwargs):
59         """
60         Ref: :py:meth:`pyro.distributions.distribution.Distribution.event_shape`
61         """
62         return self.base_dist.batch_shape(*args, **kwargs)
63 
64     def log_pdf(self, y, *args, **kwargs):
65         """
66         :param y: a value sampled from the transformed distribution
67         :type y: torch.autograd.Variable
68 
69         :returns: the score (the log pdf) of y
70         :rtype: torch.autograd.Variable
71 
72         Scores the sample by inverting the bijector(s) and computing the score using the score
73         of the base distribution and the log det jacobian
74         """
75         inverses = []
76         next_to_invert = y
77         for bijector in reversed(self.bijectors):
78             inverse = bijector.inverse(next_to_invert)
79             inverses.append(inverse)
80             next_to_invert = inverse
81         log_pdf_base = self.base_dist.log_pdf(inverses[-1], *args, **kwargs)
82         log_det_jacobian = self.bijectors[-1].log_det_jacobian(y, *args, **kwargs)
83         for bijector, inverse in zip(list(reversed(self.bijectors))[1:], inverses[:-1]):
84             log_det_jacobian += bijector.log_det_jacobian(inverse, *args, **kwargs)
85         return log_pdf_base - log_det_jacobian
86 
87     def batch_log_pdf(self, y, *args, **kwargs):
88         raise NotImplementedError("https://github.com/uber/pyro/issues/293")
89 
90 
91 class Bijector(nn.Module):
92     """
93     Abstract class `Bijector`. `Bijector` are bijective transformations with computable
94     log det jacobians. They are meant for use in `TransformedDistribution`.
95     """
96 
97     def __init__(self, *args, **kwargs):
98         super(Bijector, self).__init__(*args, **kwargs)
99         self.add_inverse_to_cache = False
100 
101     def __call__(self, *args, **kwargs):
102         """
103         Virtual forward method
104 
105         Invokes the bijection x=>y
106         """
107         raise NotImplementedError()
108 
109     def inverse(self, *args, **kwargs):
110         """
111         Virtual inverse method
112 
113         Inverts the bijection y => x.
114         """
115         raise NotImplementedError()
116 
117     def log_det_jacobian(self, *args, **kwargs):
118         """
119         Virtual logdet jacobian method.
120 
121         Computes the log det jacobian `|dy/dx|`
122         """
123         raise NotImplementedError()
124 
125 
126 class InverseAutoregressiveFlow(Bijector):
127     """
128     An implementation of an Inverse Autoregressive Flow. Together with the `TransformedDistribution` this
129     provides a way to create richer variational approximations.
130 
131     Example usage::
132 
133     >>> base_dist = Normal(...)
134     >>> iaf = InverseAutoregressiveFlow(...)
135     >>> pyro.module("my_iaf", iaf)
136     >>> iaf_dist = TransformedDistribution(base_dist, iaf)
137 
138     Note that this implementation is only meant to be used in settings where the inverse of the Bijector
139     is never explicitly computed (rather the result is cached from the forward call). In the context of
140     variational inference, this means that the InverseAutoregressiveFlow should only be used in the guide,
141     i.e. in the variational distribution. In other contexts the inverse could in principle be computed but
142     this would be a (potentially) costly computation that scales with the dimension of the input (and in
143     any case support for this is not included in this implementation).
144 
145     :param input_dim: dimension of input
146     :type input_dim: int
147     :param hidden_dim: hidden dimension (number of hidden units)
148     :type hidden_dim: int
149     :param sigmoid_bias: bias on the hidden units fed into the sigmoid; default=`2.0`
150     :type sigmoid_bias: float
151     :param permutation: whether the order of the inputs should be permuted (by default the conditional
152         dependence structure of the autoregression follows the sequential order)
153     :type permutation: bool
154 
155     References:
156 
157     1. Improving Variational Inference with Inverse Autoregressive Flow [arXiv:1606.04934]
158     Diederik P. Kingma, Tim Salimans, Rafal Jozefowicz, Xi Chen, Ilya Sutskever, Max Welling
159 
160     2. Variational Inference with Normalizing Flows [arXiv:1505.05770]
161     Danilo Jimenez Rezende, Shakir Mohamed
162 
163     3. MADE: Masked Autoencoder for Distribution Estimation [arXiv:1502.03509]
164     Mathieu Germain, Karol Gregor, Iain Murray, Hugo Larochelle
165     """
166 
167     def __init__(self, input_dim, hidden_dim, sigmoid_bias=2.0, permutation=None):
168         super(InverseAutoregressiveFlow, self).__init__()
169         self.input_dim = input_dim
170         self.hidden_dim = hidden_dim
171         self.arn = AutoRegressiveNN(input_dim, hidden_dim, output_dim_multiplier=2, permutation=permutation)
172         self.sigmoid = nn.Sigmoid()
173         self.sigmoid_bias = Variable(torch.Tensor([sigmoid_bias]))
174         self._intermediates_cache = {}
175         self.add_inverse_to_cache = True
176 
177     def get_arn(self):
178         """
179         :rtype: pyro.nn.AutoRegressiveNN
180 
181         Return the AutoRegressiveNN associated with the InverseAutoregressiveFlow
182         """
183         return self.arn
184 
185     def __call__(self, x, *args, **kwargs):
186         """
187         :param x: the input into the bijection
188         :type x: torch.autograd.Variable
189 
190         Invokes the bijection x=>y; in the prototypical context of a TransformedDistribution `x` is a
191         sample from the base distribution (or the output of a previous flow)
192         """
193         hidden = self.arn(x)
194         sigma = self.sigmoid(hidden[:, 0:self.input_dim] + self.sigmoid_bias.type_as(hidden))
195         mean = hidden[:, self.input_dim:]
196         y = sigma * x + (Variable(torch.ones(sigma.size())).type_as(sigma) - sigma) * mean
197         self._add_intermediate_to_cache(sigma, y, 'sigma')
198         return y
199 
200     def inverse(self, y, *args, **kwargs):
201         """
202         :param y: the output of the bijection
203         :type y: torch.autograd.Variable
204 
205         Inverts y => x. As noted above, this implementation is incapable of inverting arbitrary values
206         `y`; rather it assumes `y` is the result of a previously computed application of the bijector
207         to some `x` (which was cached on the forward call)
208         """
209         if (y, 'x') in self._intermediates_cache:
210             x = self._intermediates_cache.pop((y, 'x'))
211             return x
212         else:
213             raise KeyError("Bijector InverseAutoregressiveFlow expected to find" +
214                            "key in intermediates cache but didn't")
215 
216     def _add_intermediate_to_cache(self, intermediate, y, name):
217         """
218         Internal function used to cache intermediate results computed during the forward call
219         """
220         assert((y, name) not in self._intermediates_cache),\
221             "key collision in _add_intermediate_to_cache"
222         self._intermediates_cache[(y, name)] = intermediate
223 
224     def log_det_jacobian(self, y, *args, **kwargs):
225         """
226         Calculates the determinant of the log jacobian
227         """
228         if (y, 'sigma') in self._intermediates_cache:
229             sigma = self._intermediates_cache.pop((y, 'sigma'))
230         else:
231             raise KeyError("Bijector InverseAutoregressiveFlow expected to find" +
232                            "key in intermediates cache but didn't")
233         if 'log_pdf_mask' in kwargs:
234             return torch.sum(kwargs['log_pdf_mask'] * torch.log(sigma))
235         return torch.sum(torch.log(sigma))
236
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/pyro/distributions/transformed_distribution.py b/pyro/distributions/transformed_distribution.py
--- a/pyro/distributions/transformed_distribution.py
+++ b/pyro/distributions/transformed_distribution.py
@@ -59,7 +59,7 @@
         """
         Ref: :py:meth:`pyro.distributions.distribution.Distribution.event_shape`
         """
-        return self.base_dist.batch_shape(*args, **kwargs)
+        return self.base_dist.event_shape(*args, **kwargs)
 
     def log_pdf(self, y, *args, **kwargs):
         """

{"golden_diff": "diff --git a/pyro/distributions/transformed_distribution.py b/pyro/distributions/transformed_distribution.py\n--- a/pyro/distributions/transformed_distribution.py\n+++ b/pyro/distributions/transformed_distribution.py\n@@ -59,7 +59,7 @@\n         \"\"\"\n         Ref: :py:meth:`pyro.distributions.distribution.Distribution.event_shape`\n         \"\"\"\n-        return self.base_dist.batch_shape(*args, **kwargs)\n+        return self.base_dist.event_shape(*args, **kwargs)\n \n     def log_pdf(self, y, *args, **kwargs):\n         \"\"\"\n", "issue": "TransformedDistribution's event_shape forwards to incorrect base distribution's method\nProbably a typo:\r\n\r\nhttps://github.com/uber/pyro/blob/51a2ccfe9445c7072c3150c4abe1ab1d2ac17246/pyro/distributions/transformed_distribution.py#L62\n", "before_files": [{"content": "from __future__ import absolute_import, division, print_function\n\nimport torch\nimport torch.nn as nn\nfrom torch.autograd import Variable\n\nfrom pyro.distributions.distribution import Distribution\nfrom pyro.nn import AutoRegressiveNN\n\n\nclass TransformedDistribution(Distribution):\n    \"\"\"\n    Transforms the base distribution by applying a sequence of `Bijector`s to it.\n    This results in a scorable distribution (i.e. it has a `log_pdf()` method).\n\n    :param base_distribution: a (continuous) base distribution; samples from this distribution\n        are passed through the sequence of `Bijector`s to yield a sample from the\n        `TransformedDistribution`\n    :type base_distribution: pyro.distribution.Distribution\n    :param bijectors: either a single Bijector or a sequence of Bijectors wrapped in a nn.ModuleList\n    :returns: the transformed distribution\n    \"\"\"\n\n    def __init__(self, base_distribution, bijectors, *args, **kwargs):\n        super(TransformedDistribution, self).__init__(*args, **kwargs)\n        self.reparameterized = base_distribution.reparameterized\n        self.base_dist = base_distribution\n        if isinstance(bijectors, Bijector):\n            self.bijectors = nn.ModuleList([bijectors])\n        elif isinstance(bijectors, nn.ModuleList):\n            for bijector in bijectors:\n                assert isinstance(bijector, Bijector), \\\n                    \"bijectors must be a Bijector or a nn.ModuleList of Bijectors\"\n            self.bijectors = bijectors\n\n    def sample(self, *args, **kwargs):\n        \"\"\"\n        :returns: a sample y\n        :rtype: torch.autograd.Variable\n\n        Sample from base distribution and pass through bijector(s)\n        \"\"\"\n        x = self.base_dist.sample(*args, **kwargs)\n        next_input = x\n        for bijector in self.bijectors:\n            y = bijector(next_input)\n            if bijector.add_inverse_to_cache:\n                bijector._add_intermediate_to_cache(next_input, y, 'x')\n            next_input = y\n        return next_input\n\n    def batch_shape(self, x=None, *args, **kwargs):\n        \"\"\"\n        Ref: :py:meth:`pyro.distributions.distribution.Distribution.batch_shape`\n        \"\"\"\n        return self.base_dist.batch_shape(x, *args, **kwargs)\n\n    def event_shape(self, *args, **kwargs):\n        \"\"\"\n        Ref: :py:meth:`pyro.distributions.distribution.Distribution.event_shape`\n        \"\"\"\n        return self.base_dist.batch_shape(*args, **kwargs)\n\n    def log_pdf(self, y, *args, **kwargs):\n        \"\"\"\n        :param y: a value sampled from the transformed distribution\n        :type y: torch.autograd.Variable\n\n        :returns: the score (the log pdf) of y\n        :rtype: torch.autograd.Variable\n\n        Scores the sample by inverting the bijector(s) and computing the score using the score\n        of the base distribution and the log det jacobian\n        \"\"\"\n        inverses = []\n        next_to_invert = y\n        for bijector in reversed(self.bijectors):\n            inverse = bijector.inverse(next_to_invert)\n            inverses.append(inverse)\n            next_to_invert = inverse\n        log_pdf_base = self.base_dist.log_pdf(inverses[-1], *args, **kwargs)\n        log_det_jacobian = self.bijectors[-1].log_det_jacobian(y, *args, **kwargs)\n        for bijector, inverse in zip(list(reversed(self.bijectors))[1:], inverses[:-1]):\n            log_det_jacobian += bijector.log_det_jacobian(inverse, *args, **kwargs)\n        return log_pdf_base - log_det_jacobian\n\n    def batch_log_pdf(self, y, *args, **kwargs):\n        raise NotImplementedError(\"https://github.com/uber/pyro/issues/293\")\n\n\nclass Bijector(nn.Module):\n    \"\"\"\n    Abstract class `Bijector`. `Bijector` are bijective transformations with computable\n    log det jacobians. They are meant for use in `TransformedDistribution`.\n    \"\"\"\n\n    def __init__(self, *args, **kwargs):\n        super(Bijector, self).__init__(*args, **kwargs)\n        self.add_inverse_to_cache = False\n\n    def __call__(self, *args, **kwargs):\n        \"\"\"\n        Virtual forward method\n\n        Invokes the bijection x=>y\n        \"\"\"\n        raise NotImplementedError()\n\n    def inverse(self, *args, **kwargs):\n        \"\"\"\n        Virtual inverse method\n\n        Inverts the bijection y => x.\n        \"\"\"\n        raise NotImplementedError()\n\n    def log_det_jacobian(self, *args, **kwargs):\n        \"\"\"\n        Virtual logdet jacobian method.\n\n        Computes the log det jacobian `|dy/dx|`\n        \"\"\"\n        raise NotImplementedError()\n\n\nclass InverseAutoregressiveFlow(Bijector):\n    \"\"\"\n    An implementation of an Inverse Autoregressive Flow. Together with the `TransformedDistribution` this\n    provides a way to create richer variational approximations.\n\n    Example usage::\n\n    >>> base_dist = Normal(...)\n    >>> iaf = InverseAutoregressiveFlow(...)\n    >>> pyro.module(\"my_iaf\", iaf)\n    >>> iaf_dist = TransformedDistribution(base_dist, iaf)\n\n    Note that this implementation is only meant to be used in settings where the inverse of the Bijector\n    is never explicitly computed (rather the result is cached from the forward call). In the context of\n    variational inference, this means that the InverseAutoregressiveFlow should only be used in the guide,\n    i.e. in the variational distribution. In other contexts the inverse could in principle be computed but\n    this would be a (potentially) costly computation that scales with the dimension of the input (and in\n    any case support for this is not included in this implementation).\n\n    :param input_dim: dimension of input\n    :type input_dim: int\n    :param hidden_dim: hidden dimension (number of hidden units)\n    :type hidden_dim: int\n    :param sigmoid_bias: bias on the hidden units fed into the sigmoid; default=`2.0`\n    :type sigmoid_bias: float\n    :param permutation: whether the order of the inputs should be permuted (by default the conditional\n        dependence structure of the autoregression follows the sequential order)\n    :type permutation: bool\n\n    References:\n\n    1. Improving Variational Inference with Inverse Autoregressive Flow [arXiv:1606.04934]\n    Diederik P. Kingma, Tim Salimans, Rafal Jozefowicz, Xi Chen, Ilya Sutskever, Max Welling\n\n    2. Variational Inference with Normalizing Flows [arXiv:1505.05770]\n    Danilo Jimenez Rezende, Shakir Mohamed\n\n    3. MADE: Masked Autoencoder for Distribution Estimation [arXiv:1502.03509]\n    Mathieu Germain, Karol Gregor, Iain Murray, Hugo Larochelle\n    \"\"\"\n\n    def __init__(self, input_dim, hidden_dim, sigmoid_bias=2.0, permutation=None):\n        super(InverseAutoregressiveFlow, self).__init__()\n        self.input_dim = input_dim\n        self.hidden_dim = hidden_dim\n        self.arn = AutoRegressiveNN(input_dim, hidden_dim, output_dim_multiplier=2, permutation=permutation)\n        self.sigmoid = nn.Sigmoid()\n        self.sigmoid_bias = Variable(torch.Tensor([sigmoid_bias]))\n        self._intermediates_cache = {}\n        self.add_inverse_to_cache = True\n\n    def get_arn(self):\n        \"\"\"\n        :rtype: pyro.nn.AutoRegressiveNN\n\n        Return the AutoRegressiveNN associated with the InverseAutoregressiveFlow\n        \"\"\"\n        return self.arn\n\n    def __call__(self, x, *args, **kwargs):\n        \"\"\"\n        :param x: the input into the bijection\n        :type x: torch.autograd.Variable\n\n        Invokes the bijection x=>y; in the prototypical context of a TransformedDistribution `x` is a\n        sample from the base distribution (or the output of a previous flow)\n        \"\"\"\n        hidden = self.arn(x)\n        sigma = self.sigmoid(hidden[:, 0:self.input_dim] + self.sigmoid_bias.type_as(hidden))\n        mean = hidden[:, self.input_dim:]\n        y = sigma * x + (Variable(torch.ones(sigma.size())).type_as(sigma) - sigma) * mean\n        self._add_intermediate_to_cache(sigma, y, 'sigma')\n        return y\n\n    def inverse(self, y, *args, **kwargs):\n        \"\"\"\n        :param y: the output of the bijection\n        :type y: torch.autograd.Variable\n\n        Inverts y => x. As noted above, this implementation is incapable of inverting arbitrary values\n        `y`; rather it assumes `y` is the result of a previously computed application of the bijector\n        to some `x` (which was cached on the forward call)\n        \"\"\"\n        if (y, 'x') in self._intermediates_cache:\n            x = self._intermediates_cache.pop((y, 'x'))\n            return x\n        else:\n            raise KeyError(\"Bijector InverseAutoregressiveFlow expected to find\" +\n                           \"key in intermediates cache but didn't\")\n\n    def _add_intermediate_to_cache(self, intermediate, y, name):\n        \"\"\"\n        Internal function used to cache intermediate results computed during the forward call\n        \"\"\"\n        assert((y, name) not in self._intermediates_cache),\\\n            \"key collision in _add_intermediate_to_cache\"\n        self._intermediates_cache[(y, name)] = intermediate\n\n    def log_det_jacobian(self, y, *args, **kwargs):\n        \"\"\"\n        Calculates the determinant of the log jacobian\n        \"\"\"\n        if (y, 'sigma') in self._intermediates_cache:\n            sigma = self._intermediates_cache.pop((y, 'sigma'))\n        else:\n            raise KeyError(\"Bijector InverseAutoregressiveFlow expected to find\" +\n                           \"key in intermediates cache but didn't\")\n        if 'log_pdf_mask' in kwargs:\n            return torch.sum(kwargs['log_pdf_mask'] * torch.log(sigma))\n        return torch.sum(torch.log(sigma))\n", "path": "pyro/distributions/transformed_distribution.py"}], "after_files": [{"content": "from __future__ import absolute_import, division, print_function\n\nimport torch\nimport torch.nn as nn\nfrom torch.autograd import Variable\n\nfrom pyro.distributions.distribution import Distribution\nfrom pyro.nn import AutoRegressiveNN\n\n\nclass TransformedDistribution(Distribution):\n    \"\"\"\n    Transforms the base distribution by applying a sequence of `Bijector`s to it.\n    This results in a scorable distribution (i.e. it has a `log_pdf()` method).\n\n    :param base_distribution: a (continuous) base distribution; samples from this distribution\n        are passed through the sequence of `Bijector`s to yield a sample from the\n        `TransformedDistribution`\n    :type base_distribution: pyro.distribution.Distribution\n    :param bijectors: either a single Bijector or a sequence of Bijectors wrapped in a nn.ModuleList\n    :returns: the transformed distribution\n    \"\"\"\n\n    def __init__(self, base_distribution, bijectors, *args, **kwargs):\n        super(TransformedDistribution, self).__init__(*args, **kwargs)\n        self.reparameterized = base_distribution.reparameterized\n        self.base_dist = base_distribution\n        if isinstance(bijectors, Bijector):\n            self.bijectors = nn.ModuleList([bijectors])\n        elif isinstance(bijectors, nn.ModuleList):\n            for bijector in bijectors:\n                assert isinstance(bijector, Bijector), \\\n                    \"bijectors must be a Bijector or a nn.ModuleList of Bijectors\"\n            self.bijectors = bijectors\n\n    def sample(self, *args, **kwargs):\n        \"\"\"\n        :returns: a sample y\n        :rtype: torch.autograd.Variable\n\n        Sample from base distribution and pass through bijector(s)\n        \"\"\"\n        x = self.base_dist.sample(*args, **kwargs)\n        next_input = x\n        for bijector in self.bijectors:\n            y = bijector(next_input)\n            if bijector.add_inverse_to_cache:\n                bijector._add_intermediate_to_cache(next_input, y, 'x')\n            next_input = y\n        return next_input\n\n    def batch_shape(self, x=None, *args, **kwargs):\n        \"\"\"\n        Ref: :py:meth:`pyro.distributions.distribution.Distribution.batch_shape`\n        \"\"\"\n        return self.base_dist.batch_shape(x, *args, **kwargs)\n\n    def event_shape(self, *args, **kwargs):\n        \"\"\"\n        Ref: :py:meth:`pyro.distributions.distribution.Distribution.event_shape`\n        \"\"\"\n        return self.base_dist.event_shape(*args, **kwargs)\n\n    def log_pdf(self, y, *args, **kwargs):\n        \"\"\"\n        :param y: a value sampled from the transformed distribution\n        :type y: torch.autograd.Variable\n\n        :returns: the score (the log pdf) of y\n        :rtype: torch.autograd.Variable\n\n        Scores the sample by inverting the bijector(s) and computing the score using the score\n        of the base distribution and the log det jacobian\n        \"\"\"\n        inverses = []\n        next_to_invert = y\n        for bijector in reversed(self.bijectors):\n            inverse = bijector.inverse(next_to_invert)\n            inverses.append(inverse)\n            next_to_invert = inverse\n        log_pdf_base = self.base_dist.log_pdf(inverses[-1], *args, **kwargs)\n        log_det_jacobian = self.bijectors[-1].log_det_jacobian(y, *args, **kwargs)\n        for bijector, inverse in zip(list(reversed(self.bijectors))[1:], inverses[:-1]):\n            log_det_jacobian += bijector.log_det_jacobian(inverse, *args, **kwargs)\n        return log_pdf_base - log_det_jacobian\n\n    def batch_log_pdf(self, y, *args, **kwargs):\n        raise NotImplementedError(\"https://github.com/uber/pyro/issues/293\")\n\n\nclass Bijector(nn.Module):\n    \"\"\"\n    Abstract class `Bijector`. `Bijector` are bijective transformations with computable\n    log det jacobians. They are meant for use in `TransformedDistribution`.\n    \"\"\"\n\n    def __init__(self, *args, **kwargs):\n        super(Bijector, self).__init__(*args, **kwargs)\n        self.add_inverse_to_cache = False\n\n    def __call__(self, *args, **kwargs):\n        \"\"\"\n        Virtual forward method\n\n        Invokes the bijection x=>y\n        \"\"\"\n        raise NotImplementedError()\n\n    def inverse(self, *args, **kwargs):\n        \"\"\"\n        Virtual inverse method\n\n        Inverts the bijection y => x.\n        \"\"\"\n        raise NotImplementedError()\n\n    def log_det_jacobian(self, *args, **kwargs):\n        \"\"\"\n        Virtual logdet jacobian method.\n\n        Computes the log det jacobian `|dy/dx|`\n        \"\"\"\n        raise NotImplementedError()\n\n\nclass InverseAutoregressiveFlow(Bijector):\n    \"\"\"\n    An implementation of an Inverse Autoregressive Flow. Together with the `TransformedDistribution` this\n    provides a way to create richer variational approximations.\n\n    Example usage::\n\n    >>> base_dist = Normal(...)\n    >>> iaf = InverseAutoregressiveFlow(...)\n    >>> pyro.module(\"my_iaf\", iaf)\n    >>> iaf_dist = TransformedDistribution(base_dist, iaf)\n\n    Note that this implementation is only meant to be used in settings where the inverse of the Bijector\n    is never explicitly computed (rather the result is cached from the forward call). In the context of\n    variational inference, this means that the InverseAutoregressiveFlow should only be used in the guide,\n    i.e. in the variational distribution. In other contexts the inverse could in principle be computed but\n    this would be a (potentially) costly computation that scales with the dimension of the input (and in\n    any case support for this is not included in this implementation).\n\n    :param input_dim: dimension of input\n    :type input_dim: int\n    :param hidden_dim: hidden dimension (number of hidden units)\n    :type hidden_dim: int\n    :param sigmoid_bias: bias on the hidden units fed into the sigmoid; default=`2.0`\n    :type sigmoid_bias: float\n    :param permutation: whether the order of the inputs should be permuted (by default the conditional\n        dependence structure of the autoregression follows the sequential order)\n    :type permutation: bool\n\n    References:\n\n    1. Improving Variational Inference with Inverse Autoregressive Flow [arXiv:1606.04934]\n    Diederik P. Kingma, Tim Salimans, Rafal Jozefowicz, Xi Chen, Ilya Sutskever, Max Welling\n\n    2. Variational Inference with Normalizing Flows [arXiv:1505.05770]\n    Danilo Jimenez Rezende, Shakir Mohamed\n\n    3. MADE: Masked Autoencoder for Distribution Estimation [arXiv:1502.03509]\n    Mathieu Germain, Karol Gregor, Iain Murray, Hugo Larochelle\n    \"\"\"\n\n    def __init__(self, input_dim, hidden_dim, sigmoid_bias=2.0, permutation=None):\n        super(InverseAutoregressiveFlow, self).__init__()\n        self.input_dim = input_dim\n        self.hidden_dim = hidden_dim\n        self.arn = AutoRegressiveNN(input_dim, hidden_dim, output_dim_multiplier=2, permutation=permutation)\n        self.sigmoid = nn.Sigmoid()\n        self.sigmoid_bias = Variable(torch.Tensor([sigmoid_bias]))\n        self._intermediates_cache = {}\n        self.add_inverse_to_cache = True\n\n    def get_arn(self):\n        \"\"\"\n        :rtype: pyro.nn.AutoRegressiveNN\n\n        Return the AutoRegressiveNN associated with the InverseAutoregressiveFlow\n        \"\"\"\n        return self.arn\n\n    def __call__(self, x, *args, **kwargs):\n        \"\"\"\n        :param x: the input into the bijection\n        :type x: torch.autograd.Variable\n\n        Invokes the bijection x=>y; in the prototypical context of a TransformedDistribution `x` is a\n        sample from the base distribution (or the output of a previous flow)\n        \"\"\"\n        hidden = self.arn(x)\n        sigma = self.sigmoid(hidden[:, 0:self.input_dim] + self.sigmoid_bias.type_as(hidden))\n        mean = hidden[:, self.input_dim:]\n        y = sigma * x + (Variable(torch.ones(sigma.size())).type_as(sigma) - sigma) * mean\n        self._add_intermediate_to_cache(sigma, y, 'sigma')\n        return y\n\n    def inverse(self, y, *args, **kwargs):\n        \"\"\"\n        :param y: the output of the bijection\n        :type y: torch.autograd.Variable\n\n        Inverts y => x. As noted above, this implementation is incapable of inverting arbitrary values\n        `y`; rather it assumes `y` is the result of a previously computed application of the bijector\n        to some `x` (which was cached on the forward call)\n        \"\"\"\n        if (y, 'x') in self._intermediates_cache:\n            x = self._intermediates_cache.pop((y, 'x'))\n            return x\n        else:\n            raise KeyError(\"Bijector InverseAutoregressiveFlow expected to find\" +\n                           \"key in intermediates cache but didn't\")\n\n    def _add_intermediate_to_cache(self, intermediate, y, name):\n        \"\"\"\n        Internal function used to cache intermediate results computed during the forward call\n        \"\"\"\n        assert((y, name) not in self._intermediates_cache),\\\n            \"key collision in _add_intermediate_to_cache\"\n        self._intermediates_cache[(y, name)] = intermediate\n\n    def log_det_jacobian(self, y, *args, **kwargs):\n        \"\"\"\n        Calculates the determinant of the log jacobian\n        \"\"\"\n        if (y, 'sigma') in self._intermediates_cache:\n            sigma = self._intermediates_cache.pop((y, 'sigma'))\n        else:\n            raise KeyError(\"Bijector InverseAutoregressiveFlow expected to find\" +\n                           \"key in intermediates cache but didn't\")\n        if 'log_pdf_mask' in kwargs:\n            return torch.sum(kwargs['log_pdf_mask'] * torch.log(sigma))\n        return torch.sum(torch.log(sigma))\n", "path": "pyro/distributions/transformed_distribution.py"}]}