我应该如何在PyMC中使用@pm.stochastic?

1 投票
2 回答
1152 浏览
提问于 2025-05-01 04:51

这是个比较简单的问题:我应该怎么使用 @pm.stochastic? 我看过一些博客,里面说 @pm.stochastic 需要一个负的对数值:

@pm.stochastic(observed=True)
def loglike(value=data):
  # some calculations that generate a numeric result
  return -np.log(result)

我最近试过这个,但结果很糟糕。因为我还注意到,有些人用的是 np.log 而不是 -np.log,所以我也试了一下,结果好多了。@pm.stochastic 其实期待什么呢?我猜可能是因为一个很流行的例子用到了 np.log(1/(1+t_1-t_0)),而写成了 -np.log(1+t_1-t_0),所以对符号有点混淆。

还有一个问题:这个装饰器在 value 参数上到底做了什么?我理解的是,我们从一些提议的先验值开始,这些值需要进入似然函数,而 @pm.stochastic 的基本想法是生成一个数字,用来和采样过程中前一次迭代生成的数字进行比较。似然函数应该接收 value 参数和一些先验值,但我不确定 value 是否仅仅是做这些,因为这是唯一的必需参数,但我可以这样写:

@pm.stochastic(observed=True)
def loglike(value=[1]):
  data = [3,5,1] # some data
  # some calculations that generate a numeric result
  return np.log(result)

就我所知,这样的结果和之前是一样的。也许是因为我在装饰器中加了 observed=True。如果我在一个默认是 observed=False 的随机变量中试这个,value 会在每次迭代中改变,以试图获得更好的似然值。

暂无标签

2 个回答

0

是的,容易让人困惑,因为@stochastic返回的是一种可能性,这实际上是错误的反面。所以你需要对自己定义的错误函数取负对数,然后把这个结果作为你的对数可能性返回。

3

@pm.stochastic 是一个装饰器,它需要一个函数作为输入。最简单的用法就是给它一个函数,这个函数的参数里有 value,并且返回一个对数似然值。

你应该使用 @pm.stochastic 装饰器来为你模型中的参数定义一个自定义的先验。要为数据定义一个自定义的似然,你应该使用 @pm.observed 装饰器。这两个装饰器都会创建一个 pm.Stochastic 对象,这个对象的名字来自于它所装饰的函数,并且拥有所有熟悉的方法和属性(这里有一篇关于Python装饰器的不错的文章)。

例子:

一个参数 a,它的先验分布是三角形分布:

@pm.stochastic
def a(value=.5):
    if 0 <= value < 1:
        return np.log(1.-value)
    else:
        return -np.inf

这里 value=.5 被用作参数的初始值,而将其改为 value=1 会引发异常,因为这个值超出了分布的支持范围。

一个似然 b,它是以 a 为中心的正态分布,精度是固定的:

@pm.observed
def b(value=[.2,.3], mu=a):
    return pm.normal_like(value, mu, 100.)

这里 value=[.2,.3] 用来表示观察到的数据。

我把这些内容整理在一个笔记本里,展示了所有的实际操作

撰写回答