在内存中没有原始模型的情况下,可以加载PyMC3跟踪并访问值吗?

2024-03-29 05:40:41 发布

您现在位置:Python中文网/ 问答频道 /正文

我仍在学习使用PyMC3的基础知识,所以希望这在文档中不会太明显。基本的想法是,我把我的模型放在一起,取样一堆来建立我的后验分布,并保存了链。如果我按照Backends页面的建议加载像trace = pm.backends.text.load('test_txt')这样的链,那么我得到TypeError: No context on context stack。我所期望的是,我能够将text.load方法指向保存的数据库,并且我将获得包含所有跟踪值的numpy数组,也就是说,数据库将包含访问链值所需的所有信息。在

在PyMC3中,我能找到的加载跟踪的唯一示例是here,它显示了用于加载跟踪的同一个模型变量,与创建它时使用的模型变量相同。如果我想有一个脚本来运行我的链和一个单独的脚本来加载和分析跟踪,那么唯一的方法就是在两个文件中用相同的命令初始化模型。这听起来很容易在文件之间产生不一致,但是因为我必须手动保持模型的一致性。在

下面是一个来自PyMC入门页面的示例,我在其中保存了链。我用一个简短的脚本保存了下面的代码。在

import numpy as np
import pymc3 as pm
from scipy import optimize

# Initialize random number generator
np.random.seed(123)

# True parameter values
alpha, sigma = 1, 1
beta = [1, 2.5]

# Size of dataset
size = 100

# Predictor variable
X1 = np.random.randn(size)
X2 = np.random.randn(size) * 0.2

# Simulate outcome variable
Y = alpha + beta[0]*X1 + beta[1]*X2 + np.random.randn(size)*sigma

basic_model = pm.Model()

with basic_model:
    # Priors for unknown model parameters
    alpha = pm.Normal('alpha', mu=0, sd=10)
    beta = pm.Normal('beta', mu=0, sd=10, shape=2)
    sigma = pm.HalfNormal('sigma', sd=1)

    # Expected value of outcome
    mu = alpha + beta[0]*X1 + beta[1]*X2

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

    # obtain starting values via MAP
    start = pm.find_MAP(fmin=optimize.fmin_powell)

    # instantiate sampler
    step = pm.Slice(vars=[sigma])

    # instantiate database
    db = pm.backends.Text('so_save')

    # draw 5000 posterior samples
    trace = pm.sample(5000, step=step, start=start, trace=db)

然后运行下面的行(在pythoncli或在单独的脚本中)可以得到

^{pr2}$

为了获得更多的动机/背景,我尝试用两种稍微不同的方式建模相同的数据。我想有很好的长链为每个模型在磁盘上,我只需生成一次。我想和他们比较一下我想用的方法。在


Tags: of方法模型importalpha脚本sizenp
1条回答
网友
1楼 · 发布于 2024-03-29 05:40:41

简短回答:

使用此项保存跟踪

import pickle # python3
import cPickle as pickle # python 2

with open('my_model.pkl', 'wb') as buff:
    pickle.dump({'model': basic_model, 'trace': trace}, buff)

然后重新加载:

^{pr2}$

长话短说:

有一些关于deprecating the backends的讨论,它们在存储需要长时间运行并且可能超出内存的跟踪的上下文中非常有用。使用持久性后端可以恢复已经完成的工作。哈密顿取样器效率更高,因此更短的记录道就足够了,因此磁盘后端自2016年以来没有收到太多开发时间。在

加载不受信任的pickle文件有一定的危险(如果您在本地运行的话,这不是问题),重新考虑PyMC3的持久性正成为一个优先考虑的问题,但是上面的方法目前应该有效。在

相关问题 更多 >