Skip to content

Commit 95694a4

Browse files
author
Larry Dong
committed
Merge remote-tracking branch 'upstream/v4'
2 parents db789ec + 2e7d042 commit 95694a4

24 files changed

+902
-218
lines changed

RELEASE-NOTES.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,18 @@
88

99
### New Features
1010
- The `CAR` distribution has been added to allow for use of conditional autoregressions which often are used in spatial and network models.
11+
- The dimensionality of model variables can now be parametrized through either of `shape`, `dims` or `size` (see [#4625](https://github.com/pymc-devs/pymc3/pull/4625)):
12+
- With `shape` the length of dimensions must be given numerically or as scalar Aesara `Variables`. A `SpecifyShape` `Op` is added automatically unless `Ellipsis` is used. Using `shape` restricts the model variable to the exact length and re-sizing is no longer possible.
13+
- `dims` keeps model variables re-sizeable (for example through `pm.Data`) and leads to well defined coordinates in `InferenceData` objects.
14+
- The `size` kwarg creates new dimensions in addition to what is implied by RV parameters.
15+
- An `Ellipsis` (`...`) in the last position of `shape` or `dims` can be used as short-hand notation for implied dimensions.
1116
- ...
1217

1318
### Maintenance
1419
- Remove float128 dtype support (see [#4514](https://github.com/pymc-devs/pymc3/pull/4514)).
1520
- Logp method of `Uniform` and `DiscreteUniform` no longer depends on `pymc3.distributions.dist_math.bound` for proper evaluation (see [#4541](https://github.com/pymc-devs/pymc3/pull/4541)).
21+
- `Model.RV_dims` and `Model.coords` are now read-only properties. To modify the `coords` dictionary use `Model.add_coord`. Also `dims` or coordinate values that are `None` will be auto-completed (see [#4625](https://github.com/pymc-devs/pymc3/pull/4625)).
22+
- The length of `dims` in the model is now tracked symbolically through `Model.dim_lengths` (see [#4625](https://github.com/pymc-devs/pymc3/pull/4625)).
1623
- ...
1724

1825
## PyMC3 3.11.2 (14 March 2021)

pymc3/aesaraf.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
from aesara.sandbox.rng_mrg import MRG_RandomStream as RandomStream
4646
from aesara.tensor.elemwise import Elemwise
4747
from aesara.tensor.random.op import RandomVariable
48+
from aesara.tensor.shape import SpecifyShape
4849
from aesara.tensor.sharedvar import SharedVariable
4950
from aesara.tensor.subtensor import AdvancedIncSubtensor, AdvancedIncSubtensor1
5051
from aesara.tensor.var import TensorVariable
@@ -146,6 +147,8 @@ def change_rv_size(
146147
Expand the existing size by `new_size`.
147148
148149
"""
150+
if isinstance(rv_var.owner.op, SpecifyShape):
151+
rv_var = rv_var.owner.inputs[0]
149152
rv_node = rv_var.owner
150153
rng, size, dtype, *dist_params = rv_node.inputs
151154
name = rv_var.name

pymc3/backends/arviz.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -162,10 +162,7 @@ def __init__(
162162
self.trace = trace
163163

164164
# this permits us to get the model from command-line argument or from with model:
165-
try:
166-
self.model = modelcontext(model)
167-
except TypeError:
168-
self.model = None
165+
self.model = modelcontext(model)
169166

170167
self.attrs = None
171168
if trace is not None:
@@ -223,10 +220,14 @@ def arbitrary_element(dct: Dict[Any, np.ndarray]) -> np.ndarray:
223220
self.coords = {} if coords is None else coords
224221
if hasattr(self.model, "coords"):
225222
self.coords = {**self.model.coords, **self.coords}
223+
self.coords = {key: value for key, value in self.coords.items() if value is not None}
226224

227225
self.dims = {} if dims is None else dims
228226
if hasattr(self.model, "RV_dims"):
229-
model_dims = {k: list(v) for k, v in self.model.RV_dims.items()}
227+
model_dims = {
228+
var_name: [dim for dim in dims if dim is not None]
229+
for var_name, dims in self.model.RV_dims.items()
230+
}
230231
self.dims = {**model_dims, **self.dims}
231232

232233
self.density_dist_obs = density_dist_obs

pymc3/backends/base.py

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -61,17 +61,7 @@ def __init__(self, name, model=None, vars=None, test_point=None):
6161
model = modelcontext(model)
6262
self.model = model
6363
if vars is None:
64-
vars = []
65-
for v in model.unobserved_RVs:
66-
var = getattr(v.tag, "value_var", v)
67-
transform = getattr(var.tag, "transform", None)
68-
if transform:
69-
# We need to create and add an un-transformed version of
70-
# each transformed variable
71-
untrans_var = transform.backward(v, var)
72-
untrans_var.name = v.name
73-
vars.append(untrans_var)
74-
vars.append(var)
64+
vars = model.unobserved_value_vars
7565

7666
self.vars = vars
7767
self.varnames = [var.name for var in vars]

pymc3/data.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import urllib.request
2020

2121
from copy import copy
22-
from typing import Any, Dict, List
22+
from typing import Any, Dict, List, Sequence
2323

2424
import aesara
2525
import aesara.tensor as at
@@ -502,7 +502,7 @@ class Data:
502502
>>> for data_vals in observed_data:
503503
... with model:
504504
... # Switch out the observed dataset
505-
... pm.set_data({'data': data_vals})
505+
... model.set_data('data', data_vals)
506506
... traces.append(pm.sample())
507507
508508
To set the value of the data container variable, check out
@@ -543,6 +543,11 @@ def __new__(self, name, value, *, dims=None, export_index_as_coords=False):
543543

544544
if export_index_as_coords:
545545
model.add_coords(coords)
546+
elif dims:
547+
# Register new dimension lengths
548+
for d, dname in enumerate(dims):
549+
if not dname in model.dim_lengths:
550+
model.add_coord(dname, values=None, length=shared_object.shape[d])
546551

547552
# To draw the node for this variable in the graphviz Digraph we need
548553
# its shape.
@@ -562,7 +567,7 @@ def __new__(self, name, value, *, dims=None, export_index_as_coords=False):
562567
return shared_object
563568

564569
@staticmethod
565-
def set_coords(model, value, dims=None):
570+
def set_coords(model, value, dims=None) -> Dict[str, Sequence]:
566571
coords = {}
567572

568573
# If value is a df or a series, we interpret the index as coords:

pymc3/distributions/continuous.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -171,11 +171,6 @@ def get_tau_sigma(tau=None, sigma=None):
171171
else:
172172
sigma = tau ** -0.5
173173

174-
# cast tau and sigma to float in a way that works for both np.arrays
175-
# and pure python
176-
tau = 1.0 * tau
177-
sigma = 1.0 * sigma
178-
179174
return floatX(tau), floatX(sigma)
180175

181176

0 commit comments

Comments
 (0)