PyMC3中含双似然函数的足球进球预测模型WAIC计算问题
解决PyMC3中多似然模型的WAIC计算与模型比较问题
这个报错的原因很明确:你的模型里有两个独立的似然观测变量(h_goals和a_goals),ArviZ的WAIC函数默认会自动查找模型中的log likelihood数组,但当发现多个时,它无法确定要使用哪一个,因此抛出了这个类型错误。下面是两种可行的解决方法,以及后续模型比较的步骤:
方法1:手动合并整体log likelihood
最规范的做法是在模型中添加一个确定性变量,将两个似然的log概率相加,得到整个模型的总log likelihood。这样后续计算WAIC时就可以直接指定这个变量,避免歧义:
with pm.Model() as model: # 全局参数定义 h = pm.Normal('h', mu=mu, tau=tau) sd_a = pm.Gamma('sd_a', .1, .1) sd_d = pm.Gamma('sd_d', .1, .1) alpha = pm.Normal('alpha', mu=mu, tau=tau) # 球队专属参数 a_s = pm.Normal("a_s", mu=0, sd=sd_a, shape=n) d_s = pm.Normal("d_s", mu=0, sd=sd_d, shape=n) atts = pm.Deterministic('atts', a_s - tt.mean(a_s)) defs = pm.Deterministic('defs', d_s - tt.mean(d_s)) # 进球期望计算 h_theta = tt.exp(alpha + h + atts[h_t] + defs[a_t]) a_theta = tt.exp(alpha + atts[a_t] + defs[h_t]) # 似然函数 h_goals = pm.Poisson('h_goals', mu=h_theta, observed=observed_h_goals) a_goals = pm.Poisson('a_goals', mu=a_theta, observed=observed_a_goals) # 合并两个似然的log概率(每个数据点的总log likelihood) total_log_likelihood = pm.Deterministic('total_log_likelihood', h_goals.logp + a_goals.logp)
之后计算WAIC时,明确指定这个合并后的变量:
waic = pm.waic(trace, model, var_name='total_log_likelihood')
方法2:直接指定多个似然变量
如果你不想修改模型,也可以在调用pm.waic()时,通过var_names参数同时传入两个似然变量。ArviZ会自动将它们的log likelihood相加(因为独立观测的总log概率是各部分的和):
waic = pm.waic(trace, model, var_names=['h_goals', 'a_goals'])
模型比较步骤
当你需要比较多个这类多似然模型时,只需要对每个模型执行上述任意一种WAIC计算方式,然后使用pm.compare()函数进行比较:
# 假设你有两个模型:model1、model2,以及对应的采样结果trace1、trace2 waic_model1 = pm.waic(trace1, model1, var_names=['h_goals', 'a_goals']) waic_model2 = pm.waic(trace2, model2, var_names=['h_goals', 'a_goals']) # 执行模型比较 comparison_results = pm.compare({'Model 1': waic_model1, 'Model 2': waic_model2}) # 打印比较结果,默认按WAIC值从小到大排序(值越小模型越好) print(comparison_results)
注意事项
- 两种方法的核心都是确保WAIC计算使用的是整个模型的总log likelihood,也就是每个数据点(每场比赛)对应的主队进球和客队进球的log概率之和。
- 如果使用
pm.compare(),也可以直接传入trace和模型对象的字典,它会自动处理WAIC计算,但前提是你已经解决了多似然变量的问题(比如提前合并log likelihood)。
内容的提问来源于stack exchange,提问作者milanDD
相关产品推荐
相关产品推荐

