8
$\begingroup$

I am currently in the process of implementing a model for soccer result prediction in JAGS. Actually, I have implemented several, but I have reached my most difficult challenge yet: A model described by Rue & Salvesen in their paper "Prediction and retrospective analysis of soccer matches in a league". Their model uses a mixed model for truncating a Poisson distribution conditioned on attack / defense strength after 5 goals. They have also adapted a law from Dixon & Coles (1997) to increase the probability of 0-0 and 1-1 results in low-scoring games.

My problem is as follows, I am trying to implement the mixed-model: $$ \pi_{g1}(x_{A,B},y_{A,B}|\lambda_{A,B}^{(x)},\lambda_{A,B}^{(y)}) = \kappa(x_{A,B},y_{A,B}|\lambda_{A,B}^{(x)},\lambda_{A,B}^{(y)})Po(x_{A,B}|\lambda_{A,B}^{(x)})Po(y_{A,B}|\lambda_{A,B}^{(y)}) $$ Where $x_{A,B}$ denotes the number of goals scored by the home team in the game between teams A and B, and $log(\lambda_{A,B}^{(x)})$ denotes the teams' strength. I have tried to implement these two laws in JAGS by using the zeros-ones trick, but with no luck so far (error: illegal parent values). My JAGS model so far:

data {
    C <- 10000

    for(i in 1:noGames) {
        zeros[i] <- 0
    }

    homeGoalAvg <- 0.395
    awayGoalAvg <- 0.098

    rho <- 0.1
}

model {

    ### Time model - Brownian motion
    tau ~ dgamma(10, 0.1)
    precision ~ dgamma(0.1, 1)

    for(t in 1:noTeams) {
        attack[t, 1] ~ dnorm(0, precision)
        defence[t, 1] ~ dnorm(0, precision)

        for(s in 2:noTimeslices) {
            attack[t, s] ~ dnorm(attack[t, (s-1)], (tau * precision) / 
                                         (abs(days[t,s]-days[t,s-1])))
            defence[t, s] ~ dnorm(defence[t, (s-1)], (tau * precision) / 
                                          (abs(days[t,s]-days[t,s-1])))
        }
    }

    ### Goal model
    gamma ~ dunif(0, 0.1)

    for(i in 1:noGames) {

        delta[i]            <-  (
                                attack[team[i, 1], timeslice[i, 1]] + 
                                defence[team[i, 1], timeslice[i, 1]] -
                                attack[team[i, 2], timeslice[i, 2]] - 
                                defence[team[i, 2], timeslice[i, 2]]
                            ) / 2

        log(homeLambda[i])  <-  (
                                    homeGoalAvg + 
                                    (
                                        attack[team[i, 1], timeslice[i, 1]] - 
                                        defence[team[i, 2], timeslice[i, 2]] -
                                        gamma * delta[i]
                                    )
                                )

        log(awayLambda[i])  <-  (
                                    awayGoalAvg + 
                                    (
                                        attack[team[i, 2], timeslice[i, 2]] - 
                                        defence[team[i, 1], timeslice[i, 1]] +
                                        gamma * delta[i]
                                    )
                                )

        goalsScored[i, 1] ~ dpois( homeLambda[i] )
        goalsScored[i, 2] ~ dpois( awayLambda[i] )

        is0X[i] <- ifelse(goalsScored[i, 1]==0, 1, 0)
        isX0[i] <- ifelse(goalsScored[i, 2]==0, 1, 0)
        is1X[i] <- ifelse(goalsScored[i, 1]==1, 1, 0)
        isX1[i] <- ifelse(goalsScored[i, 2]==1, 1, 0)
        is00[i] <- is0X[i] * isX0[i]
        is01[i] <- is0X[i] * isX1[i]
        is10[i] <- is1X[i] * isX0[i]
        is11[i] <- is1X[i] * isX1[i]

        kappa[i] <- (
                        is00[i] * ( 1 + (homeLambda[i] * awayLambda[i] * rho) ) + 
                        is01[i] * ( 1 - (homeLambda[i] * rho                ) ) + 
                        is10[i] * ( 1 - (awayLambda[i] * rho                ) ) + 
                        is11[i] * ( 1 + rho                                     ) + 
                        1 -       ( is00[i] + is01[i] + is10[i] + is11[i]     )
                    )

        # This does not work!
        zeros[i] ~ dpois(-log(kappa[i]) + C)
    }

}
$\endgroup$
  • 3
    $\begingroup$ I think Marat is close - there could be something with the ifelse. I would recommend to simplify your model to smallest version that doesn't work! This could show you the way. $\endgroup$ – Curious Dec 7 '13 at 9:22
  • 2
    $\begingroup$ You could try Stan instead - it enables you to do actual programming rather then "tricks" stuff. Also @Curious is right - try to simplify your model: start with very basic one and make it a little bit more complicated one step at a time until it stops working. $\endgroup$ – Tim Feb 25 '15 at 11:51
0
$\begingroup$

Sometimes ifelse doesn't work. Instead

is0X[i] <- ifelse(goalsScored[i, 1]==0, 1, 0)

you should try

is0X[i] <- goalsScored[i, 1]==0

goalsScored[i, 1]==0 returns 1 if True and 0 if False

$\endgroup$
  • $\begingroup$ Thanks man, but that didn't do it for me. Still haven't found a solution to this. $\endgroup$ – thomrand Jan 19 '13 at 12:57
0
$\begingroup$

I do not think you can define zeros[i] ~ dpois(-log(kappa[i]) + C) inside of the model construction.

Try to revise the code to be zeros ~ dpois(-log(kappa[i]) + C) (take out of '[i]').

After defining the model, you re-define the data at zeors:

data$zero=0

Try if this works.

Refer to The zero-crossings trick for JAGS: Finding roots stochastically for more information.

$\endgroup$

Not the answer you're looking for? Browse other questions tagged or ask your own question.