2015-12-08 2 views
12

Есть ли способ ускорить эту простую модель PyMC? В 20-40 точках данных требуется ~ 5-11 секунд.как ускорить модель марки PyMC?

import pymc 
import time 
import numpy as np 
from collections import OrderedDict 

# prior probability of rain 
p_rain = 0.5 
variables = OrderedDict() 
# rain observations 
data = [True, True, True, True, True, 
     False, False, False, False, False]*4 
num_steps = len(data) 
p_rain_given_rain = 0.9 
p_rain_given_norain = 0.2 
p_umbrella_given_rain = 0.8 
p_umbrella_given_norain = 0.3 
for n in range(num_steps): 
    if n == 0: 
     # Rain node at time t = 0 
     rain = pymc.Bernoulli("rain_%d" %(n), p_rain) 
    else: 
     rain_trans = \ 
      pymc.Lambda("rain_trans", 
         lambda prev_rain=variables["rain_%d" %(n-1)]: \ 
         prev_rain*p_rain_given_rain + (1-prev_rain)*p_rain_given_norain) 
     rain = pymc.Bernoulli("rain_%d" %(n), p=rain_trans) 
    umbrella_obs = \ 
     pymc.Lambda("umbrella_obs", 
        lambda rain=rain: \ 
        rain*p_umbrella_given_rain + (1-rain)*p_umbrella_given_norain) 
    umbrella = pymc.Bernoulli("umbrella_%d" %(n), p=umbrella_obs, 
           observed=True, 
           value=data[n]) 
    variables["rain_%d" %(n)] = rain 
    variables["umbrella_%d" %(n)] = umbrella 

print "running on %d points" %(len(data)) 
all_vars = variables.values() 
t_start = time.time() 
model = pymc.Model(all_vars) 
m = pymc.MCMC(model) 
m.sample(iter=2000) 
t_end = time.time() 
print "\n%.2f secs to run" %(t_end - t_start) 

С точками только 40 данных, он занимает 11 секунд, чтобы запустить:

running on 40 points 
[-----------------100%-----------------] 2000 of 2000 complete in 11.5 sec 
11.54 secs to run 

(с 80 баллами она занимает 20 секунд). Это игрушечный пример. Выражения внутри Lambda(), которые определяют переходы, на практике более сложны. Эта базовая структура кода является гибкой (тогда как кодирование модели с переходными матрицами менее гибко). Есть ли способ сохранить подобную структуру кода, но получить лучшую производительность? С удовольствием переключитесь на PyMC3, если это необходимо. Благодарю.

+0

Какая версия pymc вы используете? В документации pymc для 2.3.6 я не могу найти функцию Бернулли, только Bernoulli_like [Doc] (https://pymc-devs.github.io/pymc/). – CodeMonkey

+0

существует в 2.2 – slushy

+0

У меня есть аналогичная озабоченность по поводу оптимизации (https://stackoverflow.com/questions/42205123/how-to-fit-a-method-belonging-to-an-instance-with-pymc3) –

ответ

3

Markov-Chain Монте-Карло - известная последовательная проблема.

Это означает, что время его выполнения пропорционально количеству шагов и времени выполнения вашей функции фитнеса.

Есть несколько трюков, которые вы можете сделать, однако:

  • Использование PyPy (требуется переписать, pymc не поддерживается)
  • Использование Гиббса выборки, чтобы улучшить ваш следующий шаг
  • Используйте очки многократного пуска (в параллельные)
  • Использование нескольких ветвей (параллельно)
  • использовать эвристический, чтобы остановить цепь ранее
  • Используйте приближение е или точки, близкие к уже вычислены

Harder подходов:

  • Использование Numba (компилирует функцию пригодности к машинному коду)
  • переписать функцию приспособленности в C (или аналогичном)
  • использования родной код MCMC (не-Python, требует вышеуказанного)

Наконец-то есть много исследований:

http://www.mas.ncl.ac.uk/~ndjw1/docs/pbc.pdf

https://sites.google.com/site/parallelmcmc/

http://pyinsci.blogspot.com/2010/12/efficcient-mcmc-in-python.html (PyPy)

+0

Быть ответ на очень общий вопрос, я старался оставаться кратким. Пожалуйста, прокомментируйте специфику ... –

Смежные вопросы