使用 PyMC3 和大型数据集进行贝叶斯线性回归 - 括号嵌套级别超过最大值且性能缓慢

Posted

技术标签:

【中文标题】使用 PyMC3 和大型数据集进行贝叶斯线性回归 - 括号嵌套级别超过最大值且性能缓慢【英文标题】:Bayesian Linear Regression with PyMC3 and a large dataset - bracket nesting level exceeded maximum and slow performance 【发布时间】:2019-05-09 06:37:10 【问题描述】:

我想使用贝叶斯多元线性回归来估计团队运动(例如冰球、篮球或足球)中球员的实力。为此,我创建了一个矩阵 X,其中包含作为列的球员和作为行的比赛。对于每场比赛,球员条目是 1(球员在主队比赛)、-1(球员在客队比赛)或 0(球员不参加本场比赛)。因变量 Y 定义为两队在每场比赛中的得分差异(Score_home_team - Score_away_team)。

因此,一个赛季的参数数量将非常大(例如,X 由 300 行 x 450 列定义;即 450 个球员系数 + y 截距)。运行 fit 时遇到编译错误:

('Compilation failed (return status=1): /Users/me/.theano/compiledir_Darwin-17.7.0-x86_64-i386-64bit-i386-3.6.5-64/tmpdxxc2379/mod.cpp:27598:32: fatal error: bracket nesting level exceeded maximum of 256.

我试图通过设置来处理这个错误:

theano.config.gcc.cxxflags = "-fbracket-depth=1024"

现在,采样正在运行。但是,它太慢了,即使我只取 300 行中的 35 行,采样也不会在 20 分钟内完成。

这是我的基本代码:

import pymc3 as pm
basic_model = pm.Model()

with basic_model:

    # Priors for beta coefficients - these are the coefficients of the players
    dict_betas = 
    for col in X.columns:
        dict_betas[col] = pm.Normal(col, mu=0, sd=10)

    # Priors for unknown model parameters
    alpha = pm.Normal('alpha', mu=0, sd=10) # alpha is the y-intercept
    sigma = pm.HalfNormal('sigma', sd=1) # standard deviation of the observations

    # Expected value of outcome
    mu = alpha
    for col in X.columns:
        mu = mu + dict_betas[col] * X[col] # mu = alpha + beta_1 * Player_1 + beta_2 * Player_2 + ...

    # Likelihood (sampling distribution) of observations
    Y_obs = pm.Normal('Y_obs', mu=mu, sd=sigma, observed=Y)

对于大型数据集,模型的实例化在一分钟内运行。我使用以下方法进行采样:

with basic_model:

    # draw 500 posterior samples
    trace = pm.sample(500)

小样本(例如 9 行 80 列)的采样在 7 分钟内完成。但是,随着样本量的增加,时间会显着增加。

有什么建议可以让这个贝叶斯线性回归在可行的时间内运行吗?使用 PyMC3 可以解决这些问题吗(记得我遇到了括号嵌套错误)?我在最近的一篇出版物中看到这种分析在 R 中是可行的 (https://arxiv.org/pdf/1810.08032.pdf)。因此,我想它也应该以某种方式与 Python 3 一起使用。

感谢任何帮助!

【问题讨论】:

也许尝试将其转换为点积形式,而不是使用 for 循环。类似于beta = pm.Normal('beta', mu=0, sd=10, shape=X.shape[1])mu = alpha + pm.math.dot(X, beta)。也许是this other answer might help,它还演示了如何扩充X 以包含截距并避免使用单独的alpha 变量。 梅尔夫,非常感谢您的有用评论。您使用点积而不是 for 循环/字典的建议解决了括号嵌套问题和性能缓慢问题。该程序运行良好,所有 beta 设置为 mu = 0。但是,现在我不知道如何为每个玩家添加不同的 mus?有没有办法使用您建议的 beta 定义将不同的 mus 和 sigma 包含到 beta 中?最后,我想为每个玩家运行具有不同先验的贝叶斯线性回归。 【参考方案1】:

消除 for 循环应该可以提高性能,并且还可以解决您报告的嵌套问题。 Theano TensorVariables 和派生自它们的 PyMC3 随机变量已经是多维的,并且支持线性代数运算。尝试将您的代码更改为类似于

beta = pm.Normal('beta', mu=0, sd=10, shape=X.shape[1])
...
mu = alpha + pm.math.dot(X, beta)
...

如果您需要为mu 和/或sd 指定不同的先前值,这些参数接受theano.tensor.as_tensor_variable() 接受的任何内容,因此您可以传递一个列表或numpy 数组。

我强烈建议您熟悉 theano.tensor 和 pymc3.math 操作,因为有时您必须使用它们来正确操作随机变量,并且通常它应该会产生更高效的代码。

【讨论】:

完美,梅尔夫!非常感谢! mu 和 sd 接受 numpy 数组。就我而言, mu 也接受列表,但 sd 不接受。使用 numpy 数组一切正常!

以上是关于使用 PyMC3 和大型数据集进行贝叶斯线性回归 - 括号嵌套级别超过最大值且性能缓慢的主要内容,如果未能解决你的问题,请参考以下文章

Python用PyMC3实现贝叶斯线性回归模型

贝叶斯线性回归和多元线性回归构建工资预测模型|附代码数据

比较贝叶斯线性回归与线性回归

PYMC3 季节性变量

拟合贝叶斯线性回归并预测不可观察的值

R语言用贝叶斯线性回归贝叶斯模型平均 (BMA)来预测工人工资|附代码数据