GitHub profile

Step 2 - Build the Probabilistic Model

Notation

Step 1 defined the (improper) prior on $\mu_i, \sigma_i^2$ for each component $i$. This step attaches the likelihood, completing the model:

$$z_i \sim \text{Normal}(\mu_i, \sigma_i^2), \qquad i \in {1,2,3}$$

where $z_i$ is the observed vector of that component's scores from Step 9 (Classical PCA). Combining the improper prior with this likelihood is what makes the model proper again — the posterior integrates to 1 even though the prior alone didn't (see Priors — Proper vs improper priors). Each component is modelled independently, so there are three separate (mu, sigma, likelihood) groups in the one model rather than a joint/correlated structure.

The model built here is still unsampled — Step 3 runs MCMC over it to get the posterior.

Python

filename: step2_model.py

import pymc as pm
from dataframes.step9_scores import scores
from bayesian.step1_prior import prior_model

'''
extends the step 1 prior with a Normal likelihood for each component's observed scores:
z_i ~ Normal(mu_i, sigma_i), independently per component.
'''

def build_model(components=("PC1", "PC2", "PC3")):
    df = scores()
    model = prior_model(components)
    with model:
        for component in components:
            pm.Normal(
                f"z_{component}",
                mu=model[f"mu_{component}"],
                sigma=model[f"sigma_{component}"],
                observed=df[component].values,
            )
    return model
reopens the Step 1 prior model and attaches a Normal likelihood per component, observed against that component's actual scores