我在PyMC3中使用WAIC(广泛适用的信息标准)时遇到问题。也就是说,我知道根据多元Dirichlet分布分布的数据。我试图通过假设边际分布在一种情况下是β分布,而在其他对数正态分布中来拟合数据。显然,在第一种情况下,我得到的WAIC值比第二种情况要低(更好)。
问题出现在第三种情况,然后我假设数据是根据Dirichlet分布分布的。第三个WAIC比前两个案例大得多(差)。我希望这个WAIC比我在第二个(对数正态)情况下得到的更好(更好)。
基本上我想表明对数正态拟合很糟糕。这很容易被肉眼看到,但我希望有正式的结果来展示。
复制我得到的最小代码:
import pandas as pd
import numpy as np
import pymc3 as pm
# generate the data
df=pd.DataFrame(np.random.dirichlet([10,10,10],size=2000))
# fit the first case (assuming beta marginal distributions)
betaModel=pm.Model()
with betaModel:
alpha=pm.Uniform("alpha",lower=0,upper=20,shape=3)
beta=pm.Uniform("beta",lower=0,upper=40,shape=3)
observed=pm.Beta("obs",alpha=alpha,beta=beta,observed=df.values,shape=df.shape)
betaTrace=pm.sample()
# fit the second case (assuming log-normal marginal distributions)
lognormalModel=pm.Model()
with lognormalModel:
mu=pm.Normal("mu",mu=0,sd=3,shape=3)
sd=pm.HalfNormal("sd",sd=3,shape=3)
observed=pm.Lognormal("obs",mu=mu,sd=sd,observed=df.values,shape=df.shape)
lognormalTrace=pm.sample()
# fit the third case (assuming Dirichlet multivariate distribution)
dirichletModel=pm.Model()
with dirichletModel:
alpha=pm.HalfNormal("alpha",sd=3,shape=3)
observed=pm.Dirichlet("obs",a=alpha,observed=df.values,shape=df.shape)
dirichletTrace=pm.sample()
# compare WAIC
print(pm.waic(betaTrace,betaModel))
print(pm.waic(lognormalTrace,lognormalModel))
print(pm.waic(dirichletTrace,dirichletModel))
输出结果为:
WAIC_r(WAIC=-12801.95319823564, WAIC_se=105.07502476563575, p_WAIC=5.941977774190434)
WAIC_r(WAIC=-12534.643059697866, WAIC_se=115.43257184238044, p_WAIC=6.68850211472046)
WAIC_r(WAIC=-9156.050975326929, WAIC_se=81.45146980652675, p_WAIC=2.7977039523187996)
我猜问题可能与错误有关:
ValueError: operands could not be broadcast together with shapes (6000,) (2000,)
我尝试跑步时得到的:
pm.compare((betaTrace,lognormalTrace,dirichletTrace),(betaModel,lognormalModel,dirichletModel))
有关如何获得合理比较的任何建议吗?
修改
在考虑了这个问题之后,我会相信它有些不正确"。我倾向于这么认为,因为WAIC是一个相对的衡量标准,因此很可能只能合理地比较类似的统计模型。如果模型太不相似,那么你得到了我得到的东西。
我从pm.compare
得到的错误似乎与处理随机向量有关。在前两种情况下,随机向量的每个分量被视为单独的随机变量(每2000个向量3个分量= 6000个点)。在第三种情况下,整个随机向量被视为随机变量(2000个向量= 2000个点)。
最初我认为可以通过减少前两种情况下的点数来解决这个问题。但由于前两个统计模型(错误地)假设组件是独立的,因此添加对数概率不会改变任何东西。 WAIC值保持不变。
目前我认为可以做一个小作弊。即将数据拟合到Dirichlet分布,但计算WAIC就像我将拟合beta分布一样。这给出了预期的结果 - 对于β拟合,Dirichlet拟合的WAIC略大于WAIC,但对于对数正态拟合,WAIC小于WAIC。
这个"作弊的代码":
from collections import namedtuple
from scipy.special import logsumexp
def cheat_logp(tracePoint,model):
values=model.obs.eval()
_,components=values.shape
cb=[None]*components
beta=np.sum(tracePoint["alpha"])
for i in range(components):
cheatBeta=pm.Beta.dist(alpha=tracePoint["alpha"][i],beta=beta-tracePoint["alpha"][i])
cb[i]=cheatBeta.logp(values[:,i]).eval()
return np.array(cb).T
def _log_post_trace(trace, model):
# copy the contents of _log_post_trace function from pymc3/stats.py
# but replace "var.logp_elemwise(pt)" with "cheat_logp(pt,model)"
# <...>
def mywaic(trace, model=None, pointwise=False):
# copy the contents of waic function from pymc3/stats.py
# <...>
显然这种作弊不是很好&#34;很好&#34;并且我仍然对如何实现类似结果非常感兴趣,但是以适当的方式。当然,如果可能的话。