与PyMC3的稳健贝叶斯相关

时间:2016-10-19 09:04:29

标签: python correlation bayesian pymc pymc3

这是贝叶斯关联分析的follow-up question,如this example for PyMC2中所述。

我成功移植了非稳健方法,该方法使用多变量正态分布到PyMC3,但我正在努力使用强大的版本,而使用多变量Student-t分布。

问题在于,表示方差的sigma向量最终变得太大,并且不再能够计算协方差矩阵的逆。因此,相关r的后验几乎跨越整个区间[-1; 1]。

完整代码位于this notebook for PyMC2this 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下行为的提示都受到高度赞赏。

1 个答案:

答案 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