这是贝叶斯关联分析的follow-up question,如this example for PyMC2中所述。
我成功移植了非稳健方法,该方法使用多变量正态分布到PyMC3,但我正在努力使用强大的版本,而使用多变量Student-t分布。
问题在于,表示方差的sigma
向量最终变得太大,并且不再能够计算协方差矩阵的逆。因此,相关r
的后验几乎跨越整个区间[-1; 1]。
完整代码位于this notebook for PyMC2和this notebook for PyMC3。
PyMC2的相关代码是:
import pymc
import numpy as np
from scipy.special import gammaln
def analyze(data):
mu = pymc.Normal('mu', 0, 0.000001, size=2)
sigma = pymc.Uniform('sigma', 0, 1000, size=2)
rho = pymc.Uniform('r', -1, 1)
nu = pymc.Exponential('nu',1/29., 1)
# we model nu as an Exponential plus one
@pymc.deterministic
def nuplus(nu=nu):
return nu + 1
@pymc.deterministic
def precision(sigma=sigma,rho=rho):
ss1 = float(sigma[0] * sigma[0])
ss2 = float(sigma[1] * sigma[1])
rss = float(rho * sigma[0] * sigma[1])
return np.linalg.inv(np.mat([[ss1, rss], [rss, ss2]]))
# log-likelihood of multivariate t-distribution
@pymc.stochastic(observed=True)
def mult_t(value=data.T, mu=mu, tau=precision, nu=nuplus):
k = float(tau.shape[0])
res = 0
for r in value:
delta = r - mu
enum1 = gammaln((nu+k)/2.) + 0.5 * np.log(np.linalg.det(tau))
denom = (k/2.)*np.log(nu*np.pi) + gammaln(nu/2.)
enum2 = (-(nu+k)/2.) * np.log (1 + (1/nu)*delta.dot(tau).dot(delta.T))
result = enum1 + enum2 - denom
res += result[0]
return res[0,0]
model = pymc.MCMC(locals())
model.sample(50000,25000)
对于PyMC3,我可以使用内置的MvStudentT
分布,它需要协方差矩阵而不是精度矩阵。
import pymc3 as pm
import numpy as np
def mad(data, axis=None):
return np.median(np.absolute(data - np.median(data, axis)), axis)
def covariance(sigma, rho):
C = T.alloc(rho, 2, 2)
C = T.fill_diagonal(C, 1.)
S = T.diag(sigma)
return S.dot(C).dot(S)
def analyze_robust(data):
with pm.Model() as model:
# priors might be adapted here to be less flat
mu = pm.Normal('mu', mu=0., tau=0.000001, shape=2, testval=np.median(data, axis=1))
sigma = pm.Uniform('sigma', lower=0, upper=1000, shape=2, testval=mad(data.T, axis=0))
rho = pm.Uniform('r', lower=-1., upper=1., testval=0.5)
cov = pm.Deterministic('cov', covariance(sigma, rho))
nu = pm.Exponential('nu_minus_one', lam=1./29.) + 1
mult_t = pm.MvStudentT('mult_t', nu=nu, mu=mu, Sigma=cov, observed=data.T)
return model
任何可能解释PyMC3下行为的提示都受到高度赞赏。
答案 0 :(得分:0)
我发现以下内容似乎可以产生合理的结果。我基于this article建立先验,并用它来验证相关性。所有工作都在此notebook中。
def mad(data, axis=None):
return np.median(np.absolute(data - np.median(data, axis)), axis)
def covariance(sigma, rho):
C = T.alloc(rho, 2, 2)
C = T.fill_diagonal(C, 1.)
S = T.diag(sigma)
return S.dot(C).dot(S)
def analyze_robust(data):
with pm.Model() as model:
# priors might be adapted here to be less flat
mu = pm.Normal('mu', mu=0., sd=100., shape=2, testval=np.median(data.T, axis=1))
bound_sigma = pm.Bound(pm.Normal, lower=0.)
sigma = bound_sigma('sigma', mu=0., sd=100., shape=2, testval=mad(data, axis=0))
rho = pm.Uniform('r', lower=-1., upper=1., testval=0)
cov = pm.Deterministic('cov', covariance(sigma, rho))
bound_nu = pm.Bound(pm.Gamma, lower=1.)
nu = bound_nu('nu', alpha=2, beta=10)
mult_t = pm.MvStudentT('mult_t', nu=nu, mu=mu, Sigma=cov, observed=data)
return model