Not sure if this is a bug or just a short between the chair and the keyboard. =)
I’m trying to use a data container with a GP, and the GP doesn’t seem to be able to handle it.
Here’s a model in which I have a GP as part of a hierarchical model. This is simplified, so it doesn’t mean much in itself, but replicates the error.
n_samples = 40
x_sampled = np.random.uniform(-1, 1, size=(n_samples,1))
t_sampled = np.random.uniform(-1, 1, size=(1,n_samples))
z_observations = np.random.uniform(-1, 1, size=(n_samples,1))
gp_length_scale=.4
with pm.Model() as model:
# Encapsulate data for use in our model
x_sampled_c = pm.Data("x_sampled", x_sampled)
t_sampled_c = pm.Data("t_sampled", t_sampled)
z_observations_c = pm.Data("z_observations", z_observations)
# Define a gaussian process to represent the coefficient
# The mean function will default to 0
cov_func = pm.gp.cov.ExpQuad(1, ls=gp_length_scale)
gp = pm.gp.Latent(cov_func=cov_func)
# Place a GP prior over coefficient
Cx = gp.prior("Cx", X=t_sampled_c)
# Prior for the intercept
b = pm.Normal("b", mu=0, sd=1)
# Prior for noise
noise = pm.Gamma("noise", alpha=2, beta=1)
# Assume a linear functional form defined by sampled coefficient
z = pm.Deterministic("z", Cx*x_sampled_c + b)
# assume that observations are sampled with gaussian noise
z_measured = pm.Normal("z_measured", mu=z, sd=noise, observed=z_observations_c)
The stack trace is:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/usr/local/anaconda3/lib/python3.7/site-packages/pymc3/gp/util.py in infer_shape(X, n_points)
13 try:
---> 14 n_points = np.int(X.shape[0])
15 except TypeError:
TypeError: int() argument must be a string, a bytes-like object or a number, not 'TensorVariable'
During handling of the above exception, another exception occurred:
TypeError Traceback (most recent call last)
<ipython-input-30-aab14f998f0f> in <module>
18
19 # Place a GP prior over coefficient
---> 20 Cx = gp.prior("Cx", X=t_sampled_c)
21
22 # Prior for the intercept
/usr/local/anaconda3/lib/python3.7/site-packages/pymc3/gp/gp.py in prior(self, name, X, reparameterize, **kwargs)
143 """
144
--> 145 f = self._build_prior(name, X, reparameterize, **kwargs)
146 self.X = X
147 self.f = f
/usr/local/anaconda3/lib/python3.7/site-packages/pymc3/gp/gp.py in _build_prior(self, name, X, reparameterize, **kwargs)
110 mu = self.mean_func(X)
111 cov = stabilize(self.cov_func(X))
--> 112 shape = infer_shape(X, kwargs.pop("shape", None))
113 if reparameterize:
114 v = pm.Normal(name + "_rotated_", mu=0.0, sigma=1.0, shape=shape, **kwargs)
/usr/local/anaconda3/lib/python3.7/site-packages/pymc3/gp/util.py in infer_shape(X, n_points)
14 n_points = np.int(X.shape[0])
15 except TypeError:
---> 16 raise TypeError("Cannot infer 'shape', provide as an argument")
17 return n_points
18
TypeError: Cannot infer 'shape', provide as an argument
I’ve tried including a shape parameter in the GP prior:
n_samples = 40
x_sampled = np.random.uniform(-1, 1, size=(n_samples,1))
t_sampled = np.random.uniform(-1, 1, size=(1, n_samples))
z_observations = np.random.uniform(-1, 1, size=(n_samples,1))
gp_length_scale=.4
with pm.Model() as model:
# Encapsulate data for use in our model
x_sampled_c = pm.Data("x_sampled", x_sampled)
t_sampled_c = pm.Data("t_sampled", t_sampled)
z_observations_c = pm.Data("z_observations", z_observations)
# Define a gaussian process to represent the coefficient
# The mean function will default to 0
cov_func = pm.gp.cov.ExpQuad(1, ls=gp_length_scale)
gp = pm.gp.Latent(cov_func=cov_func)
# Place a GP prior over coefficient
Cx = gp.prior("Cx", X=t_sampled_c, shape=t_sampled.shape)
# Prior for the intercept
b = pm.Normal("b", mu=0, sd=1)
# Prior for noise
noise = pm.Gamma("noise", alpha=2, beta=1)
# Assume a linear functional form defined by sampled coefficient
z = pm.Deterministic("z", Cx*x_sampled_c + b)
# assume that observations are sampled with gaussian noise
z_measured = pm.Normal("z_measured", mu=z, sd=noise, observed=z_observations_c)
but this seems to just kick the can down the road to the next point I need to use the GP:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-33-61d6bbd10b21> in <module>
18
19 # Place a GP prior over coefficient
---> 20 Cx = gp.prior("Cx", X=t_sampled_c, shape=t_sampled.shape)
21
22 # Prior for the intercept
/usr/local/anaconda3/lib/python3.7/site-packages/pymc3/gp/gp.py in prior(self, name, X, reparameterize, **kwargs)
143 """
144
--> 145 f = self._build_prior(name, X, reparameterize, **kwargs)
146 self.X = X
147 self.f = f
/usr/local/anaconda3/lib/python3.7/site-packages/pymc3/gp/gp.py in _build_prior(self, name, X, reparameterize, **kwargs)
113 if reparameterize:
114 v = pm.Normal(name + "_rotated_", mu=0.0, sigma=1.0, shape=shape, **kwargs)
--> 115 f = pm.Deterministic(name, mu + cholesky(cov).dot(v))
116 else:
117 f = pm.MvNormal(name, mu=mu, cov=cov, shape=shape, **kwargs)
/usr/local/anaconda3/lib/python3.7/site-packages/theano/tensor/var.py in __add__(self, other)
126 def __add__(self, other):
127 try:
--> 128 return theano.tensor.basic.add(self, other)
129 # We should catch the minimum number of exception here.
130 # Otherwise this will convert error when Theano flags
/usr/local/anaconda3/lib/python3.7/site-packages/theano/gof/op.py in __call__(self, *inputs, **kwargs)
672 thunk.outputs = [storage_map[v] for v in node.outputs]
673
--> 674 required = thunk()
675 assert not required # We provided all inputs
676
/usr/local/anaconda3/lib/python3.7/site-packages/theano/gof/op.py in rval()
860
861 def rval():
--> 862 thunk()
863 for o in node.outputs:
864 compute_map[o][0] = True
/usr/local/anaconda3/lib/python3.7/site-packages/theano/gof/cc.py in __call__(self)
1737 print(self.error_storage, file=sys.stderr)
1738 raise
-> 1739 reraise(exc_type, exc_value, exc_trace)
1740
1741
/usr/local/anaconda3/lib/python3.7/site-packages/six.py in reraise(tp, value, tb)
701 if value.__traceback__ is not tb:
702 raise value.with_traceback(tb)
--> 703 raise value
704 finally:
705 value = None
ValueError: Input dimension mis-match. (input[0].shape[1] = 1, input[1].shape[1] = 40)
Thing is, it works fine without the data container:
n_samples = 40
x_sampled = np.random.uniform(-1, 1, size=(n_samples,1))
t_sampled = np.random.uniform(-1, 1, size=(1,n_samples))
z_observations = np.random.uniform(-1, 1, size=(n_samples,1))
gp_length_scale=.4
with pm.Model() as model:
# Encapsulate data for use in our model
x_sampled_c = x_sampled #pm.Data("x_sampled", x_sampled)
t_sampled_c = t_sampled #pm.Data("t_sampled", t_sampled)
z_observations_c = z_observations #pm.Data("z_observations", z_observations)
# Define a gaussian process to represent the coefficient
# The mean function will default to 0
cov_func = pm.gp.cov.ExpQuad(1, ls=gp_length_scale)
gp = pm.gp.Latent(cov_func=cov_func)
# Place a GP prior over coefficient
Cx = gp.prior("Cx", X=t_sampled_c)
# Prior for the intercept
b = pm.Normal("b", mu=0, sd=1)
# Prior for noise
noise = pm.Gamma("noise", alpha=2, beta=1)
# Assume a linear functional form defined by sampled coefficient
z = pm.Deterministic("z", Cx*x_sampled_c + b)
# assume that observations are sampled with gaussian noise
z_measured = pm.Normal("z_measured", mu=z, sd=noise, observed=z_observations_c)
I just want to be able to predict new points later on…
Am I missing a data alignment/transform somewhere, or is this a bug?
My system:
Python 3.7.6
numpy 1.19.2
theano 1.0.4
pymc3 3.8