Pymc3:如何定义参数的有序向量

时间:2017-03-30 09:15:10

标签: python pymc3

我试图进行有序逻辑回归,其中一个参数是切割点的有序向量。我不确定如何定义它们。

我提出的一个非常愚蠢的方法是手动定义向量的每个组件,使用一个作为另一个组合:

with pm.Model() as bound_model:
    a = pm.Normal('a', mu=0, sd=10)
    BoundedB = pm.Bound(pm.Normal, upper=a)
    b = BoundedB('b', mu=0, sd=10)
    BoundedC = pm.Bound(pm.Normal, upper=b)
    c = BoundedC('c', mu=0, sd=10)

    bound_trace = pm.sample(1000)

这几乎没有效率,我不确定它们是否会按预期工作。有更好的方法吗?

1 个答案:

答案 0 :(得分:2)

我猜这是pymc3中缺少的功能。我可能会写一个拉取请求,但在此期间你可以使用这样的东西:

class Ordered(pymc3.distributions.transforms.ElemwiseTransform):
    name = "ordered"

    def forward(self, x):
        out = tt.zeros(x.shape)
        out = tt.inc_subtensor(out[0], x[0])
        out = tt.inc_subtensor(out[1:], tt.log(x[1:] - x[:-1]))
        return out

    def backward(self, y):
        out = tt.zeros(y.shape)
        out = tt.inc_subtensor(out[0], y[0])
        out = tt.inc_subtensor(out[1:], tt.exp(y[1:]))
        return tt.cumsum(out)

    def jacobian_det(self, y):
        return tt.sum(y[1:])

并像这样使用它:

N = 10
with pm.Model() as model:
    pm.Normal('y', mu=np.zeros(N), sd=1, shape=N, 
              transform=Ordered(), testval=np.arange(N))

修改:关于此处发生的事情的非常简短说明:

我们通过

定义从$ R ^ n $到有序序列集的映射
f(x_1) = x_1,\quad f(x_i) = f(x_{i - 1}) + exp(x_i)

由于这是一个很好的双射函数,我们可以通过

计算$ R ^ n $的概率密度
P_{R^n}(x) = P_{ordered}(f(x)) \cdot |J_{f(x)}|

其中J是转换的雅各比。

采样器只能看到无约束的值。这就是Bound首先实现的方式。

如果您想了解更多详情,可以查看stan manual。它包含对这些变换的很好的描述,pymc3和stan的数学是相同的。