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