PyMC3:如何更好地为Theano编写我的自定义分布与观察数据?

时间:2015-06-30 13:01:24

标签: pymc pymc3

我试图在pymc3中实现一个相当简单的模型。要点是我有一些从随机选择序列生成的数据。这些选择可以被认为是一个多项式,并且该过程选择选择作为先前选择的函数。

使用Dirichlet先验模拟类别的总体概率。

必须为手头的数据定制似然函数。数据是从进程输出的0和1的列表。我已经在pymc2中成功制作了模型,你可以在this blog post找到它。这是一个python函数,它为这个问题生成测试数据:

ps = [0.2,0.35,0.25,0.15,0.0498,1/5000]
def make(ps):
    out = []
    while len(out) < 5:
        n_spots = 5-len(out)
        sp = sum(ps[:n_spots+1])
        P = [x/sp for x in ps[:n_spots+1]]
        l = np.argwhere(np.random.multinomial(1,P)==1).ravel()[0]
        #if len(out) == 4:
        #    l = np.argwhere(np.random.multinomial(1,ps[:2])==1).ravel()[0]
        out.extend([1]*l)
        if (out and out[-1] == 1 and len(out) < 5) or l == 0:
            out.append(0)
        #print n_spots, l, len(out)
    assert len(out) == 5
    return out

当我正在学习/转向pymc3时,我正在尝试将观察到的数据输入到自定义似然函数中,并且我在此过程中遇到了几个问题。这可能是因为这是我第一次体验Theano,但我希望有人可以提供一些建议。

这是我的代码(使用上面的make函数):

import numpy as np
import pymc3 as pm
from scipy import optimize
import theano.tensor as T
from theano.compile.ops import as_op
from collections import Counter

# This function gets the attributes of the data that are relevant for calculating the likelihood 
def scan(value):
    groups = []
    prev = False
    s = 0
    for i in xrange(5):
        if value[i] == 0:
            if prev:
                groups.append((s,5-(i-s)))
                prev = False
                s = 0
            else:
                groups.append((0,5-i))
        else:
            prev = True
            s += 1
    if prev:
        groups.append((s,4-(i-s)))
    return groups

# The likelihood calculation for a single data point
def like1(v,p):
    l = 1
    groups = scan(v)
    for n, s in groups:
        l *= p[n]/p[:s+1].sum()
    return T.log(l)

# my custom likelihood class
class CustomDist(pm.distributions.Discrete):
    def __init__(self, ps, data, *args, **kwargs):
        super(CustomDist, self).__init__(*args, **kwargs)
        self.ps = ps
        self.data = data

    def logp(self,v):
        all_l = 0
        for v, k in self.data.items():
            l = like1(v,self.ps)
            all_l += l*k
        return all_l

# model creation
model = pm.Model()

with model:
    probs = pm.Dirichlet('probs',a=np.array([0.5]*6),shape=6,testval=np.array([1/6.0]*6))
    output = CustomDist("rolls",ps=probs,data=data,observed=True)

我能在大约一分钟内找到MAP(我的机器是Windows 7,i7-4790 @ 3.6GHz)。 MAP与输入概率向量匹配良好,这至少意味着模型正确链接。

但是,当我尝试做痕迹时,我的内存使用量猛增(最多几次演出)而我实际上并没有足够耐心地让模型完成编译。我等了10分钟+ NUTS或HMC甚至在追踪之前编译。虽然大都市步进工作得很好(并且比pymc2快得多)。

我是否真的希望Theano能够很好地处理非theano数据的for循环?有没有更好的方法来编写这个代码,以便Theano可以很好地使用它,或者我是有限的,因为我的数据是一个自定义的python类型,不能用数组/矩阵操作进行分析?

提前感谢您的建议和反馈。请让我知道可能需要澄清的内容!

0 个答案:

没有答案