Skip to content

Default to pm.Data(mutable=False), deprecate MLDA and bump to v4.1.0 #5944

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jul 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pymc/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
# limitations under the License.

# pylint: disable=wildcard-import
__version__ = "4.0.1"
__version__ = "4.1.0"

import logging
import multiprocessing as mp
Expand Down
18 changes: 8 additions & 10 deletions pymc/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -661,16 +661,14 @@ def Data(
arr = convert_observed_data(value)

if mutable is None:
major, minor = (int(v) for v in pm.__version__.split(".")[:2])
mutable = major == 4 and minor < 1
if mutable:
warnings.warn(
"The `mutable` kwarg was not specified. Currently it defaults to `pm.Data(mutable=True)`,"
" which is equivalent to using `pm.MutableData()`."
" In v4.1.0 the default will change to `pm.Data(mutable=False)`, equivalent to `pm.ConstantData`."
" Set `pm.Data(..., mutable=False/True)`, or use `pm.ConstantData`/`pm.MutableData`.",
FutureWarning,
)
warnings.warn(
"The `mutable` kwarg was not specified. Before v4.1.0 it defaulted to `pm.Data(mutable=True)`,"
" which is equivalent to using `pm.MutableData()`."
" In v4.1.0 the default changed to `pm.Data(mutable=False)`, equivalent to `pm.ConstantData`."
" Use `pm.ConstantData`/`pm.MutableData` or pass `pm.Data(..., mutable=False/True)` to avoid this warning.",
UserWarning,
)
mutable = False
if mutable:
x = aesara.shared(arr, name, **kwargs)
else:
Expand Down
19 changes: 12 additions & 7 deletions pymc/step_methods/mlda.py
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ class MLDA(ArrayStepShared):
sum of the quantity of interest after sampling. In order to use
variance reduction, the user needs to do the following when defining
the PyMC model (also demonstrated in the example notebook):
- Include a `pm.Data()` variable with the name `Q` in the
- Include a `pm.MutableData()` variable with the name `Q` in the
model description of all levels.
- Use an Aesara Op to calculate the forward model (or the
combination of a forward model and a likelihood). This Op
Expand All @@ -286,7 +286,7 @@ class MLDA(ArrayStepShared):
definition at all levels except the finest one, the
extra variables mu_B and Sigma_B, which will capture
the bias between different levels. All these variables
should be instantiated using the pm.Data method.
should be instantiated using the pm.MutableData method.
- Use an Aesara Op to define the forward model (and
optionally the likelihood) for all levels. The Op needs
to store the result of each forward model calculation
Expand Down Expand Up @@ -365,6 +365,11 @@ def __init__(
adaptive_error_model: bool = False,
**kwargs,
) -> None:
warnings.warn(
"The MLDA stepper will be migrated to the pymc-experimental project!"
" See https://github.com/pymc-devs/pymc/issues/5942",
DeprecationWarning,
)

# this variable is used to identify MLDA objects which are
# not in the finest level (i.e. child MLDA objects)
Expand Down Expand Up @@ -401,12 +406,12 @@ def __init__(
"the variable in the model definition"
"for variance reduction to work or"
"for storing the fine Q."
"Use pm.Data() to define it."
"Use pm.MutableData() to define it."
)
if not isinstance(self.model.Q, TensorSharedVariable):
raise TypeError(
"The variable 'Q' in the model definition is not of type "
"'TensorSharedVariable'. Use pm.Data() to define the"
"'TensorSharedVariable'. Use pm.MutableData() to define the"
"variable."
)

Expand All @@ -427,15 +432,15 @@ def __init__(
"variable 'mu_B'. You need to include"
"the variable in the model definition"
"for adaptive error model to work."
"Use pm.Data() to define it."
"Use pm.MutableData() to define it."
)
if not hasattr(self.model_below, "Sigma_B"):
raise AttributeError(
"Model below in hierarchy does not contain"
"variable 'Sigma_B'. You need to include"
"the variable in the model definition"
"for adaptive error model to work."
"Use pm.Data() to define it."
"Use pm.MutableData() to define it."
)
if not (
isinstance(self.model_below.mu_B, TensorSharedVariable)
Expand All @@ -444,7 +449,7 @@ def __init__(
raise TypeError(
"At least one of the variables 'mu_B' and 'Sigma_B' "
"in the definition of the below model is not of type "
"'TensorSharedVariable'. Use pm.Data() to define those "
"'TensorSharedVariable'. Use pm.MutableData() to define those "
"variables."
)

Expand Down
5 changes: 2 additions & 3 deletions pymc/tests/test_data_container.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import pytest

from aesara import shared
from aesara.compile.sharedvalue import SharedVariable
from aesara.tensor import TensorConstant
from aesara.tensor.var import TensorVariable

Expand Down Expand Up @@ -431,9 +430,9 @@ def test_data_kwargs(self):

def test_data_mutable_default_warning(self):
with pm.Model():
with pytest.warns(FutureWarning, match="`mutable` kwarg was not specified"):
with pytest.warns(UserWarning, match="`mutable` kwarg was not specified"):
data = pm.Data("x", [1, 2, 3])
assert isinstance(data, SharedVariable)
assert isinstance(data, TensorConstant)
pass


Expand Down
30 changes: 15 additions & 15 deletions pymc/tests/test_step.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
import pymc as pm

from pymc.aesaraf import floatX
from pymc.data import Data
from pymc.data import Data, MutableData
from pymc.distributions import (
Bernoulli,
Beta,
Expand Down Expand Up @@ -1109,7 +1109,7 @@ def perform(self, node, inputs, outputs):
intercept = inputs[0][0]
x_coeff = inputs[0][1]

temp = intercept + x_coeff * x + self.pymc_model.bias.get_value()
temp = intercept + x_coeff * x + self.pymc_model.bias.data
with self.pymc_model:
set_data({"model_output": temp})
outputs[0][0] = np.array(temp)
Expand All @@ -1120,9 +1120,9 @@ def perform(self, node, inputs, outputs):

with Model() as coarse_model_0:
bias = Data("bias", 3.5 * np.ones(y.shape, dtype=p))
mu_B = Data("mu_B", -1.3 * np.ones(y.shape, dtype=p))
Sigma_B = Data("Sigma_B", np.zeros((y.shape[0], y.shape[0]), dtype=p))
model_output = Data("model_output", np.zeros(y.shape, dtype=p))
mu_B = MutableData("mu_B", -1.3 * np.ones(y.shape, dtype=p))
Sigma_B = MutableData("Sigma_B", np.zeros((y.shape[0], y.shape[0]), dtype=p))
model_output = MutableData("model_output", np.zeros(y.shape, dtype=p))
Sigma_e = Data("Sigma_e", s)

# Define priors
Expand All @@ -1140,9 +1140,9 @@ def perform(self, node, inputs, outputs):

with Model() as coarse_model_1:
bias = Data("bias", 2.2 * np.ones(y.shape, dtype=p))
mu_B = Data("mu_B", -2.2 * np.ones(y.shape, dtype=p))
Sigma_B = Data("Sigma_B", np.zeros((y.shape[0], y.shape[0]), dtype=p))
model_output = Data("model_output", np.zeros(y.shape, dtype=p))
mu_B = MutableData("mu_B", -2.2 * np.ones(y.shape, dtype=p))
Sigma_B = MutableData("Sigma_B", np.zeros((y.shape[0], y.shape[0]), dtype=p))
model_output = MutableData("model_output", np.zeros(y.shape, dtype=p))
Sigma_e = Data("Sigma_e", s)

# Define priors
Expand All @@ -1161,7 +1161,7 @@ def perform(self, node, inputs, outputs):
# fine model and inference
with Model() as model:
bias = Data("bias", np.zeros(y.shape, dtype=p))
model_output = Data("model_output", np.zeros(y.shape, dtype=p))
model_output = MutableData("model_output", np.zeros(y.shape, dtype=p))
Sigma_e = Data("Sigma_e", s)

# Define priors
Expand Down Expand Up @@ -1268,9 +1268,9 @@ def perform(self, node, inputs, outputs):

with Model() as coarse_model_0:
if aesara.config.floatX == "float32":
Q = Data("Q", np.float32(0.0))
Q = MutableData("Q", np.float32(0.0))
else:
Q = Data("Q", np.float64(0.0))
Q = MutableData("Q", np.float64(0.0))

# Define priors
intercept = Normal("Intercept", true_intercept, sigma=1)
Expand All @@ -1285,9 +1285,9 @@ def perform(self, node, inputs, outputs):

with Model() as coarse_model_1:
if aesara.config.floatX == "float32":
Q = Data("Q", np.float32(0.0))
Q = MutableData("Q", np.float32(0.0))
else:
Q = Data("Q", np.float64(0.0))
Q = MutableData("Q", np.float64(0.0))

# Define priors
intercept = Normal("Intercept", true_intercept, sigma=1)
Expand All @@ -1302,9 +1302,9 @@ def perform(self, node, inputs, outputs):

with Model() as model:
if aesara.config.floatX == "float32":
Q = Data("Q", np.float32(0.0))
Q = MutableData("Q", np.float32(0.0))
else:
Q = Data("Q", np.float64(0.0))
Q = MutableData("Q", np.float64(0.0))

# Define priors
intercept = Normal("Intercept", true_intercept, sigma=1)
Expand Down