【问题标题】:Multivariate linear regression in pymc3pymc3中的多元线性回归
【发布时间】:2016-09-24 14:07:56
【问题描述】:

在专门使用emcee 多年后,我最近开始学习pymc3,但我遇到了一些概念问题。

我正在练习Hogg's Fitting a model to data 的第 7 章。这涉及到具有任意二维不确定性的直线的 mcmc 拟合。我在emcee 中很容易做到这一点,但是pymc 给我带来了一些问题。

它本质上归结为使用多元高斯似然。

这是我目前所拥有的。

from pymc3 import  *

import numpy as np
import matplotlib.pyplot as plt

size = 200
true_intercept = 1
true_slope = 2

true_x = np.linspace(0, 1, size)
# y = a + b*x
true_regression_line = true_intercept + true_slope * true_x
# add noise

# here the errors are all the same but the real world they are usually not!
std_y, std_x = 0.1, 0.1 
y = true_regression_line + np.random.normal(scale=std_y, size=size)
x = true_x + np.random.normal(scale=std_x, size=size)

y_err = np.ones_like(y) * std_y
x_err = np.ones_like(x) * std_x

data = dict(x=x, y=y)

with Model() as model: # model specifications in PyMC3 are wrapped in a with-statement
    # Define priors
    intercept = Normal('Intercept', 0, sd=20)
    gradient = Normal('gradient', 0, sd=20)


    # Define likelihood
    likelihood = MvNormal('y', mu=intercept + gradient * x,
                        tau=1./(np.stack((y_err, x_err))**2.), observed=y)

    # start the mcmc!
    start = find_MAP() # Find starting value by optimization
    step = NUTS(scaling=start) # Instantiate MCMC sampling algorithm
    trace = sample(2000, step, start=start, progressbar=False) # draw 2000 posterior samples using NUTS sampling

这会引发错误:LinAlgError: Last 2 dimensions of the array must be square

所以我试图通过MvNormal x 和 y 的测量值 (mus) 及其相关的测量不确定性(y_errx_err)。但它似乎不喜欢 2d tau 参数。

有什么想法吗?这一定是可能的

谢谢

【问题讨论】:

  • 您是否尝试进行线性回归,包括模型中xy 的测量误差?
  • 是:二维不确定性

标签: python statistics pymc3 mcmc emcee


【解决方案1】:

您可以尝试调整以下模型。是“常规”线性回归。但是xy 已经被高斯分布所取代。在这里,我不仅假设输入和输出变量的测量值,还假设它们的误差的可靠估计(例如由测量设备提供)。如果您不相信这些错误值,您可以尝试从数据中估算它们。

with pm.Model() as model:
    intercept = pm.Normal('intercept', 0, sd=20)
    gradient = pm.Normal('gradient', 0, sd=20)
    epsilon = pm.HalfCauchy('epsilon', 5)
    obs_x = pm.Normal('obs_x', mu=x, sd=x_err, shape=len(x))
    obs_y = pm.Normal('obs_y', mu=y, sd=y_err, shape=len(y))

    likelihood = pm.Normal('y', mu=intercept + gradient * obs_x,
                    sd=epsilon, observed=obs_y)

    trace = pm.sample(2000)

如果您从数据中估计误差,可以合理地假设它们可能是相关的,因此,您可以使用多元高斯而不是使用两个单独的高斯。在这种情况下,您最终会得到如下模型:

df_data = pd.DataFrame(data)
cov = df_data.cov()

with pm.Model() as model:
    intercept = pm.Normal('intercept', 0, sd=20)
    gradient = pm.Normal('gradient', 0, sd=20)
    epsilon = pm.HalfCauchy('epsilon', 5)

    obs_xy = pm.MvNormal('obs_xy', mu=df_data, tau=pm.matrix_inverse(cov), shape=df_data.shape)

    yl = pm.Normal('yl', mu=intercept + gradient * obs_xy[:,0],
                    sd=epsilon, observed=obs_xy[:,1])

mu, sds, elbo = pm.variational.advi(n=20000)
step =  pm.NUTS(scaling=model.dict_to_array(sds), is_cov=True)
trace = pm.sample(1000, step=step, start=mu)

请注意,在之前的模型中,协方差矩阵是根据数据计算得出的。如果您要这样做,那么我认为使用第一个模型会更好,但如果您要估计协方差矩阵,那么第二个模型可能是一种明智的方法。

对于第二个模型,我使用 ADVI 对其进行初始化。 ADVI 是初始化模型的好方法,通常它比 find_MAP() 效果更好。

您可能还想查看 David Hogg 的 repository。还有这本书Statistical Rethinking,McElreath 讨论了进行线性回归的问题,包括输入和输出变量中的误差。

【讨论】:

  • 这看起来很有希望。但是 epsilon 在那里做什么呢?
  • 如果您测量成年男性的身高,您的样本将具有类似高斯分布的sd=epsilon,这仅仅是因为人们的身高不同。除此之外,您将有一个与测量每个人相关的错误。这就是为什么即使我们包括测量误差,我们仍然有y ~ N(Beta X, sd=epsilon)。我想这个例子可以“转移”到你的问题上,但我可能错了,所以请随意对模型进行所有必要的更改。
  • 所以 epsilon 是分布的内在散射,与测量误差分开处理?
  • 这一切都很好,但我真正想要的是重建可能性here,没有提到 epsilon,只有测量误差的相关矩阵。
  • 另外,您的模型需要很长时间才能运行。
猜你喜欢
  • 1970-01-01
  • 2010-11-23
  • 2014-09-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-17
  • 2014-05-20
相关资源
最近更新 更多