0

We have a bayesian logistic regression model in python using a pyro and sklearn environment.
The model is trained and tested with a dataset that contains categorical and continuous variables. The code starts by preprocessing the dataset (using the LabelEncoder for categorical variables).

Here is the code then defines the function:

import torch
import torch
import pyro
import pyro.distributions as dist
from pyro.infer import MCMC, NUTS

""" Model definition """
def bayesian_logistic_regression(X_categorical, X_continuous):
    num_categories = X_categorical.shape[1]
    num_predictors = num_categories + X_continuous.shape[1]
    
    alpha = pyro.sample("alpha", dist.Normal(alpha_prior_mean, alpha_prior_scale))
    beta_categorical = pyro.sample("beta_categorical",
                                   dist.Normal(beta_categorical_prior_means,
                                               beta_categorical_prior_scales))
    beta_continuous = pyro.sample("beta_continuous",
                          dist.Normal(beta_continuous_prior_means.unsqueeze(1),
                                      beta_continuous_prior_scales.unsqueeze(1)))
    
    logits = alpha 
            + torch.matmul(X_categorical, beta_categorical) 
            + torch.matmul(X_continuous, beta_continuous)

    probs = torch.sigmoid(logits)
    beta_categorical = beta_categorical.to(torch.float)
    beta_continuous = beta_continuous.to(torch.float)
    y_obs = pyro.sample("y", dist.Bernoulli(probs=probs), obs=y) #dist.Multinomial(100, probs)

    # Inference
    nuts_kernel = NUTS(bayesian_logistic_regression)
    mcmc = MCMC(nuts_kernel, num_samples=50, warmup_steps=10, num_chains=1)
    mcmc.run(X_categorical, X_continuous)

    # Get posterior samples
    posterior_samples = mcmc.get_samples()
    alpha_samples = posterior_samples['alpha']
    beta_categorical_samples = posterior_samples['beta_categorical']
    beta_continuous_samples = posterior_samples['beta_continuous']

    return alpha_samples, beta_categorical_samples, 
            beta_continuous_samples, posterior_samples
""" Priors """
alpha_prior_mean = torch.tensor(0.0)
alpha_prior_scale = torch.tensor(1.0)
beta_categorical_prior_means = torch.tensor([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0])
beta_categorical_prior_scales = torch.tensor([1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0])

# Fix the data types and dimensions of beta_continuous_prior_means and beta_continuous_prior_scales
beta_continuous_prior_means = torch.tensor([0.0, 0.0, 0.0, 0.0], 
dtype=torch.float32)
beta_continuous_prior_scales = torch.tensor([1.0, 1.0, 1.0, 1.0], 
dtype=torch.float32)

""" Run model """
alpha_samples, beta_categorical_samples, 
beta_continuous_samples, posterior_samples  = bayesian_logistic_regression(y_train, X_categorical, X_continuous)   

The objective of this model is to predict the response variable, but also to serve as a tool that can be easily modified for additional or changes in the input parameters.

The results of this model returns predictions all = 0 (for the binary response variable) which is incorrect based on the samples. My current assumption is that there is an issue with the way I have set up the model definition and using the NUTS MCMC sampling methods.

My question is: have I incorrectly set up this model or is there a better methodology to coding a Bayesian logistic regression?

I have attempted to use this methodology on the Iris dataset. I have updated the code to work with the input parameters used in previous papers.
However, my code still predicts 0 for the response variable on this dataset as well. We once again know this to be false since we have results for the input parameters used in the model.

Myron_Ben4
  • 432
  • 4
  • 13
jon0003
  • 1
  • 2

0 Answers0