[Python] Bayesian Approach

Discussão em 'Python' iniciado por Stack, Maio 23, 2025.

  1. Stack

    Stack Membro Participativo

    I have only this problem statement as of now that I will get Annual Values from 2010-2024 (from a reliable source) and monthly values will be derived via proxy (separate model). Since, the monthly values for a particular year will not add up to the Annual value of that year. So i have to devise a method where the monthly values gets adjusted and adds up to the Annual Value.

    For this, I did a Bayesian Analysis as below.

    Created synthetic Yearly Data from 2010-2024 (Ay);y is 2010-2024 My Assumption is that True_Monthly_Value should be equal to (Ay)/12 Created an observed monthly value and added some noise to it.

    # Add noise to the monthly value
    np.random.seed(42)
    noise = np.random.normal(0,10, size = len(df_monthly))*emphasized text*
    df_monthly['Monthly_Observed']= df_monthly['Monthly_Value']+np.abs(noise)


    After this I wanted my model to try to remove the noise and estimate something closer to the correct data which is (Ay)/12. I did the following code:

    #PyMC model
    with pm.Model() as model:

    #Setting the PRIOR for Noise from the Monthly_Observed Value
    #Because I created the noise thats why this is my PRIOR
    #“I believe the noise is positive (via HalfNormal), and probably close to 5, but let the data update that belief.”
    sigma = pm.HalfNormal("sigma", sigma=5)


    #PRIOR distribution over the latent monthly values
    #You're saying:
    #“I believe the true values are centered around the noisy monthly_observed values, but they could vary with σ = 10.”
    #Monthly_observed is used in this because its the belief that my actual monthly values are closer to the Monthly_Observed values
    #with a standard deviation of 10
    T_raw = pm.Normal("T_raw", mu=monthly_observed, sigma=10, shape=(n_years, n_months))

    #Enforce Constraint i.e. sum of each month in a year = Annual Total
    T_total = T_raw.sum(axis=1, keepdims=True)
    scaling_factor = annual_total[:, None] / T_total
    T = pm.Deterministic("T", T_raw * scaling_factor) ---#check this

    # Likelihood: observed noisy monthly values // How probable the observed data is given a specific choice of model parameters
    #here’s my noisy observed data monthly_observed. I think these are normally distributed around the true (unknown) monthly values T,
    #and the amount of noise in that distribution is described by sigma
    M_obs = pm.Normal("M_obs", mu=T, sigma=sigma, observed=monthly_observed)

    # Inference
    # TRACE comprises the POSTERIOR Samples of the model's parameters
    # TUNE is the Burn-in samples
    # Burn-in samples are essential for getting accurate Bayesian inference using MCMC
    trace = pm.sample(2000, tune=1000, target_accept=0.95, return_inferencedata=True, random_seed=42)

    #Extract the de-noised monthly values that the Bayesian Model learned
    # Posterior mean of T (shape: n_years x 12)
    T_posterior_mean = trace.posterior["T"].mean(dim=("chain", "draw")).values


    My Results from the posterior are very good. The r_hat is equivalent to 1.0 and the 96% HDI is also narrow.

    Now my doubt is in the model I am using a soft constraint:

    #Enforce Constraint i.e. sum of each month in a year = Annual Total
    T_total = T_raw.sum(axis=1, keepdims=True)
    scaling_factor = annual_total[:, None] / T_total
    T = pm.Deterministic("T", T_raw * scaling_factor) ---#check this


    I think this is scaling my data and giving me the good results. DO you think its okk to use a soft constraint or I should do something differently. I really need some advise

    Continue reading...

Compartilhe esta Página