Можно ли загрузить трассировку PyMC3 и получить доступ к значениям без исходной модели в памяти?

Я все еще изучаю основы работы с PyMC3, поэтому, надеюсь, это не слишком болезненно очевидно в документации. Основная идея заключается в том, что я собрал свою модель, отобрал ее для создания моего заднего распределения и сохранил цепочки. Если я последую предложению Backends страница для загрузки сети, как trace = pm.backends.text.load('test_txt') затем я получаю TypeError: No context on context stack. Я ожидал, что смогу указать text.load метод в сохраненной базе данных, и я хотел вернуться массивы numpy со всеми значениями трассировки, т. е. база данных будет содержать всю информацию, необходимую для доступа к цепочке ценностей.

немного охоты и единственный пример загрузки трассировки в PyMC3, который я мог найти, был здесь, и это показывает ту же переменную модели, которая используется для загрузки трассировки, что и для ее создания. Если бы я хотел иметь скрипт для запуска моих цепочек и отдельный скрипт для загрузки и анализа трассировок, кажется, единственный способ-иметь модель инициализируется одними и теми же командами в обоих файлах. Это звучит склонным к созданию несоответствий между файлами, однако, поскольку мне придется вручную сохранять модели идентичными.

вот пример, взятый со страницы начала работы 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)

затем запуск этих следующих строк (на Python CLI или в отдельном скрипте) дает

trace = pm.backends.text.load('so_save')
# TypeError: No context on context stack

trace = pm.backends.text.load('so_save', model=pm.Model())
print trace
print trace.varnames
# <MultiTrace: 1 chains, 5000 iterations, 0 variables>
# []

# run same first 36 lines from the big code block above
trace = pm.backends.text.load('so_save', model=basic_model)
print trace
print trace.varnames
# <MultiTrace: 1 chains, 5000 iterations, 4 variables>
# ['alpha', 'beta', 'sigma_log_', 'sigma']

для немного больше мотивации/контекст, Я экспериментирую с моделированием одних и тех же данных несколькими немного разными способами. Я хотел бы иметь хорошие длинные цепочки для каждой модели на диске, которые мне нужно создать только один раз. Затем я могу поиграть с сравнением их по линии, когда я думаю о том, как я хочу проанализировать следы.

1 ответов


короткий ответ:

используйте это, чтобы сохранить трассировку

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)

и после этого перезагрузку:

with open('my_model.pkl', 'rb') as buff:
    data = pickle.load(buff)  

basic_model, trace = data['model'], data['trace']

ответ:

было некоторое обсуждение над закрывается модули -- они были полезны в контексте хранения следов, которые должны были работать в течение длительного времени и могли опережать память. Использование постоянного бэкэнда может затем восстановить работу, которая уже была сделана. Гамильтоновы сэмплеры намного больше эффективный, поэтому более коротких трассировок достаточно, и поэтому бэкэнды на диске не получили много времени разработки с ~2016.

существует некоторая опасность загрузки ненадежных файлов рассола (не проблема, если вы запускаете вещи локально), и становится приоритетом переосмыслить персистентность для PyMC3, но выше должно работать сейчас.