I’ve built a simple generative model to produce an output matrix Y : N x T (the shape/dims). I have a single datum of a matrix D : NxT and I want to fit my generative model parameters so that it will produce samples that very closely match my one data matrix D. I’m hoping the trained generative model parameters will be able to tell me useful, interpretable information about the structure of my experimental data matrix D.
The “forward” pass of my model indeed generates samples that look the way I want, now I just want to run SVI or MCMC to infer the optimal model parameters to fit my data, but alas I get an error.
Here’s my model:
pyro.clear_param_store()
class scNMF:
def __init__(self, data, M=5, tau=15):
#N = # neurons, T := time of recordingM = num motifs, tau = length (time) of motif
#General parameters/input
self.data = data
N, T = data.shape
self.N = N
self.T = T
self.M = M
self.tau = tau
self.tot = M * N * tau
#priors
self.noise_probs = th.Tensor([0.001]).repeat(N*T).reshape(N,T)
self.motif_probs = th.Tensor([1/10]).repeat(self.tot).reshape(M, N, tau)
self.act_probs = th.Tensor([1/T]).repeat(N*T).reshape(N,T)
#pyro params
self.noise_probs_guide = pyro.param('noise_probs', self.noise_probs, constraint=constraints.positive)
self.motif_probs_guide = pyro.param('motif_probs',self.motif_probs, constraint=constraints.positive)
self.act_probs_guide = pyro.param('act_probs', self.act_probs, constraint=constraints.positive)
#output
self.Y = None
def model_(self, motifs, s, noise):
Y_ = th.zeros(self.N,self.T)
for i in range(self.M):
a = motifs[i]
Y_ += thconv(a,s[i])
Y = Y_ + noise
Y /= Y.max(dim=1,keepdim=True)[0].repeat(1,self.T)
Ydist = pyro.sample('Y', dist.Bernoulli(Y))#, obs=self.data)
'''sigma = th.zeros(Y.shape)
sigma[:] = 0.001
Ydist = pyro.sample('Y', dist.Normal(Y,sigma))
self.Y = Ydist'''
return Ydist
def model(self):
#model distributions
noise_ = dist.Bernoulli(self.noise_probs)
motifs_ = dist.Bernoulli(self.motif_probs)
s_ = dist.Bernoulli(self.act_probs)
#sampling
noise = pyro.sample('noise',noise_)
motifs = pyro.sample('motifs',motifs_)
s = pyro.sample('s',s_)
print(noise.shape,motifs.shape,s.shape)
#generate samples
return self.model_(motifs,s,noise)
def guide(self):
#guide distributions
noise_ = dist.Bernoulli(self.noise_probs_guide)
motifs_ = dist.Bernoulli(self.motif_probs_guide)
s_ = dist.Bernoulli(self.act_probs_guide)
#sampling
noise = pyro.sample('noise',noise_)
motifs = pyro.sample('motifs',motifs_)
s = pyro.sample('s',s_)
#generate samples
return self.model_(motifs,s,noise)
def conditioned_model(self):
return pyro.condition(self.model, data={'Y': self.data})
As I said, if I instantiate this object and call the .model()
method it successfully produces samples. But then I try inference (I tried MCMC and SVI), showing MCMC, I get this error:
nuts_kernel = NUTS(scnmf.conditioned_model, adapt_step_size=True)
hmc_posterior = MCMC(nuts_kernel, num_samples=1000, warmup_steps=200).run()
Error:
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-543-2f95e5fde050> in <module>()
1 nuts_kernel = NUTS(scnmf.conditioned_model, adapt_step_size=True)
----> 2 hmc_posterior = MCMC(nuts_kernel, num_samples=1000, warmup_steps=200).run()
~/anaconda3/envs/deeprl/lib/python3.6/site-packages/pyro/infer/abstract_infer.py in run(self, *args, **kwargs)
81 """
82 self._init()
---> 83 for tr, logit in poutine.block(self._traces)(*args, **kwargs):
84 self.exec_traces.append(tr)
85 self.log_weights.append(logit)
~/anaconda3/envs/deeprl/lib/python3.6/site-packages/pyro/infer/mcmc/mcmc.py in _traces(self, *args, **kwargs)
30
31 def _traces(self, *args, **kwargs):
---> 32 self.kernel.setup(*args, **kwargs)
33 trace = self.kernel.initial_trace()
34 self.logger.info("Starting MCMC using kernel - {} ...".format(self.kernel.__class__.__name__))
~/anaconda3/envs/deeprl/lib/python3.6/site-packages/pyro/infer/mcmc/hmc.py in setup(self, *args, **kwargs)
186 if self._automatic_transform_enabled:
187 self.transforms = {}
--> 188 for name, node in sorted(trace.iter_stochastic_nodes(), key=lambda x: x[0]):
189 site_value = node["value"]
190 if node["fn"].support is not constraints.real and self._automatic_transform_enabled:
~/anaconda3/envs/deeprl/lib/python3.6/site-packages/pyro/poutine/trace_struct.py in iter_stochastic_nodes(self)
322 :return: an iterator over stochastic nodes in the trace.
323 """
--> 324 for name, node in self.nodes.items():
325 if node["type"] == "sample" and not node["is_observed"]:
326 yield name, node
AttributeError: 'function' object has no attribute 'items
I’m probably doing something stupid, it’s my first time using Pyro. Any help would be much appreciated!