We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
ConditionedPlanarFlow's event_dim is wrong [bug]

--------------------------------------------------------------------------------------------------
### Issue Description
Provide a brief description of the issue.

I think the ConditionedPlanarFlow's event_dim is incorrect. I think the class needs to be set as such:
```

class ConditionedPlanarFlow(Transform):
   event_dim=1 #this line is not in the current release version
    def __init__(self, bias=None, u=None, w=None):
        super(ConditionedPlanarFlow, self).__init__(cache_size=1)
        self.bias = bias
        self.u = u
        self.w = w
        self._cached_logDetJ = None

```
The Transform super class default is event_dim=0.

Maybe I misunderstand this class, but I notice the PlanarFlow class has event_dim=1, as do many of the other normalizing flows and when I tried using this flow for my models my ELBO would go negative. I think the confusion is that ConditionalPlanarFlow has the event_dim=1, but that isn't setting it when it the actual flows are created (from what I can tell anyways).

### Environment
For any bugs, please provide the following:
 - Found on: Ubuntu 
 - PyTorch version: I think I was using 1.2 ...but again this is a super minor bug
You can see it in the the pyro docs http://docs.pyro.ai/en/stable/_modules/pyro/distributions/transforms/planar.html#ConditionalPlanarFlow

 - Pyro version: 3.6.10 (I think...pretty sure a single boolean value is pretty robust to version though)
Was originally found in...nightly build (not sure on term... I built from sourceb asically)



--- 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/transforms/planar.py`
Content:
```
1 import math
2 
3 import torch
4 import torch.nn as nn
5 from torch.distributions import constraints
6 import torch.nn.functional as F
7 
8 from torch.distributions import Transform
9 from pyro.distributions.conditional import ConditionalTransformModule
10 from pyro.distributions.torch_transform import TransformModule
11 from pyro.distributions.util import copy_docs_from
12 from pyro.nn import DenseNN
13 
14 
15 @copy_docs_from(Transform)
16 class ConditionedPlanar(Transform):
17     def __init__(self, bias=None, u=None, w=None):
18         super(ConditionedPlanar, self).__init__(cache_size=1)
19         self.bias = bias
20         self.u = u
21         self.w = w
22         self._cached_logDetJ = None
23 
24     # This method ensures that torch(u_hat, w) > -1, required for invertibility
25     def u_hat(self, u, w):
26         alpha = torch.matmul(u.unsqueeze(-2), w.unsqueeze(-1)).squeeze(-1)
27         a_prime = -1 + F.softplus(alpha)
28         return u + (a_prime - alpha) * w.div(w.pow(2).sum(dim=-1, keepdim=True))
29 
30     def _call(self, x):
31         """
32         :param x: the input into the bijection
33         :type x: torch.Tensor
34         Invokes the bijection x => y; in the prototypical context of a
35         :class:`~pyro.distributions.TransformedDistribution` `x` is a sample from the base distribution (or the output
36         of a previous transform)
37         """
38 
39         # x ~ (batch_size, dim_size, 1)
40         # w ~ (batch_size, 1, dim_size)
41         # bias ~ (batch_size, 1)
42         act = torch.tanh(torch.matmul(self.w.unsqueeze(-2), x.unsqueeze(-1)).squeeze(-1) + self.bias)
43         u_hat = self.u_hat(self.u, self.w)
44         y = x + u_hat * act
45 
46         psi_z = (1. - act.pow(2)) * self.w
47         self._cached_logDetJ = torch.log(
48             torch.abs(1 + torch.matmul(psi_z.unsqueeze(-2), u_hat.unsqueeze(-1)).squeeze(-1).squeeze(-1)))
49 
50         return y
51 
52     def _inverse(self, y):
53         """
54         :param y: the output of the bijection
55         :type y: torch.Tensor
56         Inverts y => x. As noted above, this implementation is incapable of inverting arbitrary values
57         `y`; rather it assumes `y` is the result of a previously computed application of the bijector
58         to some `x` (which was cached on the forward call)
59         """
60 
61         raise KeyError("ConditionalPlanar object expected to find key in intermediates cache but didn't")
62 
63     def log_abs_det_jacobian(self, x, y):
64         """
65         Calculates the elementwise determinant of the log Jacobian
66         """
67         return self._cached_logDetJ
68 
69 
70 @copy_docs_from(ConditionedPlanar)
71 class Planar(ConditionedPlanar, TransformModule):
72     """
73     A 'planar' bijective transform with equation,
74 
75         :math:`\\mathbf{y} = \\mathbf{x} + \\mathbf{u}\\tanh(\\mathbf{w}^T\\mathbf{z}+b)`
76 
77     where :math:`\\mathbf{x}` are the inputs, :math:`\\mathbf{y}` are the outputs, and the learnable parameters
78     are :math:`b\\in\\mathbb{R}`, :math:`\\mathbf{u}\\in\\mathbb{R}^D`, :math:`\\mathbf{w}\\in\\mathbb{R}^D` for input
79     dimension :math:`D`. For this to be an invertible transformation, the condition
80     :math:`\\mathbf{w}^T\\mathbf{u}>-1` is enforced.
81 
82     Together with :class:`~pyro.distributions.TransformedDistribution` this provides a way to create richer
83     variational approximations.
84 
85     Example usage:
86 
87     >>> base_dist = dist.Normal(torch.zeros(10), torch.ones(10))
88     >>> transform = Planar(10)
89     >>> pyro.module("my_transform", transform)  # doctest: +SKIP
90     >>> flow_dist = dist.TransformedDistribution(base_dist, [transform])
91     >>> flow_dist.sample()  # doctest: +SKIP
92         tensor([-0.4071, -0.5030,  0.7924, -0.2366, -0.2387, -0.1417,  0.0868,
93                 0.1389, -0.4629,  0.0986])
94 
95     The inverse of this transform does not possess an analytical solution and is left unimplemented. However,
96     the inverse is cached when the forward operation is called during sampling, and so samples drawn using
97     the planar transform can be scored.
98 
99     :param input_dim: the dimension of the input (and output) variable.
100     :type input_dim: int
101 
102     References:
103 
104     Variational Inference with Normalizing Flows [arXiv:1505.05770]
105     Danilo Jimenez Rezende, Shakir Mohamed
106 
107     """
108 
109     domain = constraints.real
110     codomain = constraints.real
111     bijective = True
112     event_dim = 1
113 
114     def __init__(self, input_dim):
115         super(Planar, self).__init__()
116 
117         self.bias = nn.Parameter(torch.Tensor(1,))
118         self.u = nn.Parameter(torch.Tensor(input_dim,))
119         self.w = nn.Parameter(torch.Tensor(input_dim,))
120         self.input_dim = input_dim
121         self.reset_parameters()
122 
123     def reset_parameters(self):
124         stdv = 1. / math.sqrt(self.u.size(0))
125         self.w.data.uniform_(-stdv, stdv)
126         self.u.data.uniform_(-stdv, stdv)
127         self.bias.data.zero_()
128 
129 
130 @copy_docs_from(ConditionalTransformModule)
131 class ConditionalPlanar(ConditionalTransformModule):
132     """
133     A conditional 'planar' bijective transform using the equation,
134 
135         :math:`\\mathbf{y} = \\mathbf{x} + \\mathbf{u}\\tanh(\\mathbf{w}^T\\mathbf{z}+b)`
136 
137     where :math:`\\mathbf{x}` are the inputs with dimension :math:`D`, :math:`\\mathbf{y}` are the outputs,
138     and the pseudo-parameters :math:`b\\in\\mathbb{R}`, :math:`\\mathbf{u}\\in\\mathbb{R}^D`, and
139     :math:`\\mathbf{w}\\in\\mathbb{R}^D` are the output of a function, e.g. a NN, with input
140     :math:`z\\in\\mathbb{R}^{M}` representing the context variable to condition on. For this to be an
141     invertible transformation, the condition :math:`\\mathbf{w}^T\\mathbf{u}>-1` is enforced.
142 
143     Together with :class:`~pyro.distributions.ConditionalTransformedDistribution` this provides a way to create
144     richer variational approximations.
145 
146     Example usage:
147 
148     >>> from pyro.nn.dense_nn import DenseNN
149     >>> input_dim = 10
150     >>> context_dim = 5
151     >>> batch_size = 3
152     >>> base_dist = dist.Normal(torch.zeros(input_dim), torch.ones(input_dim))
153     >>> hypernet = DenseNN(context_dim, [50, 50], param_dims=[1, input_dim, input_dim])
154     >>> transform = ConditionalPlanar(hypernet)
155     >>> z = torch.rand(batch_size, context_dim)
156     >>> flow_dist = dist.ConditionalTransformedDistribution(base_dist, [transform]).condition(z)
157     >>> flow_dist.sample(sample_shape=torch.Size([batch_size])) # doctest: +SKIP
158 
159     The inverse of this transform does not possess an analytical solution and is left unimplemented. However,
160     the inverse is cached when the forward operation is called during sampling, and so samples drawn using
161     the planar transform can be scored.
162 
163     :param nn: a function inputting the context variable and outputting a triplet of real-valued parameters
164         of dimensions :math:`(1, D, D)`.
165     :type nn: callable
166 
167     References:
168     Variational Inference with Normalizing Flows [arXiv:1505.05770]
169     Danilo Jimenez Rezende, Shakir Mohamed
170 
171     """
172 
173     domain = constraints.real
174     codomain = constraints.real
175     bijective = True
176     event_dim = 1
177 
178     def __init__(self, nn):
179         super(ConditionalPlanar, self).__init__()
180         self.nn = nn
181 
182     def condition(self, context):
183         bias, u, w = self.nn(context)
184         return ConditionedPlanar(bias, u, w)
185 
186 
187 def planar(input_dim):
188     """
189     A helper function to create a :class:`~pyro.distributions.transforms.Planar` object for consistency with other
190     helpers.
191 
192     :param input_dim: Dimension of input variable
193     :type input_dim: int
194 
195     """
196 
197     return Planar(input_dim)
198 
199 
200 def conditional_planar(input_dim, context_dim, hidden_dims=None):
201     """
202     A helper function to create a :class:`~pyro.distributions.transforms.ConditionalPlanar` object that takes care of
203     constructing a dense network with the correct input/output dimensions.
204 
205     :param input_dim: Dimension of input variable
206     :type input_dim: int
207     :param context_dim: Dimension of context variable
208     :type context_dim: int
209     :param hidden_dims: The desired hidden dimensions of the dense network. Defaults
210         to using [input_dim * 10, input_dim * 10]
211     :type hidden_dims: list[int]
212 
213 
214     """
215 
216     if hidden_dims is None:
217         hidden_dims = [input_dim * 10, input_dim * 10]
218     hypernet = DenseNN(context_dim, hidden_dims, param_dims=[1, input_dim, input_dim])
219     return ConditionalPlanar(hypernet)
220
```
--- 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/transforms/planar.py b/pyro/distributions/transforms/planar.py
--- a/pyro/distributions/transforms/planar.py
+++ b/pyro/distributions/transforms/planar.py
@@ -14,6 +14,11 @@
 
 @copy_docs_from(Transform)
 class ConditionedPlanar(Transform):
+    domain = constraints.real
+    codomain = constraints.real
+    bijective = True
+    event_dim = 1
+
     def __init__(self, bias=None, u=None, w=None):
         super(ConditionedPlanar, self).__init__(cache_size=1)
         self.bias = bias

{"golden_diff": "diff --git a/pyro/distributions/transforms/planar.py b/pyro/distributions/transforms/planar.py\n--- a/pyro/distributions/transforms/planar.py\n+++ b/pyro/distributions/transforms/planar.py\n@@ -14,6 +14,11 @@\n \n @copy_docs_from(Transform)\n class ConditionedPlanar(Transform):\n+    domain = constraints.real\n+    codomain = constraints.real\n+    bijective = True\n+    event_dim = 1\n+\n     def __init__(self, bias=None, u=None, w=None):\n         super(ConditionedPlanar, self).__init__(cache_size=1)\n         self.bias = bias\n", "issue": "ConditionedPlanarFlow's event_dim is wrong [bug]\n\r\n--------------------------------------------------------------------------------------------------\r\n### Issue Description\r\nProvide a brief description of the issue.\r\n\r\nI think the ConditionedPlanarFlow's event_dim is incorrect. I think the class needs to be set as such:\r\n```\r\n\r\nclass ConditionedPlanarFlow(Transform):\r\n   event_dim=1 #this line is not in the current release version\r\n    def __init__(self, bias=None, u=None, w=None):\r\n        super(ConditionedPlanarFlow, self).__init__(cache_size=1)\r\n        self.bias = bias\r\n        self.u = u\r\n        self.w = w\r\n        self._cached_logDetJ = None\r\n\r\n```\r\nThe Transform super class default is event_dim=0.\r\n\r\nMaybe I misunderstand this class, but I notice the PlanarFlow class has event_dim=1, as do many of the other normalizing flows and when I tried using this flow for my models my ELBO would go negative. I think the confusion is that ConditionalPlanarFlow has the event_dim=1, but that isn't setting it when it the actual flows are created (from what I can tell anyways).\r\n\r\n### Environment\r\nFor any bugs, please provide the following:\r\n - Found on: Ubuntu \r\n - PyTorch version: I think I was using 1.2 ...but again this is a super minor bug\r\nYou can see it in the the pyro docs http://docs.pyro.ai/en/stable/_modules/pyro/distributions/transforms/planar.html#ConditionalPlanarFlow\r\n\r\n - Pyro version: 3.6.10 (I think...pretty sure a single boolean value is pretty robust to version though)\r\nWas originally found in...nightly build (not sure on term... I built from sourceb asically)\r\n\r\n\n", "before_files": [{"content": "import math\n\nimport torch\nimport torch.nn as nn\nfrom torch.distributions import constraints\nimport torch.nn.functional as F\n\nfrom torch.distributions import Transform\nfrom pyro.distributions.conditional import ConditionalTransformModule\nfrom pyro.distributions.torch_transform import TransformModule\nfrom pyro.distributions.util import copy_docs_from\nfrom pyro.nn import DenseNN\n\n\n@copy_docs_from(Transform)\nclass ConditionedPlanar(Transform):\n    def __init__(self, bias=None, u=None, w=None):\n        super(ConditionedPlanar, self).__init__(cache_size=1)\n        self.bias = bias\n        self.u = u\n        self.w = w\n        self._cached_logDetJ = None\n\n    # This method ensures that torch(u_hat, w) > -1, required for invertibility\n    def u_hat(self, u, w):\n        alpha = torch.matmul(u.unsqueeze(-2), w.unsqueeze(-1)).squeeze(-1)\n        a_prime = -1 + F.softplus(alpha)\n        return u + (a_prime - alpha) * w.div(w.pow(2).sum(dim=-1, keepdim=True))\n\n    def _call(self, x):\n        \"\"\"\n        :param x: the input into the bijection\n        :type x: torch.Tensor\n        Invokes the bijection x => y; in the prototypical context of a\n        :class:`~pyro.distributions.TransformedDistribution` `x` is a sample from the base distribution (or the output\n        of a previous transform)\n        \"\"\"\n\n        # x ~ (batch_size, dim_size, 1)\n        # w ~ (batch_size, 1, dim_size)\n        # bias ~ (batch_size, 1)\n        act = torch.tanh(torch.matmul(self.w.unsqueeze(-2), x.unsqueeze(-1)).squeeze(-1) + self.bias)\n        u_hat = self.u_hat(self.u, self.w)\n        y = x + u_hat * act\n\n        psi_z = (1. - act.pow(2)) * self.w\n        self._cached_logDetJ = torch.log(\n            torch.abs(1 + torch.matmul(psi_z.unsqueeze(-2), u_hat.unsqueeze(-1)).squeeze(-1).squeeze(-1)))\n\n        return y\n\n    def _inverse(self, y):\n        \"\"\"\n        :param y: the output of the bijection\n        :type y: torch.Tensor\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\n        raise KeyError(\"ConditionalPlanar object expected to find key in intermediates cache but didn't\")\n\n    def log_abs_det_jacobian(self, x, y):\n        \"\"\"\n        Calculates the elementwise determinant of the log Jacobian\n        \"\"\"\n        return self._cached_logDetJ\n\n\n@copy_docs_from(ConditionedPlanar)\nclass Planar(ConditionedPlanar, TransformModule):\n    \"\"\"\n    A 'planar' bijective transform with equation,\n\n        :math:`\\\\mathbf{y} = \\\\mathbf{x} + \\\\mathbf{u}\\\\tanh(\\\\mathbf{w}^T\\\\mathbf{z}+b)`\n\n    where :math:`\\\\mathbf{x}` are the inputs, :math:`\\\\mathbf{y}` are the outputs, and the learnable parameters\n    are :math:`b\\\\in\\\\mathbb{R}`, :math:`\\\\mathbf{u}\\\\in\\\\mathbb{R}^D`, :math:`\\\\mathbf{w}\\\\in\\\\mathbb{R}^D` for input\n    dimension :math:`D`. For this to be an invertible transformation, the condition\n    :math:`\\\\mathbf{w}^T\\\\mathbf{u}>-1` is enforced.\n\n    Together with :class:`~pyro.distributions.TransformedDistribution` this provides a way to create richer\n    variational approximations.\n\n    Example usage:\n\n    >>> base_dist = dist.Normal(torch.zeros(10), torch.ones(10))\n    >>> transform = Planar(10)\n    >>> pyro.module(\"my_transform\", transform)  # doctest: +SKIP\n    >>> flow_dist = dist.TransformedDistribution(base_dist, [transform])\n    >>> flow_dist.sample()  # doctest: +SKIP\n        tensor([-0.4071, -0.5030,  0.7924, -0.2366, -0.2387, -0.1417,  0.0868,\n                0.1389, -0.4629,  0.0986])\n\n    The inverse of this transform does not possess an analytical solution and is left unimplemented. However,\n    the inverse is cached when the forward operation is called during sampling, and so samples drawn using\n    the planar transform can be scored.\n\n    :param input_dim: the dimension of the input (and output) variable.\n    :type input_dim: int\n\n    References:\n\n    Variational Inference with Normalizing Flows [arXiv:1505.05770]\n    Danilo Jimenez Rezende, Shakir Mohamed\n\n    \"\"\"\n\n    domain = constraints.real\n    codomain = constraints.real\n    bijective = True\n    event_dim = 1\n\n    def __init__(self, input_dim):\n        super(Planar, self).__init__()\n\n        self.bias = nn.Parameter(torch.Tensor(1,))\n        self.u = nn.Parameter(torch.Tensor(input_dim,))\n        self.w = nn.Parameter(torch.Tensor(input_dim,))\n        self.input_dim = input_dim\n        self.reset_parameters()\n\n    def reset_parameters(self):\n        stdv = 1. / math.sqrt(self.u.size(0))\n        self.w.data.uniform_(-stdv, stdv)\n        self.u.data.uniform_(-stdv, stdv)\n        self.bias.data.zero_()\n\n\n@copy_docs_from(ConditionalTransformModule)\nclass ConditionalPlanar(ConditionalTransformModule):\n    \"\"\"\n    A conditional 'planar' bijective transform using the equation,\n\n        :math:`\\\\mathbf{y} = \\\\mathbf{x} + \\\\mathbf{u}\\\\tanh(\\\\mathbf{w}^T\\\\mathbf{z}+b)`\n\n    where :math:`\\\\mathbf{x}` are the inputs with dimension :math:`D`, :math:`\\\\mathbf{y}` are the outputs,\n    and the pseudo-parameters :math:`b\\\\in\\\\mathbb{R}`, :math:`\\\\mathbf{u}\\\\in\\\\mathbb{R}^D`, and\n    :math:`\\\\mathbf{w}\\\\in\\\\mathbb{R}^D` are the output of a function, e.g. a NN, with input\n    :math:`z\\\\in\\\\mathbb{R}^{M}` representing the context variable to condition on. For this to be an\n    invertible transformation, the condition :math:`\\\\mathbf{w}^T\\\\mathbf{u}>-1` is enforced.\n\n    Together with :class:`~pyro.distributions.ConditionalTransformedDistribution` this provides a way to create\n    richer variational approximations.\n\n    Example usage:\n\n    >>> from pyro.nn.dense_nn import DenseNN\n    >>> input_dim = 10\n    >>> context_dim = 5\n    >>> batch_size = 3\n    >>> base_dist = dist.Normal(torch.zeros(input_dim), torch.ones(input_dim))\n    >>> hypernet = DenseNN(context_dim, [50, 50], param_dims=[1, input_dim, input_dim])\n    >>> transform = ConditionalPlanar(hypernet)\n    >>> z = torch.rand(batch_size, context_dim)\n    >>> flow_dist = dist.ConditionalTransformedDistribution(base_dist, [transform]).condition(z)\n    >>> flow_dist.sample(sample_shape=torch.Size([batch_size])) # doctest: +SKIP\n\n    The inverse of this transform does not possess an analytical solution and is left unimplemented. However,\n    the inverse is cached when the forward operation is called during sampling, and so samples drawn using\n    the planar transform can be scored.\n\n    :param nn: a function inputting the context variable and outputting a triplet of real-valued parameters\n        of dimensions :math:`(1, D, D)`.\n    :type nn: callable\n\n    References:\n    Variational Inference with Normalizing Flows [arXiv:1505.05770]\n    Danilo Jimenez Rezende, Shakir Mohamed\n\n    \"\"\"\n\n    domain = constraints.real\n    codomain = constraints.real\n    bijective = True\n    event_dim = 1\n\n    def __init__(self, nn):\n        super(ConditionalPlanar, self).__init__()\n        self.nn = nn\n\n    def condition(self, context):\n        bias, u, w = self.nn(context)\n        return ConditionedPlanar(bias, u, w)\n\n\ndef planar(input_dim):\n    \"\"\"\n    A helper function to create a :class:`~pyro.distributions.transforms.Planar` object for consistency with other\n    helpers.\n\n    :param input_dim: Dimension of input variable\n    :type input_dim: int\n\n    \"\"\"\n\n    return Planar(input_dim)\n\n\ndef conditional_planar(input_dim, context_dim, hidden_dims=None):\n    \"\"\"\n    A helper function to create a :class:`~pyro.distributions.transforms.ConditionalPlanar` object that takes care of\n    constructing a dense network with the correct input/output dimensions.\n\n    :param input_dim: Dimension of input variable\n    :type input_dim: int\n    :param context_dim: Dimension of context variable\n    :type context_dim: int\n    :param hidden_dims: The desired hidden dimensions of the dense network. Defaults\n        to using [input_dim * 10, input_dim * 10]\n    :type hidden_dims: list[int]\n\n\n    \"\"\"\n\n    if hidden_dims is None:\n        hidden_dims = [input_dim * 10, input_dim * 10]\n    hypernet = DenseNN(context_dim, hidden_dims, param_dims=[1, input_dim, input_dim])\n    return ConditionalPlanar(hypernet)\n", "path": "pyro/distributions/transforms/planar.py"}], "after_files": [{"content": "import math\n\nimport torch\nimport torch.nn as nn\nfrom torch.distributions import constraints\nimport torch.nn.functional as F\n\nfrom torch.distributions import Transform\nfrom pyro.distributions.conditional import ConditionalTransformModule\nfrom pyro.distributions.torch_transform import TransformModule\nfrom pyro.distributions.util import copy_docs_from\nfrom pyro.nn import DenseNN\n\n\n@copy_docs_from(Transform)\nclass ConditionedPlanar(Transform):\n    domain = constraints.real\n    codomain = constraints.real\n    bijective = True\n    event_dim = 1\n\n    def __init__(self, bias=None, u=None, w=None):\n        super(ConditionedPlanar, self).__init__(cache_size=1)\n        self.bias = bias\n        self.u = u\n        self.w = w\n        self._cached_logDetJ = None\n\n    # This method ensures that torch(u_hat, w) > -1, required for invertibility\n    def u_hat(self, u, w):\n        alpha = torch.matmul(u.unsqueeze(-2), w.unsqueeze(-1)).squeeze(-1)\n        a_prime = -1 + F.softplus(alpha)\n        return u + (a_prime - alpha) * w.div(w.pow(2).sum(dim=-1, keepdim=True))\n\n    def _call(self, x):\n        \"\"\"\n        :param x: the input into the bijection\n        :type x: torch.Tensor\n        Invokes the bijection x => y; in the prototypical context of a\n        :class:`~pyro.distributions.TransformedDistribution` `x` is a sample from the base distribution (or the output\n        of a previous transform)\n        \"\"\"\n\n        # x ~ (batch_size, dim_size, 1)\n        # w ~ (batch_size, 1, dim_size)\n        # bias ~ (batch_size, 1)\n        act = torch.tanh(torch.matmul(self.w.unsqueeze(-2), x.unsqueeze(-1)).squeeze(-1) + self.bias)\n        u_hat = self.u_hat(self.u, self.w)\n        y = x + u_hat * act\n\n        psi_z = (1. - act.pow(2)) * self.w\n        self._cached_logDetJ = torch.log(\n            torch.abs(1 + torch.matmul(psi_z.unsqueeze(-2), u_hat.unsqueeze(-1)).squeeze(-1).squeeze(-1)))\n\n        return y\n\n    def _inverse(self, y):\n        \"\"\"\n        :param y: the output of the bijection\n        :type y: torch.Tensor\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\n        raise KeyError(\"ConditionalPlanar object expected to find key in intermediates cache but didn't\")\n\n    def log_abs_det_jacobian(self, x, y):\n        \"\"\"\n        Calculates the elementwise determinant of the log Jacobian\n        \"\"\"\n        return self._cached_logDetJ\n\n\n@copy_docs_from(ConditionedPlanar)\nclass Planar(ConditionedPlanar, TransformModule):\n    \"\"\"\n    A 'planar' bijective transform with equation,\n\n        :math:`\\\\mathbf{y} = \\\\mathbf{x} + \\\\mathbf{u}\\\\tanh(\\\\mathbf{w}^T\\\\mathbf{z}+b)`\n\n    where :math:`\\\\mathbf{x}` are the inputs, :math:`\\\\mathbf{y}` are the outputs, and the learnable parameters\n    are :math:`b\\\\in\\\\mathbb{R}`, :math:`\\\\mathbf{u}\\\\in\\\\mathbb{R}^D`, :math:`\\\\mathbf{w}\\\\in\\\\mathbb{R}^D` for input\n    dimension :math:`D`. For this to be an invertible transformation, the condition\n    :math:`\\\\mathbf{w}^T\\\\mathbf{u}>-1` is enforced.\n\n    Together with :class:`~pyro.distributions.TransformedDistribution` this provides a way to create richer\n    variational approximations.\n\n    Example usage:\n\n    >>> base_dist = dist.Normal(torch.zeros(10), torch.ones(10))\n    >>> transform = Planar(10)\n    >>> pyro.module(\"my_transform\", transform)  # doctest: +SKIP\n    >>> flow_dist = dist.TransformedDistribution(base_dist, [transform])\n    >>> flow_dist.sample()  # doctest: +SKIP\n        tensor([-0.4071, -0.5030,  0.7924, -0.2366, -0.2387, -0.1417,  0.0868,\n                0.1389, -0.4629,  0.0986])\n\n    The inverse of this transform does not possess an analytical solution and is left unimplemented. However,\n    the inverse is cached when the forward operation is called during sampling, and so samples drawn using\n    the planar transform can be scored.\n\n    :param input_dim: the dimension of the input (and output) variable.\n    :type input_dim: int\n\n    References:\n\n    Variational Inference with Normalizing Flows [arXiv:1505.05770]\n    Danilo Jimenez Rezende, Shakir Mohamed\n\n    \"\"\"\n\n    domain = constraints.real\n    codomain = constraints.real\n    bijective = True\n    event_dim = 1\n\n    def __init__(self, input_dim):\n        super(Planar, self).__init__()\n\n        self.bias = nn.Parameter(torch.Tensor(1,))\n        self.u = nn.Parameter(torch.Tensor(input_dim,))\n        self.w = nn.Parameter(torch.Tensor(input_dim,))\n        self.input_dim = input_dim\n        self.reset_parameters()\n\n    def reset_parameters(self):\n        stdv = 1. / math.sqrt(self.u.size(0))\n        self.w.data.uniform_(-stdv, stdv)\n        self.u.data.uniform_(-stdv, stdv)\n        self.bias.data.zero_()\n\n\n@copy_docs_from(ConditionalTransformModule)\nclass ConditionalPlanar(ConditionalTransformModule):\n    \"\"\"\n    A conditional 'planar' bijective transform using the equation,\n\n        :math:`\\\\mathbf{y} = \\\\mathbf{x} + \\\\mathbf{u}\\\\tanh(\\\\mathbf{w}^T\\\\mathbf{z}+b)`\n\n    where :math:`\\\\mathbf{x}` are the inputs with dimension :math:`D`, :math:`\\\\mathbf{y}` are the outputs,\n    and the pseudo-parameters :math:`b\\\\in\\\\mathbb{R}`, :math:`\\\\mathbf{u}\\\\in\\\\mathbb{R}^D`, and\n    :math:`\\\\mathbf{w}\\\\in\\\\mathbb{R}^D` are the output of a function, e.g. a NN, with input\n    :math:`z\\\\in\\\\mathbb{R}^{M}` representing the context variable to condition on. For this to be an\n    invertible transformation, the condition :math:`\\\\mathbf{w}^T\\\\mathbf{u}>-1` is enforced.\n\n    Together with :class:`~pyro.distributions.ConditionalTransformedDistribution` this provides a way to create\n    richer variational approximations.\n\n    Example usage:\n\n    >>> from pyro.nn.dense_nn import DenseNN\n    >>> input_dim = 10\n    >>> context_dim = 5\n    >>> batch_size = 3\n    >>> base_dist = dist.Normal(torch.zeros(input_dim), torch.ones(input_dim))\n    >>> hypernet = DenseNN(context_dim, [50, 50], param_dims=[1, input_dim, input_dim])\n    >>> transform = ConditionalPlanar(hypernet)\n    >>> z = torch.rand(batch_size, context_dim)\n    >>> flow_dist = dist.ConditionalTransformedDistribution(base_dist, [transform]).condition(z)\n    >>> flow_dist.sample(sample_shape=torch.Size([batch_size])) # doctest: +SKIP\n\n    The inverse of this transform does not possess an analytical solution and is left unimplemented. However,\n    the inverse is cached when the forward operation is called during sampling, and so samples drawn using\n    the planar transform can be scored.\n\n    :param nn: a function inputting the context variable and outputting a triplet of real-valued parameters\n        of dimensions :math:`(1, D, D)`.\n    :type nn: callable\n\n    References:\n    Variational Inference with Normalizing Flows [arXiv:1505.05770]\n    Danilo Jimenez Rezende, Shakir Mohamed\n\n    \"\"\"\n\n    domain = constraints.real\n    codomain = constraints.real\n    bijective = True\n    event_dim = 1\n\n    def __init__(self, nn):\n        super(ConditionalPlanar, self).__init__()\n        self.nn = nn\n\n    def condition(self, context):\n        bias, u, w = self.nn(context)\n        return ConditionedPlanar(bias, u, w)\n\n\ndef planar(input_dim):\n    \"\"\"\n    A helper function to create a :class:`~pyro.distributions.transforms.Planar` object for consistency with other\n    helpers.\n\n    :param input_dim: Dimension of input variable\n    :type input_dim: int\n\n    \"\"\"\n\n    return Planar(input_dim)\n\n\ndef conditional_planar(input_dim, context_dim, hidden_dims=None):\n    \"\"\"\n    A helper function to create a :class:`~pyro.distributions.transforms.ConditionalPlanar` object that takes care of\n    constructing a dense network with the correct input/output dimensions.\n\n    :param input_dim: Dimension of input variable\n    :type input_dim: int\n    :param context_dim: Dimension of context variable\n    :type context_dim: int\n    :param hidden_dims: The desired hidden dimensions of the dense network. Defaults\n        to using [input_dim * 10, input_dim * 10]\n    :type hidden_dims: list[int]\n\n\n    \"\"\"\n\n    if hidden_dims is None:\n        hidden_dims = [input_dim * 10, input_dim * 10]\n    hypernet = DenseNN(context_dim, hidden_dims, param_dims=[1, input_dim, input_dim])\n    return ConditionalPlanar(hypernet)\n", "path": "pyro/distributions/transforms/planar.py"}]}