import os
import logging
import pandas as pd
import numpy as np
import seaborn as sns
import arviz as az
import matplotlib.pyplot as plt
from IPython import get_ipython
import warnings
="ignore", category=FutureWarning)
warnings.simplefilter(actionimport cmdstanpy
cmdstanpy.utils.get_logger().setLevel(logging.ERROR)from cmdstanpy import CmdStanModel
import pingouin as pg
from sklearn.linear_model import LinearRegression
72 Bellezza, sesso e potere
Prerequisiti
- Leggere Regression and Other Stories (Gelman et al., 2020).
- Prestare particolare attenzione al Capitolo 9, “Prediction and Bayesian Inference”, che discute in dettaglio l’utilità di includere informazioni aggiuntive nel modello utilizzando una distribuzione a priori.
Concetti e Competenze Chiave
Preparazione del Notebook
int = sum(map(ord, "beauty_sex_power"))
seed: = np.random.default_rng(seed=seed)
rng: np.random.Generator ="colorblind")
sns.set_theme(palette"arviz-darkgrid")
az.style.use(%config InlineBackend.figure_format = "retina"
# Get the home directory
= os.path.expanduser("~")
home_directory # Construct the path to the Quarto project directory
= os.path.join(home_directory, "_repositories", "psicometria")
project_directory
def standardize(series):
"""Standardize a pandas series with n degrees of freedom"""
return (series - series.mean()) / series.std(ddof=0)
Introduzione
Gelman & Weakliem (2009) discutono le difficoltà statistiche che emergono nell’analizzare piccoli campioni di dati. Uno degli studi che esaminano è quello di Kanazawa (2007), in cui l’autore propone che i genitori con tratti ereditari che aumentano il successo riproduttivo maschile più di quello femminile in un dato ambiente avranno una proporzione di figli maschi superiore al previsto. Al contrario, i genitori con tratti ereditari che favoriscono maggiormente il successo riproduttivo femminile rispetto a quello maschile avranno una proporzione di figlie superiore al previsto. Kanazawa identifica l’attrattività fisica come un tratto ereditario che aumenta significativamente il successo riproduttivo delle figlie più di quello dei figli. Pertanto, prevede che i genitori fisicamente attraenti avranno una proporzione di figlie superiore al previsto. Inoltre, se l’attrattività è ereditaria e i genitori attraenti hanno più figlie, nel corso dell’evoluzione le donne dovrebbero diventare gradualmente più attraenti degli uomini. Secondo Kanazawa (2007), l’analisi dei dati della National Longitudinal Study of Adolescent Health (Add Health) conferma entrambe queste ipotesi: gli individui molto attraenti hanno il 26% di probabilità in meno di avere un figlio maschio, e le donne risultano significativamente più attraenti degli uomini nel campione rappresentativo americano.
72.1 Lo Studio di @Kanazawa (2007)
L’attrattività è stata misurata su una scala da 1 a 5 (“molto poco attraente” a “molto attraente”). Gelman & Weakliem (2009) si concentrano su questo risultato riportato da Kanazawa (2007):
If I dichotomize the respondents into those who are rated ‘‘very attractive’’ and everyone else, the difference in the proportion of sons between the two groups (0.52 vs. 0.44) is statistically significant (t = 2.44, p \(\geq\) 0.05). There appears to be something qualitatively different about respondents rated “very attractive”.
In altre parole:
- il 56% dei figli di genitori nella categoria 5 erano femmine;
- il 48% dei figli di genitori nelle categorie da 1 a 4 erano femmine.
Questo risultato risulta ‘statisticamente significativo’.
Gelman & Weakliem (2009) fanno notare come la dicotomizzazione proposta da Kanazawa (2007) sia arbitraria. La variabile indipendente ha 5 livelli e sono possibili quattro confronti tra i livelli. Kanazawa (2007) ha scelto arbitariamente uno di questi confronti.
È dunque più naturale esaminare tutti i dati mediante un modello di regressione. I dati sono i seguenti:
= np.arange(-2, 3, 1)
x = np.array([50, 44, 50, 47, 56])
y = pd.DataFrame({"x": x, "y": y})
sexratio sexratio
x | y | |
---|---|---|
0 | -2 | 50 |
1 | -1 | 44 |
2 | 0 | 50 |
3 | 1 | 47 |
4 | 2 | 56 |
Per comodità, le cinque categorie della \(X\) sono state ricodificate in modo tale che la categoria centrale abbia valore 0.
# Calcolo dei prior Bayesiani
= 0
theta_hat_prior = 0.25
se_prior = 8
theta_hat_data = 3
se_data = (theta_hat_prior / se_prior**2 + theta_hat_data / se_data**2) / (
theta_hat_bayes 1 / se_prior**2 + 1 / se_data**2
)= np.sqrt(1 / (1 / se_prior**2 + 1 / se_data**2)) se_bayes
# Regressione lineare con Pingouin
= pg.linear_regression(sexratio[["x"]], sexratio["y"])
fm round(4) fm.
names | coef | se | T | pval | r2 | adj_r2 | CI[2.5%] | CI[97.5%] | |
---|---|---|---|---|---|---|---|---|---|
0 | Intercept | 49.4 | 1.9442 | 25.4086 | 0.0001 | 0.2841 | 0.0455 | 43.2126 | 55.5874 |
1 | x | 1.5 | 1.3748 | 1.0911 | 0.3550 | 0.2841 | 0.0455 | -2.8751 | 5.8751 |
# Plot dei dati e della linea di regressione
=(10, 5))
plt.figure(figsize
1, 2, 1)
plt.subplot("o", markersize=5)
plt.plot(x, y, 43, 57)
plt.ylim("Attractiveness of parent")
plt.xlabel("Percentage of girl babies")
plt.ylabel("Data on beauty and sex ratio")
plt.title(45, 50, 55], [f"{i}%" for i in [45, 50, 55]])
plt.yticks([
1, 2, 2)
plt.subplot("o", markersize=5)
plt.plot(x, y, 43, 57)
plt.ylim("Attractiveness of parent")
plt.xlabel("Percentage of girl babies")
plt.ylabel("Data and least-squares regression line")
plt.title(45, 50, 55], [f"{i}%" for i in [45, 50, 55]])
plt.yticks([= fm["coef"].values[1], fm["coef"].values[0]
slope, intercept + slope * x, "-")
plt.plot(x, intercept
plt.text(1,
52.2,
f"y = {intercept:.1f} + {slope:.1f} x\n(Std err of slope is {fm['se'].values[1]:.1f})",
)
plt.tight_layout() plt.show()
/var/folders/s7/z86r4t9j6yx376cm120nln6w0000gn/T/ipykernel_32471/3465279703.py:27: UserWarning: The figure layout has changed to tight
plt.tight_layout()
72.2 Analisi Bayesiana con Prior Non Informativi
Mediante l’utilizzo di prior non informativi ci possiamo aspettare che l’analisi bayesisana sostanzialmente replichi il risultato dell’analisi frequentista.
Sistemiamo i dati nel formato richiesto da Stan.
= {"N": len(sexratio), "x": sexratio["x"].values, "y": sexratio["y"].values}
stan_data stan_data
{'N': 5, 'x': array([-2, -1, 0, 1, 2]), 'y': array([50, 44, 50, 47, 56])}
Formuliamo il modello di regressione bivariata utilizzando prior non informativi.
= os.path.join(project_directory, 'stan', 'sex_ratio.stan')
stan_file = CmdStanModel(stan_file=stan_file)
model1 print(model1.code())
data {
int<lower=0> N;
vector[N] x;
vector[N] y;
}
parameters {
real alpha;
real beta;
real<lower=0> sigma;
}
model {
y ~ normal(alpha + beta * x, sigma);
}
Eseguiamo il campionamento MCMC.
= model1.sample(
fit1 =stan_data,
data=2_000,
iter_warmup=2_000,
iter_sampling=123,
seed=False,
show_progress=False
show_console )
Esaminiamo le distribuzioni a posteriori dei parametri.
=(["alpha", "beta", "sigma"]), hdi_prob=0.94) az.summary(fit1, var_names
mean | sd | hdi_3% | hdi_97% | mcse_mean | mcse_sd | ess_bulk | ess_tail | r_hat | |
---|---|---|---|---|---|---|---|---|---|
alpha | 49.512 | 6.228 | 39.278 | 58.560 | 0.103 | 0.081 | 3384.0 | 1640.0 | 1.0 |
beta | 1.543 | 4.567 | -5.028 | 8.927 | 0.088 | 0.104 | 3851.0 | 1381.0 | 1.0 |
sigma | 9.406 | 10.183 | 2.109 | 22.019 | 0.357 | 0.252 | 912.0 | 1188.0 | 1.0 |
La soluzione ottenuta replica quella del metodo dei minimi quadrati. In entrambi i casi, sia l’intervallo di confidenza che l’intervallo credibile includono lo zero, il che indica che l’attrattività dei genitori non sembra avere un effetto credibile sulla proporzione di nascite femminili. Tuttavia, nonostante la notevole incertezza, l’analisi mostra che il coefficiente \(\beta\) è positivo e pari a 1.5.
72.3 Analisi Bayesiana con Prior Debolmente Informativi
Gelman & Weakliem (2009) propongono l’uso di prior debolmente informativi nel contesto di un’analisi sulla relazione tra l’attrattività dei genitori e la percentuale di nascite femminili. Questi prior sono basati su informazioni precedenti e su ipotesi ragionevoli relative al problema studiato. Ecco come vengono definiti i due principali coefficienti del modello di regressione:
- Intercetta (a):
- La variabile intercetta rappresenta la percentuale di nascite femminili quando l’attrattività dei genitori è nella media.
- Gelman & Weakliem (2009) utilizzano una distribuzione normale centrata a 48.8 con una deviazione standard di 0.5. Questo indica che, sulla base dei dati esistenti, ci si aspetta che la percentuale di nascite femminili per genitori con attrattività media sia circa il 48.8%, con un margine di variazione di ±0.5%. Questo valore è scelto perché, in generale, la percentuale di nascite femminili è stabile tra il 48.5% e il 49%.
- Coefficiente angolare (b):
- Il coefficiente angolare rappresenta l’effetto dell’attrattività dei genitori sulla percentuale di nascite femminili.
- Gelman & Weakliem (2009) scelgono una distribuzione normale centrata a 0 con una deviazione standard di 0.2. Questo riflette l’assenza di una forte convinzione a priori che l’attrattività sia correlata in modo robusto con il sesso del neonato. Il valore della deviazione standard di 0.2 indica che ci si aspetta che il coefficiente possa variare tra -0.2 e 0.2. Dato che la variabile predittiva (l’attrattività) ha un intervallo di 4 punti, questa scelta implica che l’effetto massimo atteso dell’attrattività sulla percentuale di nascite femminili sia di ±0.8 punti percentuali, confrontando la categoria di attrattività più alta con quella più bassa.
Questi prior debolmente informativi aiutano a guidare l’analisi, integrando l’informazione che la percentuale di nascite femminili è molto stabile e suggerendo che, se c’è un effetto dell’attrattività, esso è probabile che sia piuttosto piccolo.
Compiliamo e stampiamo il modello che include i prior debolmente informativi.
= os.path.join(project_directory, "stan", "sex_ratio_informative_prior.stan")
stan_file_ip = CmdStanModel(stan_file=stan_file_ip)
model2 print(model2.code())
data {
int<lower=0> N;
vector[N] x;
vector[N] y;
}
parameters {
real alpha;
real beta;
real<lower=0> sigma;
}
model {
alpha ~ normal(48.8, 0.5);
beta ~ normal(0, 0.2);
y ~ normal(alpha + beta * x, sigma);
}
Eseguiamo il campionamento.
= model2.sample(
fit2 =stan_data,
data=2_000,
iter_warmup=2_000,
iter_sampling=123,
seed=False,
show_progress=False,
show_console )
Esaminiamo le distribuzioni a posteriori.
=(["alpha", "beta", "sigma"]), hdi_prob=0.94) az.summary(fit2, var_names
mean | sd | hdi_3% | hdi_97% | mcse_mean | mcse_sd | ess_bulk | ess_tail | r_hat | |
---|---|---|---|---|---|---|---|---|---|
alpha | 48.828 | 0.487 | 47.879 | 49.715 | 0.006 | 0.004 | 6402.0 | 5373.0 | 1.0 |
beta | 0.028 | 0.201 | -0.352 | 0.395 | 0.002 | 0.002 | 7334.0 | 5464.0 | 1.0 |
sigma | 5.696 | 3.290 | 2.294 | 10.366 | 0.060 | 0.049 | 6248.0 | 3964.0 | 1.0 |
Si osserva che, quando vengono utilizzati prior debolmente informativi, l’effetto dell’attrattività dei genitori risulta sostanzialmente nullo.
I due grafici seguenti mostrano la variabilità della retta di regressione stimata dal modello bayesiano sia con prior non informativi che con prior informativi. Nel caso di prior non informativi, nonostante l’ampia variabilità nella stima della pendenza della retta di regressione, emerge una lieve coerenza che suggerisce una relazione positiva molto debole. Al contrario, con prior debolmente informativi, la pendenza della retta di regressione stimata dal modello bayesiano risulta chiaramente piatta, eliminando qualsiasi incertezza.
# Analisi dei risultati
= [fit1, fit2]
fit_bayes
for k, fit in enumerate(fit_bayes):
= fit.draws_pd()
sims = sims.median()
coef_est = 1.483 * np.median(np.abs(sims["beta"] - coef_est["beta"]))
b_se
=(10, 5))
plt.figure(figsize
# Plot delle simulazioni posteriori
1, 2, 1)
plt.subplot("alpha"], sims["beta"], "o", markersize=2)
plt.plot(sims["Intercept, a")
plt.xlabel("Slope, b")
plt.ylabel(
plt.title(f"Posterior simulations under {'default prior' if k == 0 else 'informative prior'}"
)
# Plot dei dati grezzi e della linea di regressione
1, 2, 2)
plt.subplot("o", color="blue", markersize=5)
plt.plot(x, y, 43, 57)
plt.ylim("Attractiveness of parent")
plt.xlabel("Percentage of girl babies")
plt.ylabel(
plt.title(f"{'Least-squares regression line and\nposterior uncertainty given default prior' if k == 0 else 'Bayes estimated regression line and\nposterior uncertainty given informative prior'}"
)45, 50, 55], [f"{i}%" for i in [45, 50, 55]])
plt.yticks([
# Aggiunta delle linee di regressione dai campioni posteriori
for i in range(100):
plt.plot("alpha"].iloc[i] + sims["beta"].iloc[i] * x, color="gray", lw=0.5
x, sims[
)
# Linea di regressione basata sui valori mediani stimati
"alpha"] + coef_est["beta"] * x, color="black", lw=2)
plt.plot(x, coef_est[
plt.tight_layout() plt.show()
/var/folders/s7/z86r4t9j6yx376cm120nln6w0000gn/T/ipykernel_32471/2498333150.py:40: UserWarning: The figure layout has changed to tight
plt.tight_layout()
/var/folders/s7/z86r4t9j6yx376cm120nln6w0000gn/T/ipykernel_32471/2498333150.py:40: UserWarning: The figure layout has changed to tight
plt.tight_layout()
72.4 Considerazioni Conclusive
L’analisi delle relazioni tra bellezza e proporzione di nascite femminili nei campioni di piccole dimensioni mette in luce l’importanza di considerare la potenza statistica e l’uso di prior informativi nei modelli statistici. In studi con campioni ridotti, c’è un rischio notevole di ottenere risultati che, pur sembrando indicativi di un effetto, sono in realtà frutto del caso e non rappresentano una realtà sottostante. Questo fenomeno è reso più insidioso dall’attuale pratiche delle pubblicazioni scientifiche che molto spesso selezionano gli studi da pubblicare solo sulla presenza di effetti “statisticamente significativi”, e che tendono a favorire e amplificare risultati che sembrano innovativi o controintuitivi, anche quando questi risultati non sono supportati da solide evidenze statistiche.
Gelman & Weakliem (2009) sottolineano che l’uso di prior debolmente informativi, come illustrato nel presente modello bayesiano, rappresenta un approccio metodologico che può aiutare a contrastare queste problematiche. Ad esempio, quando vengono applicati prior debolmente informativi, l’effetto dell’attrattività dei genitori sulla proporzione di nascite femminili emerge come sostanzialmente nullo, evidenziando come l’apparente effetto osservato in modelli meno rigorosi possa essere semplicemente un artefatto dovuto a fluttuazioni casuali. Questo non solo rende più chiaro il vero segnale presente nei dati, ma aiuta anche a prevenire l’interpretazione errata dei risultati.
Inoltre, Gelman & Weakliem (2009) mettono in evidenza come le limitazioni legate alla potenza statistica siano spesso ignorate nella pratica di ricerca, portando a stime degli effetti sovrastimate, specialmente in studi con campioni piccoli – si veda il Capitolo 119. Questo problema è accentuato dalla tendenza della comunità scientifica a privilegiare risultati sensazionali, che possono far emergere ipotesi infondate come verità accettate. L’esempio del rapporto tra bellezza e sex-ratio mostra come questi errori possano condurre a una distorsione della conoscenza scientifica, con conseguenze che vanno ben oltre l’ambito accademico.
Per contrastare questi problemi, è essenziale promuovere una maggiore trasparenza nel processo di revisione e pubblicazione scientifica, così come un uso più diffuso di metodi statistici che incorporino la conoscenza a priori e considerino la potenza statistica in tutte le fasi del processo di ricerca. Solo attraverso un approccio più rigoroso e critico possiamo sperare di ridurre la diffusione di affermazioni infondate e migliorare la qualità complessiva della ricerca in psicologia e nelle scienze sociali. In questo contesto, l’adozione di modelli bayesiani con priori informativi rappresenta un passo avanti importante, permettendo ai ricercatori di evitare trappole comuni e di fornire risultati che riflettono più accuratamente la realtà dei fenomeni studiati.
Informazioni sull’Ambiente di Sviluppo
%load_ext watermark
%watermark -n -u -v -iv -m
Last updated: Tue Jul 30 2024
Python implementation: CPython
Python version : 3.12.4
IPython version : 8.26.0
Compiler : Clang 16.0.6
OS : Darwin
Release : 23.6.0
Machine : arm64
Processor : arm
CPU cores : 8
Architecture: 64bit
matplotlib: 3.9.1
arviz : 0.18.0
cmdstanpy : 1.2.4
pandas : 2.2.2
logging : 0.5.1.2
pingouin : 0.5.4
seaborn : 0.13.2
numpy : 1.26.4