Ici nous considérons le modèle Bayésien suivant \[
N_i \mid \lambda \stackrel{iid}{\sim} Poisson(\lambda), \qquad i = 1,
\ldots, n,
\] avec la loi a priori \(\lambda \sim
Gamma(\alpha, \beta)\). Attention \(\beta\) est le paramètre
d’intensité (rate).
Un peu de calcul et nous trouvons la loi a posteriori qui est une
\(Gamma(\tilde \alpha, \tilde \beta)\)
avec \[
\tilde \alpha = \alpha + \sum_{i=1}^n N_i, \qquad \tilde \beta = n +
\beta,
\]
Afin de vérifier que nous savons coder un Metropolis–Hastings sur un
vrai modèle statistique on va utiliser la loi cible \[
\pi(\lambda \mid N_1, \ldots, N_n) \propto \lambda^{\alpha +
\sum_{i=1}^n N_i} - 1 - (n + \beta) \log \lambda.
\] Evidemment cela ne sert à rien normalement mais cela a un
intérêt pédagogique.
football <- function(nchain, data, hyper_param,
prop_sd, init = 1){
chain <- rep(NA, nchain + 1)
chain[1] <- init
nobs <- length(data)
acc_rate <- 0
for (i in 1:nchain){
## Générons un candidat (marche alétoire à l'échelle log)
prop <- rlnorm(1, log(chain[i]), prop_sd)
## Calcul de la probabilité d'acceptation
top <- -(nobs + hyper_param[2]) * prop +
(hyper_param[1] + sum(data) - 1) * log(prop)
bottom <- -(nobs + hyper_param[2]) * chain[i] +
(hyper_param[1] + sum(data) - 1) * log(chain[i])
## Attention ici le ratio des noyaux de proposition n'est pas 1
acc_prob <- exp(top - bottom) * prop / chain[i]
## Mise a jour
if (runif(1) < acc_prob){
chain[i+1] <- prop
acc_rate <- acc_rate + 1
} else
chain[i+1] <- chain[i]
}
acc_rate <- acc_rate / nchain
return(list(chain = chain, acc_rate = acc_rate))
}
Essai sur les données.
## Récupération des données depuis le web
url <- "https://www.football-data.co.uk/mmz4281/2324/F1.csv"
data <- read.csv(url)
## Data pre-processing
team <- "Lyon"
idx_home <- which(data$HomeTeam == team)
idx_away <- which(data$AwayTeam == team)
lyon_goals <- c(data[idx_home,"FTHG"],
data[idx_away,"FTAG"])
Choisissons des hyper-paramètres raisonnables (prior
elicitation).
alpha <- 1
beta <- 0.1
prior <- function(x)
dgamma(x, alpha, beta)
plot(prior, from = 0, to = 10,
xlab = expression(lambda),
ylab = "Density", ylim = c(0, 1))
Ici on a choisi des hyper-paramètres afin que la loi a priori soit
pas trop informative.
Testons notre function
nchain <- 50000
hyper_param <- c(alpha, beta)
prop_sd <- 0.35
ans <- football(nchain, lyon_goals, hyper_param,
prop_sd)
chain <- ans$chain
acc_rate <- ans$acc_rate
Le taux d’acceptation de notre chaîne est 0.55166 ce qui est une
bonne valeur pour une chaine en dimension 1. Confirmons cela en
visualisant notre chaine. Pour cela on peut utiliser le package
coda
library(coda)
plot(mcmc(chain))
acf(chain)
Ici pas besoin d’enlever la période de chauffe car l’on semble être
déjà dans le régime stationnaire. De plus l’ACF montre une dépendance
assez limitée. On est donc plus que content.
Regardons avec impatience si ça colle bien la théorie
nobs <- length(lyon_goals)
true_posterior <- function(x)
dgamma(x, alpha + sum(lyon_goals),
nobs + beta)
col <- RColorBrewer::brewer.pal(3, "Set2")
par(mar = c(4, 5, 0.5, 0.5))
plot(density(chain), col = col[1], main = "",
xlab = expression(lambda), lwd = 2)
curve(true_posterior, from = 0, to = 3,
add = TRUE, col = col[2], lwd = 2 )
legend("topright", c("Estimated", "True"),
lty = 1, bty = "n", col = col)
Conclusion on est trop fort !
Passons maintenant à la prédiction. Pour cela nous allons prendre
comme estimateur la moyenne de la loi prédictive. On se rappelle que la
loi prédictive a posteriori est donnée par \[
\pi(x_* \mid N_1, \ldots, N_n) = \int f(x_* \mid N_1, \ldots, N_n,
\lambda) \pi(\lambda \mid N_1, \ldots, N_n) d\lambda,
\] or ici puisque les matchs sont supposés indépendants, cela se
simplifie en \[
\pi(x_* \mid N_1, \ldots, N_n) = \int f(x_* \mid \lambda) \pi(\lambda
\mid N_1, \ldots, N_n) d\lambda.
\] L’espérance \(\mu =
\mathbb{E}(X_*)\) sous cette loi est donc \[
\mu = \sum_{k \geq 0} k \int f(k \mid \lambda) \pi(\lambda \mid N_1,
\ldots, N_n) d\lambda = \int \sum_{k \geq 0} k f(k \mid \lambda)
\pi(\lambda \mid N_1, \ldots, N_n) d\lambda,
\] qui s’écrit comme \[
\mu_N = \mathbb{E}\left\{ \mathbb{E}\left[X_* \mid \lambda
\right]\right\},
\] que l’on peut facilement estimer selon la loi des grands
nombres. Concrètement, en utilisant encore notre chaine de Markov, on
fait
sim <- rpois(length(chain), chain)
sim_factor <- factor(sim, levels = 0:10)
freq <- table(sim_factor) / length(chain)
plot(freq, xlab = "Nombre de buts",
ylab = "Fonction de masse",
col = col[1])
## Estimation et IC
c(mean(sim), quantile(sim, prob = c(0.025, 0.975)))
2.5% 97.5%
1.082778 0.000000 4.000000
Ici on devrait plutôt utiliser comme estimateur le mode de la loi
prédictive qui ici est 1 (mais 0 est très proche aussi). Donc un pari
raisonnable serait de dire que Lyon marque moins de 1.5 buts. Bon il y a
aussi le pari super sur “marque moins de 2.5 buts” mais ça ne devrait
rien rapporter.
LS0tCnRpdGxlOiAiTW9kw6lsaXNhdGlvbiBkdSBub21icmUgZGUgYnV0cyIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKSWNpIG5vdXMgY29uc2lkw6lyb25zIGxlIG1vZMOobGUgQmF5w6lzaWVuIHN1aXZhbnQKJCQKTl9pIFxtaWQgXGxhbWJkYSBcc3RhY2tyZWx7aWlkfXtcc2ltfSBQb2lzc29uKFxsYW1iZGEpLCBccXF1YWQgaSA9IDEsIFxsZG90cywgbiwKJCQKYXZlYyBsYSBsb2kgYSBwcmlvcmkgJFxsYW1iZGEgXHNpbSBHYW1tYShcYWxwaGEsIFxiZXRhKSQuIEF0dGVudGlvbiAkXGJldGEkIGVzdCBsZSBwYXJhbcOodHJlICoqZCdpbnRlbnNpdMOpKiogKHJhdGUpLgoKVW4gcGV1IGRlIGNhbGN1bCBldCBub3VzIHRyb3V2b25zIGxhIGxvaSBhIHBvc3RlcmlvcmkgcXVpIGVzdCB1bmUgJEdhbW1hKFx0aWxkZSBcYWxwaGEsIFx0aWxkZSBcYmV0YSkkIGF2ZWMKJCQKXHRpbGRlIFxhbHBoYSA9IFxhbHBoYSArIFxzdW1fe2k9MX1ebiBOX2ksIFxxcXVhZCBcdGlsZGUgXGJldGEgPSBuICsgXGJldGEsCiQkCgpBZmluIGRlIHbDqXJpZmllciBxdWUgbm91cyBzYXZvbnMgY29kZXIgdW4gTWV0cm9wb2xpcy0tSGFzdGluZ3Mgc3VyIHVuIHZyYWkgbW9kw6hsZSBzdGF0aXN0aXF1ZSBvbiB2YSB1dGlsaXNlciBsYSBsb2kgY2libGUKJCQKXHBpKFxsYW1iZGEgXG1pZCBOXzEsIFxsZG90cywgTl9uKSBccHJvcHRvIFxsYW1iZGFee1xhbHBoYSArIFxzdW1fe2k9MX1ebiBOX2l9IC0gMSAtIChuICsgXGJldGEpIFxsb2cgXGxhbWJkYS4KJCQKRXZpZGVtbWVudCBjZWxhIG5lIHNlcnQgw6AgcmllbiBub3JtYWxlbWVudCBtYWlzIGNlbGEgYSB1biBpbnTDqXLDqnQgcMOpZGFnb2dpcXVlLgoKYGBge3J9CmZvb3RiYWxsIDwtIGZ1bmN0aW9uKG5jaGFpbiwgZGF0YSwgaHlwZXJfcGFyYW0sCiAgICAgICAgICAgICAgICAgICAgIHByb3Bfc2QsIGluaXQgPSAxKXsKICBjaGFpbiA8LSByZXAoTkEsIG5jaGFpbiArIDEpCiAgY2hhaW5bMV0gPC0gaW5pdAogIG5vYnMgPC0gbGVuZ3RoKGRhdGEpCiAgCiAgYWNjX3JhdGUgPC0gMAogIAogIGZvciAoaSBpbiAxOm5jaGFpbil7CiAgICAjIyBHw6luw6lyb25zIHVuIGNhbmRpZGF0IChtYXJjaGUgYWzDqXRvaXJlIMOgIGwnw6ljaGVsbGUgbG9nKQogICAgcHJvcCA8LSBybG5vcm0oMSwgbG9nKGNoYWluW2ldKSwgcHJvcF9zZCkKICAgIAogICAgIyMgQ2FsY3VsIGRlIGxhIHByb2JhYmlsaXTDqSBkJ2FjY2VwdGF0aW9uCiAgICB0b3AgPC0gLShub2JzICsgaHlwZXJfcGFyYW1bMl0pICogcHJvcCArCiAgICAgIChoeXBlcl9wYXJhbVsxXSArIHN1bShkYXRhKSAtIDEpICogbG9nKHByb3ApCiAgICBib3R0b20gPC0gLShub2JzICsgaHlwZXJfcGFyYW1bMl0pICogY2hhaW5baV0gKwogICAgICAoaHlwZXJfcGFyYW1bMV0gKyBzdW0oZGF0YSkgLSAxKSAqIGxvZyhjaGFpbltpXSkKICAgIAogICAgIyMgQXR0ZW50aW9uIGljaSBsZSByYXRpbyBkZXMgbm95YXV4IGRlIHByb3Bvc2l0aW9uIG4nZXN0IHBhcyAxCiAgICBhY2NfcHJvYiA8LSBleHAodG9wIC0gYm90dG9tKSAqIHByb3AgLyBjaGFpbltpXQogICAgCiAgICAjIyBNaXNlIGEgam91cgogICAgaWYgKHJ1bmlmKDEpIDwgYWNjX3Byb2IpewogICAgICBjaGFpbltpKzFdIDwtIHByb3AKICAgICAgYWNjX3JhdGUgPC0gYWNjX3JhdGUgKyAxCiAgICB9IGVsc2UKICAgICAgY2hhaW5baSsxXSA8LSBjaGFpbltpXQogIH0KICAKICBhY2NfcmF0ZSA8LSBhY2NfcmF0ZSAvIG5jaGFpbgogIHJldHVybihsaXN0KGNoYWluID0gY2hhaW4sIGFjY19yYXRlID0gYWNjX3JhdGUpKQp9CmBgYAoKRXNzYWkgc3VyIGxlcyBkb25uw6llcy4KYGBge3J9CiMjIFLDqWN1cMOpcmF0aW9uIGRlcyBkb25uw6llcyBkZXB1aXMgbGUgd2ViCnVybCA8LSAiaHR0cHM6Ly93d3cuZm9vdGJhbGwtZGF0YS5jby51ay9tbXo0MjgxLzIzMjQvRjEuY3N2IgpkYXRhIDwtIHJlYWQuY3N2KHVybCkKCiMjIERhdGEgcHJlLXByb2Nlc3NpbmcKdGVhbSA8LSAiTHlvbiIKaWR4X2hvbWUgPC0gd2hpY2goZGF0YSRIb21lVGVhbSA9PSB0ZWFtKQppZHhfYXdheSA8LSB3aGljaChkYXRhJEF3YXlUZWFtID09IHRlYW0pCgpseW9uX2dvYWxzIDwtIGMoZGF0YVtpZHhfaG9tZSwiRlRIRyJdLAogICAgICAgICAgICAgICAgZGF0YVtpZHhfYXdheSwiRlRBRyJdKQpgYGAKCkNob2lzaXNzb25zIGRlcyBoeXBlci1wYXJhbcOodHJlcyByYWlzb25uYWJsZXMgKHByaW9yIGVsaWNpdGF0aW9uKS4KYGBge3J9CmFscGhhIDwtIDEKYmV0YSA8LSAwLjEKcHJpb3IgPC0gZnVuY3Rpb24oeCkKICBkZ2FtbWEoeCwgYWxwaGEsIGJldGEpCgpwbG90KHByaW9yLCBmcm9tID0gMCwgdG8gPSAxMCwKICAgICB4bGFiID0gZXhwcmVzc2lvbihsYW1iZGEpLAogICAgIHlsYWIgPSAiRGVuc2l0eSIsIHlsaW0gPSBjKDAsIDEpKQpgYGAKCkljaSBvbiBhIGNob2lzaSBkZXMgaHlwZXItcGFyYW3DqHRyZXMgYWZpbiBxdWUgbGEgbG9pIGEgcHJpb3JpIHNvaXQgcGFzIHRyb3AgaW5mb3JtYXRpdmUuCgpUZXN0b25zIG5vdHJlIGZ1bmN0aW9uCmBgYHtyfQpuY2hhaW4gPC0gNTAwMDAKaHlwZXJfcGFyYW0gPC0gYyhhbHBoYSwgYmV0YSkKcHJvcF9zZCA8LSAwLjM1CmFucyA8LSBmb290YmFsbChuY2hhaW4sIGx5b25fZ29hbHMsIGh5cGVyX3BhcmFtLAogICAgICAgICAgICAgICAgcHJvcF9zZCkKCmNoYWluIDwtIGFucyRjaGFpbgphY2NfcmF0ZSA8LSBhbnMkYWNjX3JhdGUKYGBgCgpMZSB0YXV4IGQnYWNjZXB0YXRpb24gZGUgbm90cmUgY2hhw65uZSBlc3QgYHIgYWNjX3JhdGVgIGNlIHF1aSBlc3QgdW5lIGJvbm5lIHZhbGV1ciBwb3VyIHVuZSBjaGFpbmUgZW4gZGltZW5zaW9uIDEuIENvbmZpcm1vbnMgY2VsYSBlbiB2aXN1YWxpc2FudCBub3RyZSBjaGFpbmUuIFBvdXIgY2VsYSBvbiBwZXV0IHV0aWxpc2VyIGxlIHBhY2thZ2UgKmNvZGEqCmBgYHtyfQpsaWJyYXJ5KGNvZGEpCnBsb3QobWNtYyhjaGFpbikpCmFjZihjaGFpbikKYGBgCgpJY2kgcGFzIGJlc29pbiBkJ2VubGV2ZXIgbGEgcMOpcmlvZGUgZGUgY2hhdWZmZSBjYXIgbCdvbiBzZW1ibGUgw6p0cmUgZMOpasOgIGRhbnMgbGUgcsOpZ2ltZSBzdGF0aW9ubmFpcmUuIERlIHBsdXMgbCdBQ0YgbW9udHJlIHVuZSBkw6lwZW5kYW5jZSBhc3NleiBsaW1pdMOpZS4gT24gZXN0IGRvbmMgcGx1cyBxdWUgY29udGVudC4KClJlZ2FyZG9ucyBhdmVjIGltcGF0aWVuY2Ugc2kgw6dhIGNvbGxlIGJpZW4gbGEgdGjDqW9yaWUKYGBge3J9Cm5vYnMgPC0gbGVuZ3RoKGx5b25fZ29hbHMpCnRydWVfcG9zdGVyaW9yIDwtIGZ1bmN0aW9uKHgpCiAgZGdhbW1hKHgsIGFscGhhICsgc3VtKGx5b25fZ29hbHMpLAogICAgICAgICBub2JzICsgYmV0YSkKCmNvbCA8LSBSQ29sb3JCcmV3ZXI6OmJyZXdlci5wYWwoMywgIlNldDIiKQpwYXIobWFyID0gYyg0LCA1LCAwLjUsIDAuNSkpCnBsb3QoZGVuc2l0eShjaGFpbiksIGNvbCA9IGNvbFsxXSwgbWFpbiA9ICIiLAogICAgIHhsYWIgPSBleHByZXNzaW9uKGxhbWJkYSksIGx3ZCA9IDIpCmN1cnZlKHRydWVfcG9zdGVyaW9yLCBmcm9tID0gMCwgdG8gPSAzLAogICAgICBhZGQgPSBUUlVFLCBjb2wgPSBjb2xbMl0sIGx3ZCA9IDIgKQpsZWdlbmQoInRvcHJpZ2h0IiwgYygiRXN0aW1hdGVkIiwgIlRydWUiKSwKICAgICAgIGx0eSA9IDEsIGJ0eSA9ICJuIiwgY29sID0gY29sKQpgYGAKCkNvbmNsdXNpb24gb24gZXN0IHRyb3AgZm9ydCAhCgpQYXNzb25zIG1haW50ZW5hbnQgw6AgbGEgcHLDqWRpY3Rpb24uIFBvdXIgY2VsYSBub3VzIGFsbG9ucyBwcmVuZHJlIGNvbW1lIGVzdGltYXRldXIgbGEgbW95ZW5uZSBkZSBsYSBsb2kgcHLDqWRpY3RpdmUuIE9uIHNlIHJhcHBlbGxlIHF1ZSBsYSBsb2kgcHLDqWRpY3RpdmUgYSBwb3N0ZXJpb3JpIGVzdCBkb25uw6llIHBhcgokJApccGkoeF8qIFxtaWQgTl8xLCBcbGRvdHMsIE5fbikgPSBcaW50IGYoeF8qIFxtaWQgTl8xLCBcbGRvdHMsIE5fbiwgXGxhbWJkYSkgXHBpKFxsYW1iZGEgXG1pZCBOXzEsIFxsZG90cywgTl9uKSBkXGxhbWJkYSwKJCQKb3IgaWNpIHB1aXNxdWUgbGVzIG1hdGNocyBzb250IHN1cHBvc8OpcyBpbmTDqXBlbmRhbnRzLCBjZWxhIHNlIHNpbXBsaWZpZSBlbgokJApccGkoeF8qIFxtaWQgTl8xLCBcbGRvdHMsIE5fbikgPSBcaW50IGYoeF8qIFxtaWQgXGxhbWJkYSkgXHBpKFxsYW1iZGEgXG1pZCBOXzEsIFxsZG90cywgTl9uKSBkXGxhbWJkYS4KJCQKTCdlc3DDqXJhbmNlICRcbXUgPSBcbWF0aGJie0V9KFhfKikkIHNvdXMgY2V0dGUgbG9pIGVzdCBkb25jCiQkClxtdSA9IFxzdW1fe2sgXGdlcSAwfSBrIFxpbnQgZihrIFxtaWQgXGxhbWJkYSkgXHBpKFxsYW1iZGEgXG1pZCBOXzEsIFxsZG90cywgTl9uKSBkXGxhbWJkYSA9IFxpbnQgXHN1bV97ayBcZ2VxIDB9IGsgIGYoayBcbWlkIFxsYW1iZGEpIFxwaShcbGFtYmRhIFxtaWQgTl8xLCBcbGRvdHMsIE5fbikgZFxsYW1iZGEsCiQkCnF1aSBzJ8OpY3JpdCBjb21tZQokJApcbXVfTiA9IFxtYXRoYmJ7RX1cbGVmdFx7IFxtYXRoYmJ7RX1cbGVmdFtYXyogXG1pZCBcbGFtYmRhIFxyaWdodF1ccmlnaHRcfSwKJCQKcXVlIGwnb24gcGV1dCBmYWNpbGVtZW50IGVzdGltZXIgc2Vsb24gbGEgbG9pIGRlcyBncmFuZHMgbm9tYnJlcy4gQ29uY3LDqHRlbWVudCwgZW4gdXRpbGlzYW50IGVuY29yZSBub3RyZSBjaGFpbmUgZGUgTWFya292LCBvbiBmYWl0CmBgYHtyfQpzaW0gPC0gcnBvaXMobGVuZ3RoKGNoYWluKSwgY2hhaW4pCnNpbV9mYWN0b3IgPC0gZmFjdG9yKHNpbSwgbGV2ZWxzID0gMDoxMCkKZnJlcSA8LSB0YWJsZShzaW1fZmFjdG9yKSAvIGxlbmd0aChjaGFpbikKcGxvdChmcmVxLCB4bGFiID0gIk5vbWJyZSBkZSBidXRzIiwKICAgICB5bGFiID0gIkZvbmN0aW9uIGRlIG1hc3NlIiwKICAgICBjb2wgPSBjb2xbMV0pCgoKCiMjIEVzdGltYXRpb24gZXQgSUMKYyhtZWFuKHNpbSksIHF1YW50aWxlKHNpbSwgcHJvYiA9IGMoMC4wMjUsIDAuOTc1KSkpCgpgYGAKSWNpIG9uIGRldnJhaXQgcGx1dMO0dCB1dGlsaXNlciBjb21tZSBlc3RpbWF0ZXVyIGxlIG1vZGUgZGUgbGEgbG9pIHByw6lkaWN0aXZlIHF1aSBpY2kgZXN0IDEgKG1haXMgMCBlc3QgdHLDqHMgcHJvY2hlIGF1c3NpKS4gRG9uYyB1biBwYXJpIHJhaXNvbm5hYmxlIHNlcmFpdCBkZSBkaXJlIHF1ZSBgciB0ZWFtYCBtYXJxdWUgbW9pbnMgZGUgMS41IGJ1dHMuIEJvbiBpbCB5IGEgYXVzc2kgbGUgcGFyaSBzdXBlciBzdXIgIm1hcnF1ZSBtb2lucyBkZSAyLjUgYnV0cyIgbWFpcyDDp2EgbmUgZGV2cmFpdCByaWVuIHJhcHBvcnRlci4K