sbi icon indicating copy to clipboard operation
sbi copied to clipboard

The size of tensor mismatch when sample from posterior

Open john-wang1015 opened this issue 1 year ago • 2 comments

Hi,

I am trying to sample from the posterior. I have 4 parameters in my model, when I try to sample from posterior, I got this error

---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
Input In [14], in <cell line: 1>()
----> 1 posterior_samples = posterior.sample((10000,),x = x_0)

File ~\anaconda3\lib\site-packages\sbi\inference\posteriors\mcmc_posterior.py:236, in MCMCPosterior.sample(self, sample_shape, x, method, thin, warmup_steps, num_chains, init_strategy, init_strategy_num_candidates, mcmc_parameters, mcmc_method, sample_with, num_workers, show_progress_bars)
    231 init_strategy_num_candidates = _maybe_use_dict_entry(
    232     init_strategy_num_candidates, "init_strategy_num_candidates", m_p
    233 )
    234 self.potential_ = self._prepare_potential(method)  # type: ignore
--> 236 initial_params = self._get_initial_params(
    237     init_strategy, num_chains, num_workers, show_progress_bars  # type: ignore
    238 )
    239 num_samples = torch.Size(sample_shape).numel()
    241 track_gradients = method in ("hmc", "nuts")

File ~\anaconda3\lib\site-packages\sbi\inference\posteriors\mcmc_posterior.py:363, in MCMCPosterior._get_initial_params(self, init_strategy, num_chains, num_workers, show_progress_bars)
    356         initial_params = torch.cat(
    357             Parallel(n_jobs=num_workers)(
    358                 delayed(seeded_init_fn)(seed) for seed in seeds
    359             )
    360         )
    361 else:
    362     initial_params = torch.cat(
--> 363         [init_fn() for _ in range(num_chains)]  # type: ignore
    364     )
    366 return initial_params

File ~\anaconda3\lib\site-packages\sbi\inference\posteriors\mcmc_posterior.py:363, in <listcomp>(.0)
    356         initial_params = torch.cat(
    357             Parallel(n_jobs=num_workers)(
    358                 delayed(seeded_init_fn)(seed) for seed in seeds
    359             )
    360         )
    361 else:
    362     initial_params = torch.cat(
--> 363         [init_fn() for _ in range(num_chains)]  # type: ignore
    364     )
    366 return initial_params

File ~\anaconda3\lib\site-packages\sbi\inference\posteriors\mcmc_posterior.py:301, in MCMCPosterior._build_mcmc_init_fn.<locals>.<lambda>()
    299     return lambda: proposal_init(proposal, transform=transform, **kwargs)
    300 elif init_strategy == "sir":
--> 301     return lambda: sir(proposal, potential_fn, transform=transform, **kwargs)
    302 elif init_strategy == "latest_sample":
    303     latest_sample = IterateParameters(self._mcmc_init_params, **kwargs)

File ~\anaconda3\lib\site-packages\sbi\samplers\mcmc\init_strategy.py:67, in sir(proposal, potential_fn, transform, sir_num_batches, sir_batch_size, **kwargs)
     65     batch_draws = proposal.sample((sir_batch_size,)).detach()
     66     init_param_candidates.append(batch_draws)
---> 67     log_weights.append(potential_fn(batch_draws).detach())
     68 log_weights = torch.cat(log_weights)
     69 init_param_candidates = torch.cat(init_param_candidates)

File ~\anaconda3\lib\site-packages\sbi\inference\potentials\likelihood_based_potential.py:94, in LikelihoodBasedPotential.__call__(self, theta, track_gradients)
     86 # Calculate likelihood over trials and in one batch.
     87 log_likelihood_trial_sum = _log_likelihoods_over_trials(
     88     x=self.x_o,
     89     theta=theta.to(self.device),
     90     net=self.likelihood_estimator,
     91     track_gradients=track_gradients,
     92 )
---> 94 return log_likelihood_trial_sum + self.prior.log_prob(theta)

RuntimeError: The size of tensor a (1000) must match the size of tensor b (4) at non-singleton dimension 1

I know tensor a is like a number of particels. However, I am not sure why there is tensor b (4). Can you give me some help to debug this one? I have personalized prior and .sample() and .log_prob() work correctly for such prior.

john-wang1015 avatar Aug 06 '22 16:08 john-wang1015

the log_prob() in my prior like this

def log_prob(self, values):
       log_probs = torch.ones(values.size()[0],values.size()[1])
       length = values.size()[0]
       if self.return_numpy:
           values = torch.as_tensor(values)
       
       for i in range(values.size()[0]):
           log_probs[i][0] = self.dist2.log_prob(values[i][0])
           log_probs[i][1] = self.dist3.log_prob(values[i][1])
           log_probs[i][2] = torch.log(torch.exp(torch.log(self.loc1*torch.ones(1)) + 1/(torch.sqrt(2*math.pi*torch.ones(1)))*torch.exp(-0.5 * (values[i][2]-0)**2)))
           log_probs[i][3] = torch.log(torch.exp(torch.log(self.loc2*torch.ones(1)) + 1/(torch.sqrt(2*math.pi*torch.ones(1)))*torch.exp(-0.5 * (values[i][3]-0)**2)))
       
       return log_probs.numpy() if self.return_numpy else log_probs

it return size as (n,4). I undestand I need a size (n,), but the reshape method is not working here

john-wang1015 avatar Aug 06 '22 17:08 john-wang1015

I think you need to sum the log probs over the second dimension: your prior has four independent dimensions, but the final log prob should be the joint over all dimensions, e.g., return log_probs.sum(1)

btw, I am wondering why you are converting back and forth between torch and numpy? within sbi it should be fine to only use torch. We added the numpy option for cases where the prior only returns numpy, but yours seems to be sampling form torch distributions.

janfb avatar Aug 07 '22 07:08 janfb

Closing this due to inactivity. Feel free to re-open if concrete questions come up.

michaeldeistler avatar Sep 09 '22 15:09 michaeldeistler