如何拟合pymc3中出现偏斜的数据

时间:2017-04-26 19:06:14

标签: pymc3

我将分层模型拟合到某些数据中,拟合似乎可以接受。

with pm.Model() as model:
    mu_a = pm.Normal('mu_a', 0, sd=.2)
    sigma_b = pm.HalfNormal('sig_a', 0.1)

    mean = pm.Normal('mean', mu_a, sigma_b, shape=n)
    std = pm.HalfNormal('std', 0.01 , shape=n)

    means = mean[h]
    stds = std[h]

    y = pm.Laplace('y', mu=means, b=stds, observed=data) 
    hierarchical_trace = pm.sample(2000, n_init=30000) 

当检查后验预测时,尾部似乎合理,数据的最小值和最大值(黑线)似乎都在生成样本的最小值/最大值内(StudentT不是这种情况)。

ppc_trace = pm.sample_ppc(model=model, trace=hierarchical_trace)

ppc with min/max/mean of original data

然而,平均值(最右边的图表)是偏离的,我认为这是因为我的数据是负面偏斜的,所以数据的质量将平均值移到了太远的右边。

sp.stats.skew(data)

-0.1699020117521286

Pymc3建议的方法是对这类数据进行建模。虽然它是一个对称的分布拉普拉斯似乎很适合我的数据。高斯没有在尾部提供足够的重量(排除偏斜正常吗?)。如何对这种适度偏斜的数据进行建模?

我的目标是获得准确的MAP估计值,并为我的数据的不同部分提供可靠的间隔(基于分层规范)

1 个答案:

答案 0 :(得分:1)

橡胶躲过了这个......但是对于任何后来磕磕绊绊的人都要回答

我发现asymmetric laplace很好地解决了不适合的问题。

def asym_laplace_log_p(x, m, lam, k):
    diff = x - m
    s = tt.sgn(diff)
    return tt.log(lam / (k + 1 /k)) + ( - diff * lam * s * tt.pow(k, s))

def asym_laplace_cdf(x, m, lam, k):
    diff = x - m
    k_2 = k ** 2
    if x <= m:
        return (k_2 / (1 + k_2)) * np.exp((lam / k) * diff)
    return 1 - ((1 / (1 + k_2)) * np.exp(-1 * lam * k * diff))

def inverse_cdf(u, m, lam, k):
    s = np.sign(u)
    k_s = np.power(k, s)
    return m - (1/ (lam * s * k_s)) * np.log(u * s * k_s)

def asym_laplace_mean(m, lam, k):
    return m + ((1 - k** 2) / (lam * k))

然后在模型中

y = pm.DensityDist('y', lambda x: asym_laplace_dist(x, means, stds, k), testval=0, observed=data)  

cdf,反向cdf和仅用于调试目的,值得注意的是这个实现使用lambda作为形状而不是1 / lambda所以我发现前半径比原始问题中的半正常工作更好。

很高兴听到有关此实施的反馈意见。

在撰写本文时,密度dist不适用于sample_ppc(“AttributeError:'DensityDist'对象没有属性'random'”)所以我最终可能会使用生成的位置生成我自己的样本,形状和偏斜值。

我不认为这完全是犹太人的,所以很高兴看到这方面的一些方向(或解决这个问题的方向并直接使用sample_ppc)。