比较拟合多变量数据的模型

时间:2018-03-17 19:40:14

标签: python statistics bayesian pymc pymc3

我在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;并且我仍然对如何实现类似结果非常感兴趣,但是以适当的方式。当然,如果可能的话。

0 个答案:

没有答案