我正在尝试实施贝叶斯模型来预测足球比分(英超联赛)。我假设分数的数量遵循参数为 lambda 的泊松分布,这是一般公式:
log(home_lambda) = mu + hfa + home_attack -away_def
log(away_lambda) = mu +away_attack - home_def
其中 mu 和 hfa 分别是拦截优势和主场优势。这是我的数据 (380 x 8)
所以基本上我有380x2的方程和42个参数(mu,hfa,20支球队的攻击能力和20支球队的防守能力)。以第一场比赛为例:
FTHG[1] ~ dpois(home_lambda[1]) # FTHG is full time home goal
log(home_lambda[1]) = mu + hfa + att_Crystal_Palace - att_Arsenal
FTAG[1] ~ dpois(lam_a[1]) # FTAG is full time away goal
log(away_lambda[1]) = mu + att_Arsenal - def_Crystal_Palace
下面是我的整个代码
bayes_mod_string = " model{
for (i in 1:380){
FTHG[i] ~ dpois(lam_h[i])
log(lam_h[i]) = mu + hfa + h_att[i] - a_def[i]
FTAG[i] ~ dpois(lam_a[i])
log(lam_a[i]) = mu + a_att[i] - h_def[i]
h_att[i] ~ dnorm(0, 1/1e6) # the attack and defence ability of each team follows a Normal distribution
a_def[i] ~ dnorm(0, 1/1e6)
a_att[i] ~ dnorm(0, 1/1e6)
h_def[i] ~ dnorm(0, 1/1e6)
}
mu ~ dnorm(0, 1/1e6)
hfa ~ dnorm(0, 1/1e6)
}"
data_jags = as.list(test_set)
params = c('mu', 'hfa', unique(test_set$h_att), unique(test_set$a_def)) # 42 in total
bayes_mod_string = jags.model(textConnection(bayes_mod_string),
data = data_jags, n.chains = 3)
update(bayes_mod_string, 1e3)
bayes_mod_sim = coda.samples(model = bayes_mod_string,
variable.names = params, n.iter = 1e3)
bayes_mod_csim = as.mcmc(do.call(rbind, bayes_mod_sim))
错误信息是
警告:无法为 att_Crystal_Palace 设置跟踪监视器 未找到变量 att_Crystal_Palace
不仅包含“att_Crystal_Palace”参数,还包含所有参数。
我尝试分别输入每个团队的攻击和防御能力,将它们放入和取出for循环
att_Crystal_Palace ~ dnorm(0, 1/1e6)
att_Fulham ~ dnorm(0, 1/1e6)
att_Bournemouth ~ dnorm(0, 1/1e6)
att_Leeds ~ dnorm(0, 1/1e6)
att_Newcastle ~ dnorm(0, 1/1e6)
att_Tottenham ~ dnorm(0, 1/1e6)
att_Everton ~ dnorm(0, 1/1e6)
att_Leicester ~ dnorm(0, 1/1e6)
att_Man_United ~ dnorm(0, 1/1e6)
att_West_Ham ~ dnorm(0, 1/1e6)
att_Aston_Villa ~ dnorm(0, 1/1e6)
att_Arsenal ~ dnorm(0, 1/1e6)
att_Brighton ~ dnorm(0, 1/1e6)
att_Man_City ~ dnorm(0, 1/1e6)
att_Southampton ~ dnorm(0, 1/1e6)
att_Wolves ~ dnorm(0, 1/1e6)
att_Brentford ~ dnorm(0, 1/1e6)
att_Nottm_Forest ~ dnorm(0, 1/1e6)
att_Chelsea ~ dnorm(0, 1/1e6)
att_Liverpool ~ dnorm(0, 1/1e6)
def_Crystal_Palace ~ dnorm(0, 1/1e6)
def_Fulham ~ dnorm(0, 1/1e6)
def_Bournemouth ~ dnorm(0, 1/1e6)
def_Leeds ~ dnorm(0, 1/1e6)
def_Newcastle ~ dnorm(0, 1/1e6)
def_Tottenham ~ dnorm(0, 1/1e6)
def_Everton ~ dnorm(0, 1/1e6)
def_Leicester ~ dnorm(0, 1/1e6)
def_Man_United ~ dnorm(0, 1/1e6)
def_West_Ham ~ dnorm(0, 1/1e6)
def_Aston_Villa ~ dnorm(0, 1/1e6)
def_Arsenal ~ dnorm(0, 1/1e6)
def_Brighton ~ dnorm(0, 1/1e6)
def_Man_City ~ dnorm(0, 1/1e6)
def_Southampton ~ dnorm(0, 1/1e6)
def_Wolves ~ dnorm(0, 1/1e6)
def_Brentford ~ dnorm(0, 1/1e6)
def_Nottm_Forest ~ dnorm(0, 1/1e6)
def_Chelsea ~ dnorm(0, 1/1e6)
def_Liverpool ~ dnorm(0, 1/1e6)
这次的错误是
运行时错误: 第 50 行出现编译错误。 尝试重新定义节点 def_Liverpool[1]
问题到底是什么?我该如何解决? 如果您想获取数据,请点击此处 https://www.football-data.co.uk/englandm.php,2022/2023 赛季
您的首要问题就在这里
log(lam_h[i]) = mu + hfa + h_att[i] - a_def[i]
正如您所说,h_att[i]
解析为 att_Arsenal
,但您没有定义名为 att_Arsenal
的节点(变量)。您对 h_def
、a_att
和 a_def
也有同样的问题。
处理如此数量的预测变量的最简单方法是使用数组而不是独立标量。我使用了您提供的链接中 2023/24 赛季的数据。我的输入数据如下所示:
df
# A tibble: 39 × 7
Div Date Time HomeTeam AwayTeam FTHG FTAG
<chr> <chr> <chr> <int> <int> <int> <int>
1 E0 11/08/2023 20:00 6 13 0 3
2 E0 12/08/2023 12:30 1 16 2 1
3 E0 12/08/2023 15:00 3 19 1 1
4 E0 12/08/2023 15:00 5 12 4 1
5 E0 12/08/2023 15:00 9 10 0 1
6 E0 12/08/2023 15:00 17 8 0 1
7 E0 12/08/2023 17:30 15 2 5 1
8 E0 13/08/2023 14:00 4 18 2 2
9 E0 13/08/2023 16:30 7 11 1 1
10 E0 14/08/2023 20:00 14 20 1 0
# … with 29 more rows
我按字母顺序对
HomeTeam
和 AwayTeam
进行了索引。所以,阿森纳是1
,狼队是20
。
然后我可以将模型字符串写为
bayes_mod_string = "
data {
mu ~ dnorm(0, 1/1e6)
hfa ~ dnorm(0, 1/1e6)
for (j in 1:nTeams) {
h_att[j] ~ dnorm(0, 1/1e6)
a_def[j] ~ dnorm(0, 1/1e6)
a_att[j] ~ dnorm(0, 1/1e6)
h_def[j] ~ dnorm(0, 1/1e6)
log(lam_h[j]) = mu + hfa + h_att[j] - a_def[j]
log(lam_a[j]) = mu + a_att[j] - h_def[j]
}
}
model {
for (i in 1:nMatches) {
FTHG[i] ~ dpois(lam_h[home[i]])
FTAG[i] ~ dpois(lam_a[away[i]])
}
}
"
注意模型块中
lam_a
和 lam_h
的双索引。
我更新模型并获取样本
library(rjags)
bayes_model = jags.model(textConnection(bayes_mod_string),
data = data_jags, n.chains = 3)
data_jags <- list(
nTeams = 20,
nMatches = nrow(df),
FTHG = df$FTHG,
FTAG = df$FTAG,
home = df$HomeTeam,
away = df$AwayTeam
)
update(bayes_model, 1e3)
samples <- jags.samples(
model = bayes_model,
variable.names = c('mu', 'hfa', paste0("h_att[", 1:20, "]"), paste0("a_def[", 1:20, "]")),
n.iter = 1e3
)
请注意,我已将
coda.samples
更改为 jags.samples
。
我省略了打印
samples
,因为输出相当长。
就我个人而言,我更喜欢
runjags
而不是rjags
。您可以直接使用模型字符串,而不是通过文本连接传递或写入文件,模型拟合代码更紧凑,我觉得输出更紧凑,信息更丰富。
library(runjags)
run.jags(
bayes_mod_string,
data = data_jags,
monitor = c('mu', 'hfa', paste0("h_att[", 1:20, "]"), paste0("a_def[", 1:20, "]"))
)
Compiling rjags model...
Calling the simulation using the rjags method...
Note: the model did not require adaptation
Burning in the model for 4000 iterations...
|**************************************************| 100%
Running the model for 10000 iterations...
|**************************************************| 100%
Simulation complete
Calculating summary statistics...
Note: The monitored variables 'mu', 'hfa', 'h_att[1]', 'h_att[2]', 'h_att[3]', 'h_att[4]', 'h_att[5]', 'h_att[6]', 'h_att[7]', 'h_att[8]', 'h_att[9]',
'h_att[10]', 'h_att[11]', 'h_att[12]', 'h_att[13]', 'h_att[14]', 'h_att[15]', 'h_att[16]', 'h_att[17]', 'h_att[18]', 'h_att[19]', 'h_att[20]', 'a_def[1]',
'a_def[2]', 'a_def[3]', 'a_def[4]', 'a_def[5]', 'a_def[6]', 'a_def[7]', 'a_def[8]', 'a_def[9]', 'a_def[10]', 'a_def[11]', 'a_def[12]', 'a_def[13]',
'a_def[14]', 'a_def[15]', 'a_def[16]', 'a_def[17]', 'a_def[18]', 'a_def[19]' and 'a_def[20]' appear to be non-stochastic; they will not be included in the
convergence diagnostic
Finished running the simulation
JAGS model summary statistics from 20000 samples (chains = 2; adapt+burnin = 5000):
Lower95 Upper95 Mean SD Mode MCerr MC%ofSD SSeff Lag.10 psrf
mu 827.99 827.99 827.99 0 -- -- -- -- -- --
hfa 1122.6 1122.6 1122.6 0 -- -- -- -- -- --
h_att[1] 287.62 287.62 287.62 0 -- -- -- -- -- --
h_att[2] -696.89 -696.89 -696.89 0 -- -- -- -- -- --
h_att[3] 332.89 332.89 332.89 0 -- -- -- -- -- --
h_att[4] 941.39 941.39 941.39 0 -- -- -- -- -- --
h_att[5] 795.37 795.37 795.37 0 -- -- -- -- -- --
<further output omitted>
重要输出缺乏可变性表明模型规范或我的实现存在问题。就我个人而言,我会采用分层模型。我现在没有时间进一步探索,但至少我已经为您提供了如何继续的线索。