PyMC3 中的模型比较
Model comparison in PyMC3
我是 PyMC3 的新手,正在尝试实现 Kruschke (2015) 第 12.2.2 节(模型比较)中的分层模型。
我成功地定义了完整的模型,然后查看后验参数值的差异(确定差异是否可以可信地说为零)。
我还尝试在模型中明确地进行比较,如书中所示(定义完整模型和受限模型并使用分类分布对它们进行采样)。
基本上我尝试在 PyMC3 中实现以下 JAGS 模型定义。
http://nbviewer.jupyter.org/github/JWarmenhoven/DBDA-python/blob/master/Notebooks/Chapter%2012.ipynb
但我不知道如何使用模型索引来 select (伪)先验。有什么指点吗?
JAG:
model {
for ( s in 1:nSubj ) {
nCorrOfSubj[s] ~ dbin( theta[s] , nTrlOfSubj[s] )
theta[s] ~ dbeta( aBeta[CondOfSubj[s]] , bBeta[CondOfSubj[s]] )
}
for ( j in 1:nCond ) {
# Use omega[j] for model index 1, omega0 for model index 2:
aBeta[j] <- ( equals(mdlIdx,1)*omega[j]
+ equals(mdlIdx,2)*omega0 ) * (kappa[j]-2)+1
bBeta[j] <- ( 1 - ( equals(mdlIdx,1)*omega[j]
+ equals(mdlIdx,2)*omega0 ) ) * (kappa[j]-2)+1
omega[j] ~ dbeta( a[j,mdlIdx] , b[j,mdlIdx] )
}
omega0 ~ dbeta( a0[mdlIdx] , b0[mdlIdx] )
for ( j in 1:nCond ) {
kappa[j] <- kappaMinusTwo[j] + 2
kappaMinusTwo[j] ~ dgamma( 2.618 , 0.0809 ) # mode 20 , sd 20
}
# Constants for prior and pseudoprior:
aP <- 1
bP <- 1
# a0[model] and b0[model]
a0[1] <- .48*500 # pseudo
b0[1] <- (1-.48)*500 # pseudo
a0[2] <- aP # true
b0[2] <- bP # true
# a[condition,model] and b[condition,model]
a[1,1] <- aP # true
a[2,1] <- aP # true
a[3,1] <- aP # true
a[4,1] <- aP # true
b[1,1] <- bP # true
b[2,1] <- bP # true
b[3,1] <- bP # true
b[4,1] <- bP # true
a[1,2] <- .40*125 # pseudo
a[2,2] <- .50*125 # pseudo
a[3,2] <- .51*125 # pseudo
b[1,2] <- (1-.40)*125 # pseudo
b[2,2] <- (1-.50)*125 # pseudo
b[3,2] <- (1-.51)*125 # pseudo
b[4,2] <- (1-.52)*125 # pseudo
# Prior on model index:
mdlIdx ~ dcat( modelProb[] )
modelProb[1] <- .5
modelProb[2] <- .5
}
PyMC3:
with pmc.Model() as model_1:
# constants
aP, bP = 1, 1
# Pseudo- and true hyperpriors per model
a0 = [.48*500, aP]
b0 = [(1-.48)*500, bP]
# Lower level pseudo- and true priors per model/condition combination
a = np.c_[np.tile(aP, 4), [(.40*125), (.50*125), (.51*125), (.52*125)]]
b = np.c_[np.tile(bP, 4), [(1-.40)*125, (1-.50)*125, (1-.51)*125, (1-.52)*125]]
# Prior on model index [0,1]
m_idx = pmc.Categorical('m_idx', np.asarray([.5, .5]))
# Priors on concentration parameters
kappa = pmc.Gamma('kappa', 2.618, 0.0809, shape=nCond)
# omega0
omega0 = pmc.Beta('omega0', a0[m_idx], b0[m_idx])
# omega (condition specific)
omega = pmc.Beta('omega', a[:,m_idx], b[:,m_idx], shape=nCond)
# theta
aBeta = pmc.switch(eq(m_idx, 0), omega0 * kappa[cond_idx]+1, omega[cond_idx] * kappa[cond_idx]+1)
bBeta = pmc.switch(eq(m_idx, 0), (1-omega0) * kappa[cond_idx]+1, (1-omega[cond_idx]) * kappa[cond_idx]+1)
theta = pmc.Beta('theta', aBeta[cond_idx], bBeta[cond_idx], shape=df.index.size)
# Likelihood
y = pmc.Binomial('y', n=df.nTrlOfSubj.values, p=theta, observed=df.nCorrOfSubj)
Applied log-transform to kappa and added transformed kappa_log_ to model.
输出:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-40-74e77ccc6ce9> in <module>()
8
9 # omega0
---> 10 omega0 = pmc.Beta('omega0', a0[m_idx], b0[m_idx])
11
12 # omega (condition specific)
TypeError: list indices must be integers or slices, not FreeRV
已更新
纠正伪先验(缺少括号)后,结果看起来好多了。但是,我不确定 pmc.Beta() 函数是否适用于数组作为 a 和 b 的参数。
http://nbviewer.jupyter.org/github/JWarmenhoven/DBDA-python/blob/master/Notebooks/Chapter%2012.ipynb
您收到的错误是因为您试图使用张量索引列表。解决这个问题的一种方法是将列表变成张量。
import theano.tensor as tt
a0 = tt.as_tensor([.48*500, aP])
或者,您可以使用 pmc.switch()
在先验和伪先验之间进行选择,例如:
a0 = pm.switch(m_idx, .48*500, aP)
我没有彻底检查你的代码,但注意到你有
pmc.switch(eq(m_idx, 0)....)
相反,你应该写
pmc.switch(pmc.eq(m_idx, 0)....)
或者可能是:
pmc.switch(m_idx)....)
因为 0 的计算结果为 False
而 1 的计算结果为 True
。
你还有
omega = pmc.Beta('omega0'...)
你应该
omega = pmc.Beta('omega'...)
你的问题让我意识到我忘了 port 一个伪先验的例子。我会尽快做的。
已编辑
这里是完整模型
with pmc.Model() as model_1:
# constants
aP, bP = 1., 1.
# Pseudo- and true hyperpriors per model
a0 = tt.as_tensor([aP, .48*500])
b0 = tt.as_tensor([bP, (1-.48)*500])
# Lower level pseudo- and true priors per model/condition combination
a = tt.as_tensor(np.c_[[(.40*125), (.50*125), (.51*125), (.52*125)], np.tile(aP, 4)])
b = tt.as_tensor(np.c_[[((1-.40)*125), ((1-.50)*125), ((1-.51)*125), ((1-.52)*125)], np.tile(bP, 4)])
# Prior on model index [0,1]
m_idx = pmc.Categorical('m_idx', p=np.array([.5, .5]))
# Priors on concentration parameters
kappa = pmc.Gamma('kappa', 2.618, 0.0809, shape=nCond)
# omega0
omega0 = pmc.Beta('omega0', a0[m_idx], b0[m_idx])
# omega (condition specific)
omega = pmc.Beta('omega', a[:,m_idx], b[:,m_idx], shape=nCond)
# theta
aBeta = pmc.switch(pmc.eq(m_idx, 0), omega0 * kappa+1, omega * kappa+1)
bBeta = pmc.switch(pmc.eq(m_idx, 0), (1-omega0) * kappa+1, (1-omega) * kappa+1)
theta = pmc.Beta('theta', aBeta, bBeta, shape=nCond)
# Likelihood
y = pmc.Binomial('y', n=df.nTrlOfSubj.values, p=theta[cond_idx], observed=df.nCorrOfSubj)
trace = pmc.sample(1000)
请注意,您的代码有几个问题,例如变量 b
的定义中缺少括号,以及先验和伪先验的顺序颠倒了。此外,我更改代码以让 aBeta
、bBeta
和 theta
具有 shape=nCond,然后很可能将 p
定义为 p=theta[cond_idx]
。
我没有对照 Kruschke 的书检查结果,但痕迹看起来很合理。
我是 PyMC3 的新手,正在尝试实现 Kruschke (2015) 第 12.2.2 节(模型比较)中的分层模型。
我成功地定义了完整的模型,然后查看后验参数值的差异(确定差异是否可以可信地说为零)。
我还尝试在模型中明确地进行比较,如书中所示(定义完整模型和受限模型并使用分类分布对它们进行采样)。
基本上我尝试在 PyMC3 中实现以下 JAGS 模型定义。
http://nbviewer.jupyter.org/github/JWarmenhoven/DBDA-python/blob/master/Notebooks/Chapter%2012.ipynb
但我不知道如何使用模型索引来 select (伪)先验。有什么指点吗?
JAG:
model {
for ( s in 1:nSubj ) {
nCorrOfSubj[s] ~ dbin( theta[s] , nTrlOfSubj[s] )
theta[s] ~ dbeta( aBeta[CondOfSubj[s]] , bBeta[CondOfSubj[s]] )
}
for ( j in 1:nCond ) {
# Use omega[j] for model index 1, omega0 for model index 2:
aBeta[j] <- ( equals(mdlIdx,1)*omega[j]
+ equals(mdlIdx,2)*omega0 ) * (kappa[j]-2)+1
bBeta[j] <- ( 1 - ( equals(mdlIdx,1)*omega[j]
+ equals(mdlIdx,2)*omega0 ) ) * (kappa[j]-2)+1
omega[j] ~ dbeta( a[j,mdlIdx] , b[j,mdlIdx] )
}
omega0 ~ dbeta( a0[mdlIdx] , b0[mdlIdx] )
for ( j in 1:nCond ) {
kappa[j] <- kappaMinusTwo[j] + 2
kappaMinusTwo[j] ~ dgamma( 2.618 , 0.0809 ) # mode 20 , sd 20
}
# Constants for prior and pseudoprior:
aP <- 1
bP <- 1
# a0[model] and b0[model]
a0[1] <- .48*500 # pseudo
b0[1] <- (1-.48)*500 # pseudo
a0[2] <- aP # true
b0[2] <- bP # true
# a[condition,model] and b[condition,model]
a[1,1] <- aP # true
a[2,1] <- aP # true
a[3,1] <- aP # true
a[4,1] <- aP # true
b[1,1] <- bP # true
b[2,1] <- bP # true
b[3,1] <- bP # true
b[4,1] <- bP # true
a[1,2] <- .40*125 # pseudo
a[2,2] <- .50*125 # pseudo
a[3,2] <- .51*125 # pseudo
b[1,2] <- (1-.40)*125 # pseudo
b[2,2] <- (1-.50)*125 # pseudo
b[3,2] <- (1-.51)*125 # pseudo
b[4,2] <- (1-.52)*125 # pseudo
# Prior on model index:
mdlIdx ~ dcat( modelProb[] )
modelProb[1] <- .5
modelProb[2] <- .5
}
PyMC3:
with pmc.Model() as model_1:
# constants
aP, bP = 1, 1
# Pseudo- and true hyperpriors per model
a0 = [.48*500, aP]
b0 = [(1-.48)*500, bP]
# Lower level pseudo- and true priors per model/condition combination
a = np.c_[np.tile(aP, 4), [(.40*125), (.50*125), (.51*125), (.52*125)]]
b = np.c_[np.tile(bP, 4), [(1-.40)*125, (1-.50)*125, (1-.51)*125, (1-.52)*125]]
# Prior on model index [0,1]
m_idx = pmc.Categorical('m_idx', np.asarray([.5, .5]))
# Priors on concentration parameters
kappa = pmc.Gamma('kappa', 2.618, 0.0809, shape=nCond)
# omega0
omega0 = pmc.Beta('omega0', a0[m_idx], b0[m_idx])
# omega (condition specific)
omega = pmc.Beta('omega', a[:,m_idx], b[:,m_idx], shape=nCond)
# theta
aBeta = pmc.switch(eq(m_idx, 0), omega0 * kappa[cond_idx]+1, omega[cond_idx] * kappa[cond_idx]+1)
bBeta = pmc.switch(eq(m_idx, 0), (1-omega0) * kappa[cond_idx]+1, (1-omega[cond_idx]) * kappa[cond_idx]+1)
theta = pmc.Beta('theta', aBeta[cond_idx], bBeta[cond_idx], shape=df.index.size)
# Likelihood
y = pmc.Binomial('y', n=df.nTrlOfSubj.values, p=theta, observed=df.nCorrOfSubj)
Applied log-transform to kappa and added transformed kappa_log_ to model.
输出:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-40-74e77ccc6ce9> in <module>()
8
9 # omega0
---> 10 omega0 = pmc.Beta('omega0', a0[m_idx], b0[m_idx])
11
12 # omega (condition specific)
TypeError: list indices must be integers or slices, not FreeRV
已更新
纠正伪先验(缺少括号)后,结果看起来好多了。但是,我不确定 pmc.Beta() 函数是否适用于数组作为 a 和 b 的参数。
http://nbviewer.jupyter.org/github/JWarmenhoven/DBDA-python/blob/master/Notebooks/Chapter%2012.ipynb
您收到的错误是因为您试图使用张量索引列表。解决这个问题的一种方法是将列表变成张量。
import theano.tensor as tt
a0 = tt.as_tensor([.48*500, aP])
或者,您可以使用 pmc.switch()
在先验和伪先验之间进行选择,例如:
a0 = pm.switch(m_idx, .48*500, aP)
我没有彻底检查你的代码,但注意到你有
pmc.switch(eq(m_idx, 0)....)
相反,你应该写
pmc.switch(pmc.eq(m_idx, 0)....)
或者可能是:
pmc.switch(m_idx)....)
因为 0 的计算结果为 False
而 1 的计算结果为 True
。
你还有
omega = pmc.Beta('omega0'...)
你应该
omega = pmc.Beta('omega'...)
你的问题让我意识到我忘了 port 一个伪先验的例子。我会尽快做的。
已编辑
这里是完整模型
with pmc.Model() as model_1:
# constants
aP, bP = 1., 1.
# Pseudo- and true hyperpriors per model
a0 = tt.as_tensor([aP, .48*500])
b0 = tt.as_tensor([bP, (1-.48)*500])
# Lower level pseudo- and true priors per model/condition combination
a = tt.as_tensor(np.c_[[(.40*125), (.50*125), (.51*125), (.52*125)], np.tile(aP, 4)])
b = tt.as_tensor(np.c_[[((1-.40)*125), ((1-.50)*125), ((1-.51)*125), ((1-.52)*125)], np.tile(bP, 4)])
# Prior on model index [0,1]
m_idx = pmc.Categorical('m_idx', p=np.array([.5, .5]))
# Priors on concentration parameters
kappa = pmc.Gamma('kappa', 2.618, 0.0809, shape=nCond)
# omega0
omega0 = pmc.Beta('omega0', a0[m_idx], b0[m_idx])
# omega (condition specific)
omega = pmc.Beta('omega', a[:,m_idx], b[:,m_idx], shape=nCond)
# theta
aBeta = pmc.switch(pmc.eq(m_idx, 0), omega0 * kappa+1, omega * kappa+1)
bBeta = pmc.switch(pmc.eq(m_idx, 0), (1-omega0) * kappa+1, (1-omega) * kappa+1)
theta = pmc.Beta('theta', aBeta, bBeta, shape=nCond)
# Likelihood
y = pmc.Binomial('y', n=df.nTrlOfSubj.values, p=theta[cond_idx], observed=df.nCorrOfSubj)
trace = pmc.sample(1000)
请注意,您的代码有几个问题,例如变量 b
的定义中缺少括号,以及先验和伪先验的顺序颠倒了。此外,我更改代码以让 aBeta
、bBeta
和 theta
具有 shape=nCond,然后很可能将 p
定义为 p=theta[cond_idx]
。
我没有对照 Kruschke 的书检查结果,但痕迹看起来很合理。