PyMC3 中的 pm.Potential 是什么?

机器算法验证 贝叶斯 pymc
2022-03-24 03:24:41

我正在阅读Probabilistic Programming & Bayesian Methods for Hackers第 5 章中 的 Price Is Right 示例

上面写着:

示例:针对价格合适的展示进行优化

如果您曾被选为价格合适的参赛者,请祝福您,因为在这里我们将向您展示如何优化您在展示柜上的最终价格。对于那些忘记规则的人:

  1. 两名参赛者在 The Showcase 中竞争。
  2. 每位参赛者都会获得一套独特的奖品。
  3. 观看后,参赛者被要求竞标他们独特的奖品套件的价格。
  4. 如果投标价格高于实际价格,投标的所有者将被取消中标资格。
  5. 如果投标价格低于真实价格低于250美元,获胜者将获得两个奖项。

游戏中的难点在于平衡您对价格的不确定性,将您的出价保持在足够低的水平以免出价过高,并试图以接近价格的价格出价。

假设我们已经记录了之前 The Price is Right 剧集的 Showcases,并且对真实价格遵循的分布有先验信念。为简单起见,假设它遵循 Normal:

True PriceNormal(μp,σp)

在后面的章节中,我们将实际使用真实的 Price is Right Showcase 数据来形成历史先验,但这需要一些高级 PyMC3 使用,所以我们不会在这里使用它。目前,我们假设μp=>35000σp=7500.

我们需要一个模型来说明我们应该如何玩 Showcase。对于奖品套件中的每个奖品,我们都知道它的价格,但这种猜测可能与真实价格有很大不同。(再加上舞台上越来越大的压力,你就会明白为什么有些出价如此疯狂)。假设您对奖品价格的看法也遵循正态分布:

PrizeiNormal(μi,σi),i=1,2

这就是贝叶斯分析很棒的真正原因:我们可以通过μi参数,并表达我们猜测的不确定性σi范围。

为简洁起见,我们假设每个套件有两个奖品,但这可以扩展到任何数量。奖品套房的真实价格由下式给出Prize1+Prize2+ϵ, 在哪里 ϵ是一些错误术语。

我们对更新感兴趣True Price鉴于我们已经观察到这两个奖项并且对它们有信念分布。我们可以使用 PyMC3 执行此操作。

让我们把一些价值观具体化。假设观察到的奖品套件中有两个奖品:

  1. 美妙的加拿大多伦多之旅!
  2. 一个可爱的新吹雪机!

我们对这些物品的真实价格有一些猜测,但我们也不确定它们。我可以通过法线的参数来表达这种不确定性:

snowblowerNormal(3000,500)TorontoNormal(12000,3000)

例如,我认为去多伦多旅行的真实价格是 12 000 美元,并且价格有 68.2% 的机会下跌 1 个标准差,即我相信这次旅行有 68.2% 的机会位于 [9 000, 15 000] 中。

提供的代码如下:

import pymc3 as pm

data_mu = [3e3, 12e3]

data_std = [5e2, 3e3] 

mu_prior = 35e3
std_prior = 75e2

with pm.Model() as model:

    true_price = pm.Normal("true_price", mu=mu_prior, sd=std_prior)

    prize_1 = pm.Normal("first_prize", mu=data_mu[0], sd=data_std[0])
    prize_2 = pm.Normal("second_prize", mu=data_mu[1], sd=data_std[1])
    price_estimate = prize_1 + prize_2

    logp = pm.Normal.dist(mu=price_estimate, sd=(3e3)).logp(true_price)
    error = pm.Potential("error", logp)

    trace = pm.sample(50000, step=pm.Metropolis())
    burned_trace = trace[10000:]

price_trace = burned_trace["true_price"]

我不明白:

  1. true_price搭配如何price_estimate
  2. 是从哪里来sd=(3e3)的?
  3. 什么是pm.Potential对象?

任何帮助将不胜感激。谢谢!

2个回答

我们pm.Potential在这里主要是为了绕过可能性的定义。我们通常以PyMC 文档中描述的方式使用它来限制我们的可能性,但在这个例子中,我们永远不会最终定义一个真正的可能性(这需要包含观察结果)。因此,我们抽取的所有样本都是基于我们如何定义potential.

我们的price_estimate通过本质上使我们的观察值true_price彼此相关。当我们说:potentialtrue_price

logp = pm.Normal.dist(mu=price_estimate, sd=(3e3)).logp(true_price)

我们正在(我们的模拟观察)提供的值上评估平均值为price_estimate、标准差为的正态分布。这模拟了我们可以从中采样以获得后验的可能性。至于作为标准偏差的有效性,我认为这是合理的,因为它是我们用来定义我们这里的组件的标准偏差中的较大者:3e3true_price3e3price_estimate

data_std = [5e2, 3e3]

我保留“error”作为变量的名称,因为 Campm.potential在本章的 PyMC 版本中使用装饰器时就是这样命名函数的。

如果不清楚,请告诉我!

旧版本的 PyMC 文档中有对电位的描述:

http://pymc-devs.github.io/pymc/modelbuilding.html#the-potential-class

据我了解,概率编程包括在高可能性区域进行蒙特卡罗模拟。通常,这种可能性是通过定义一个分布来设置可能性并使用已实现的数据设置观察到的参数来确定的。

例如,在PyMC3 文档中的线性回归示例中。

basic_model = Model()

with basic_model:

    # Priors for unknown model parameters
    alpha = Normal('alpha', mu=0, sd=10)
    beta = Normal('beta', mu=0, sd=10, shape=2)
    sigma = HalfNormal('sigma', sd=1)

    # Expected value of outcome
    mu = alpha + beta[0]*X1 + beta[1]*X2

    # Likelihood (sampling distribution) of observations
    Y_obs = Normal('Y_obs', mu=mu, sd=sigma, observed=Y)

Y_obs是决定似然函数的因素。

您还可以设置自定义似然函数。这就是潜力所在。

我认为这个名字error具有误导性。它应该是可能性(相当于可能性的负数)