2017-06-26 10 views
6

Wciąż uczę się podstaw pracy z PyMC3, więc mam nadzieję, że nie jest to już zbyt boleśnie oczywiste w dokumentacji. Podstawową ideą jest to, że skomponowałem mój model, spróbowałem go, by zbudować moją dystrybucję tylną i uratowałem łańcuchy. Jeśli zastosuję się do sugestii strony Backends, aby załadować łańcuchy takie jak trace = pm.backends.text.load('test_txt'), otrzymam TypeError: No context on context stack. Spodziewałbym się, że będę w stanie wskazać metodę text.load w zapisanej bazie danych i otrzymam numpy tablic ze wszystkimi wartościami śledzenia, tj. Baza danych będzie zawierała wszystkie informacje potrzebne do uzyskania dostępu do wartości łańcucha.Czy można załadować ślad PyMC3 i uzyskać dostęp do wartości bez oryginalnego modelu w pamięci?

Małe polowanie i jedyny przykład ładowania śladu w PyMC3 Mogłem znaleźć here, który pokazuje tę samą zmienną modelu, która jest używana do załadowania śladu, który został użyty do jego utworzenia. Jeśli chciałbym mieć skrypt do uruchamiania moich łańcuchów i osobny skrypt do ładowania i analizowania śladów, to wydaje się, że jedynym sposobem jest zainicjowanie modelu za pomocą tych samych poleceń w obu plikach. Wydaje się to być podatne na tworzenie niespójności między plikami, ponieważ musiałbym jednak zachować identyczność modeli ręcznie.

Oto przykład zaczerpnięty ze strony początkowej PyMC, w której zapisuję łańcuch. Zapisałem poniższy kod w krótkim skrypcie.

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) 

następnie uruchomić te kolejne linie (w tym Python CLI lub w osobnym skrypcie) Daje

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'] 

na trochę więcej motywacji/kontekście, mam eksperymentowanie z modelowania tych samych danych w krótkim czasie kilka nieznacznie różnych sposobów. Chciałbym mieć ładne długie łańcuchy dla każdego modelu na dysku, które muszę tylko raz wygenerować. Wtedy mogę się bawić porównując je w dół, jak myślę o tym, jak chcę analizować ślady.

Odpowiedz

7

Krótka odpowiedź:

Użyj tego, aby zapisać ślad

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) 

a następnie to, aby przeładować:

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

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

Długa odpowiedź:

Poczyniono pewne dyskusja nad deprecating the backends - były użyteczne w kontekście przechowywania śladów tha t musiałaby działać przez długi czas i mogłaby prześcignąć pamięć. Korzystanie z trwałego zaplecza może następnie przywrócić pracę, która została już wykonana. Próbniki Hamiltonian są znacznie wydajniejsze, więc wystarczają krótsze ślady, więc backende na serwerze nie otrzymały dużego czasu na dev od roku 2016.

Istnieje pewne niebezpieczeństwo ładowania niezaufanych plików pikla (nie stanowi to problemu, jeśli pracujesz lokalnie), a priorytetem jest ponowne rozważenie trwałości dla PyMC3, ale powyższe powinno działać na teraz.

+0

Czy chcesz, aby trzeba było ponownie sprawdzić, czy projekt PyMC3 lub pikle Pythona wymagają ponownej analizy? – strwrsdbz

+0

dla PyMC3 - zaktualizowana odpowiedź do disambiguate :) – colcarroll

Powiązane problemy