Как определить общую детерминированную функцию в PyMC

В моей модели мне нужно получить значение моей детерминированной переменной из набора родительских переменных, используя сложную функцию Python.

Возможно ли это сделать?

Ниже приведен код pyMC3, который показывает, что я пытаюсь сделать в упрощенном случае.

import numpy as np
import pymc as pm


#Predefine values on two parameter Grid (x,w) for a set of i values (1,2,3)
idata = np.array([1,2,3])
size= 20
gridlength = size*size
Grid = np.empty((gridlength,2+len(idata)))
for x in range(size):
    for w in range(size):
        # A silly version of my real model evaluated on grid.
        Grid[x*size+w,:]= np.array([x,w]+[(x**i + w**i) for i in idata])

# A function to find the nearest value in Grid and return its product with third variable z
def FindFromGrid(x,w,z):
    return Grid[int(x)*size+int(w),2:] * z

#Generate fake Y data with error
yerror = np.random.normal(loc=0.0, scale=9.0, size=len(idata))
ydata = Grid[16*size+12,2:]*3.6 + yerror  # ie. True x= 16, w= 12 and z= 3.6


with pm.Model() as model:

    #Priors
    x = pm.Uniform('x',lower=0,upper= size)
    w = pm.Uniform('w',lower=0,upper =size)
    z = pm.Uniform('z',lower=-5,upper =10)

    #Expected value
    y_hat = pm.Deterministic('y_hat',FindFromGrid(x,w,z))

    #Data likelihood
    ysigmas = np.ones(len(idata))*9.0 
    y_like = pm.Normal('y_like',mu= y_hat, sd=ysigmas, observed=ydata)

    # Inference...
    start = pm.find_MAP() # Find starting value by optimization
    step = pm.NUTS(state=start) # Instantiate MCMC sampling algorithm
    trace = pm.sample(1000, step, start=start, progressbar=False) # draw 1000 posterior samples using NUTS sampling


print('The trace plot')
fig = pm.traceplot(trace, lines={'x': 16, 'w': 12, 'z':3.6})
fig.show()

Когда я запускаю этот код, я получаю сообщение об ошибке на этапе y_hat, потому что для функции int() внутри функции FindFromGrid(x,w,z) требуется целое число, а не FreeRV.

Нахождение y_hat из предварительно рассчитанной сетки важно, потому что моя реальная модель для y_hat не имеет аналитической формы для выражения.

Раньше я пытался использовать OpenBUGS, но узнал здесь это это невозможно сделать в OpenBUGS. Возможно ли это в PyMC?

Обновлять

Основываясь на примере на странице pyMC github, я обнаружил, что мне нужно добавить следующий декоратор к моей функции FindFromGrid(x,w,z).

@pm.theano.compile.ops.as_op(itypes=[t.dscalar, t.dscalar, t.dscalar],otypes=[t.dvector])

Это, кажется, решает вышеупомянутую проблему. Но я больше не могу использовать сэмплер NUTS, так как ему нужен градиент.

Мегаполис, похоже, не сходится.

Какой пошаговый метод следует использовать в подобном сценарии?


person indiajoe    schedule 16.10.2014    source источник


Ответы (1)


Вы нашли правильное решение с as_op.

Что касается сходимости: вы случайно не используете pm.Metropolis() вместо pm.NUTS()? Одна из причин, по которой это не может сойтись, заключается в том, что Metropolis() по умолчанию сэмплирует в совместном пространстве, в то время как Гиббс в Метрополисе часто более эффективен (и это было по умолчанию в pymc2). Сказав это, я просто объединил это: https://github.com/pymc-devs/pymc/pull/587, который меняет стандартное поведение сэмплера Metropolis и Slice на неблокированное по умолчанию (как в Gibbs). Другие сэмплеры, такие как NUTS, которые в первую очередь предназначены для сэмплирования суставного пространства, по умолчанию все еще заблокированы. Вы всегда можете явно установить это с помощью kwarg blocked=True.

В любом случае, обновите pymc самым последним мастером и посмотрите, улучшится ли конвергенция. Если нет, попробуйте сэмплер Slice.

person twiecki    schedule 18.10.2014
comment
Спасибо за помощь. Я предполагаю, что в моем примере модели выше происходит то, что переменные сильно коррелированы. Итак, он застревает в какой-то момент после нескольких цепочек MC. Есть ли способ увеличить размер шага в прыжках МС? Мне также было интересно, почему я получаю ошибку без атрибута grad() для моей функции при использовании pm.find_MAP(), если она использует оптимизацию Нелдера-Мида, которая не требует производных. - person indiajoe; 20.10.2014
comment
Да, find_MAP() с Нелдер-Мидом должно работать. Можете ли вы открыть проблему на github по этому поводу с некоторым кодом для воспроизведения? - person twiecki; 27.10.2014
comment
Что касается застревания, то это проблемы MCMC. Если корреляция является проблемой, вы можете попробовать настроить распределение предложений для Метрополис-Гастингс или просто запустить больше образцов. - person twiecki; 27.10.2014
comment
Спасибо. Я опубликую вопрос в github. - person indiajoe; 28.10.2014