Как я могу сделать дискретную модель Маркова с pymc?
Я пытаюсь выяснить, как правильно создать целую модель дискретного состояния Маркова с pymc
.
В качестве примера (представление в nbviewer) позволяет создать цепочку длины T = 10, где состояние Маркова двоично, распределение начального состояния [0.2, 0.8] и что вероятность состояний переключения в состоянии 1 равна 0,01, а в состоянии 2 - 0,5
import numpy as np
import pymc as pm
T = 10
prior0 = [0.2, 0.8]
transMat = [[0.99, 0.01], [0.5, 0.5]]
Чтобы создать модель, я создаю массив переменных состояния и массив вероятностей перехода, которые зависят от переменных состояния (с использованием функции pymc.Index)
states = np.empty(T, dtype=object)
states[0] = pm.Categorical('state_0', prior0)
transPs = np.empty(T, dtype=object)
transPs[0] = pm.Index('trans_0', transMat, states[0])
for i in range(1, T):
states[i] = pm.Categorical('state_%i' % i, transPs[i-1])
transPs[i] = pm.Index('trans_%i' %i, transMat, states[i])
Сэмплирование модели показывает, что маргиналы состояний - это то, что они должны быть (по сравнению с моделью, построенной с пакетом BNT Kevin Murphy в Matlab)
model = pm.MCMC([states, transPs])
model.sample(10000, 5000)
[np.mean(model.trace('state_%i' %i)[:]) for i in range(T)]
выдает:
[-----------------100%-----------------] 10000 of 10000 complete in 7.5 sec
[0.80020000000000002,
0.39839999999999998,
0.20319999999999999,
0.1118,
0.064199999999999993,
0.044600000000000001,
0.033000000000000002,
0.026200000000000001,
0.024199999999999999,
0.023800000000000002]
Мой вопрос - это не похоже на самый изящный способ построить цепь Маркова с помощью pymc. Есть ли более чистый способ, который не требует массива детерминированных функций?
Моя цель - написать пакет на основе pymc для более общих динамических байесовских сетей.
Ответы
Ответ 1
Насколько я знаю, вы должны кодировать распределение каждого временного шага как детерминированную функцию предыдущего шага времени, потому что это то, что есть - нет никакой случайности, связанной с параметрами, потому что вы определили их в задаче -до. Тем не менее, я думаю, вы сомневаетесь, возможно, больше в поиске более интуитивного способа представления модели.
Одним из альтернативных способов было бы прямое кодирование переходов временного шага в зависимости от предыдущего шага времени.
from pymc import Bernoulli, MCMC
def generate_timesteps(N,p_init,p_trans):
timesteps=np.empty(N,dtype=object)
# A success denotes being in state 2, a failure being in state 1
timesteps[0]=Bernoulli('T0',p_init)
for i in xrange(1,N):
# probability of being in state 1 at time step `i` given time step `i-1`
p_i = p_trans[1]*timesteps[i-1]+p_trans[0]*(1-timesteps[i-1])
timesteps[i] = Bernoulli('T%d'%i,p_i)
return timesteps
timesteps = generate_timesteps(10,0.8,[0.001,0.5])
model = MCMC(timesteps)
model.sample(10000) # no burn in necessary since we're sampling directly from the distribution
[np.mean( model.trace(t).gettrace() ) for t in timesteps]
Ответ 2
Если вы хотите взглянуть на долговременное поведение вашей цепи Маркова, может оказаться полезным пакет discreteMarkovChain. В примерах приведены некоторые идеи для создания дискретной цепочки Маркова, определяющей функцию перехода, которая сообщает каждому государству о достижимых состояниях на следующем шаге и их вероятностях. Вы можете использовать эту же функцию для имитации процесса.