pymc.CustomDist#
- class pymc.CustomDist(name, *dist_params, dist=None, random=None, logp=None, logcdf=None, moment=None, ndim_supp=0, ndims_params=None, dtype='floatX', **kwargs)[源代码]#
一个用于创建自定义分布的帮助类
此类可用于包装黑盒随机和logp方法,以便在前向和mcmc采样中使用。
用户可以提供一个 dist 函数,该函数返回一个由更简单的 PyMC 分布构建的 PyTensor 图,该图表示分布。此图用于进行随机抽取,并在用户未提供时自动推断 logp 表达式。
另外,用户可以提供一个 random 函数,该函数返回数值抽取结果(例如,通过 NumPy 例程),以及一个 logp 函数,该函数必须返回一个 Python 图,当评估时表示 logp 图。这用于 MCMC 采样。
此外,用户可以提供 logcdf 和 moment 函数,这些函数必须返回一个计算这些量的 PyTensor 图。这些可能会被其他 PyMC 例程使用。
- 参数:
- 名称 :
str
str
- dist_params元组
分布参数的序列。这些将在内部转换为 Pytensor 张量变量。
- dist: Optional[Callable]
一个返回从更简单的 PyMC 分布构建的 PyTensor 图的可调用对象,该图表示分布。PyMC 可以使用它来进行随机抽取,并且在某些情况下推断分布的对数概率。在这种情况下,不需要实现
random
或logp
函数。它必须有以下签名:
dist(*dist_params, size)
。符号张量分布参数作为位置参数传递,顺序与它们在构建CustomDist
时提供的顺序相同。- random可选的[可调用]
一个可调用的函数,用于从分布中生成随机抽样
它必须具有以下签名:
random(*dist_params, rng=None, size=None)
。数值分布参数作为位置参数传递,顺序与它们在构造CustomDist
时提供的顺序相同。关键字参数是rng
,它将提供随机变量关联的Generator
,以及size
,它将表示所需随机抽取的大小。如果为None
,则在尝试从分布的先验或后验预测中抽取随机样本时,将引发NotImplemented
错误。- logp可选的[可调用]
一个计算给定
value
在某些分布参数值条件下的对数概率的可调用对象。它必须具有以下签名:logp(value, *dist_params)
,其中value
是一个表示分布值的 PyTensor 张量,而dist_params
是持有分布参数值的张量。该函数必须返回一个 PyTensor 张量。当指定了 dist 函数时,PyMC 将尝试在没有提供的情况下自动推断 logp。
否则,在尝试计算分布的对数概率时,将引发
NotImplementedError
。- logcdf可选的[可调用]
一个计算给定
value
在某些分布参数值条件下的对数累积概率的可调用对象。它必须具有以下签名:logcdf(value, *dist_params)
,其中value
是一个表示分布值的 PyTensor 张量,而dist_params
是保存分布参数值的张量。此函数必须返回一个 PyTensor 张量。如果为None
,则在尝试计算分布的对数累积分布函数时将引发NotImplementedError
。- moment可选的[可调用]
一个可用于计算分布矩的函数。它必须具有以下签名:
moment(rv, size, *rv_inputs)
。分布的变量作为第一个参数rv
传递。size
是由dims
、size
和提供给分布的参数隐含的随机变量的大小。最后,rv_inputs
是分布参数的序列,顺序与创建 CustomDist 时提供的顺序相同。如果为None
,将分配一个默认的moment
函数,该函数将始终返回 0 或零数组。- ndim_supp
int
分布支持中的维度数量。默认假设为标量分布,即
ndim_supp = 0
。- ndims_params
Optional
[Sequence
[int
]] 每个分布参数支持中的维度数量列表。如果为
None
,则假定所有参数都是标量,因此它们的支持维度数将为 0。如果提供了 PyTensor 分布函数,则不需要此项。- dtype
str
分布的 dtype。所有传递给分布的抽取和观察值都将被转换为此 dtype。如果提供了 PyTensor 分布函数,则不需要此项,因为该函数应已返回正确的 dtype!
- class_name
str
用于包装 CustomDist 方法的类的名称。如果未指定,将使用模型变量的名称。
- kwargs
额外的关键字参数被传递给父类的
__new__
方法。
- 名称 :
示例
创建一个自定义的 CustomDist,它封装了一个黑箱 logp 函数。由于没有提供随机函数,因此该变量不能用于先验或后验预测采样。
import numpy as np import pymc as pm from pytensor.tensor import TensorVariable def logp(value: TensorVariable, mu: TensorVariable) -> TensorVariable: return -(value - mu)**2 with pm.Model(): mu = pm.Normal('mu',0,1) pm.CustomDist( 'custom_dist', mu, logp=logp, observed=np.random.randn(100), ) idata = pm.sample(100)
提供一个返回数值抽取的随机函数。这允许在先验和后验预测采样中使用 CustomDist。
from typing import Optional, Tuple import numpy as np import pymc as pm from pytensor.tensor import TensorVariable def logp(value: TensorVariable, mu: TensorVariable) -> TensorVariable: return -(value - mu)**2 def random( mu: np.ndarray | float, rng: Optional[np.random.Generator] = None, size : Optional[Tuple[int]]=None, ) -> np.ndarray | float : return rng.normal(loc=mu, scale=1, size=size) with pm.Model(): mu = pm.Normal('mu', 0 , 1) pm.CustomDist( 'custom_dist', mu, logp=logp, random=random, observed=np.random.randn(100, 3), size=(100, 3), ) prior = pm.sample_prior_predictive(10)
提供一个 dist 函数,该函数创建一个由其他 PyMC 分布构建的 PyTensor 图。PyMC 可以自动推断出该变量的 logp 对应于一个偏移的指数分布。
import pymc as pm from pytensor.tensor import TensorVariable def dist( lam: TensorVariable, shift: TensorVariable, size: TensorVariable, ) -> TensorVariable: return pm.Exponential.dist(lam, size=size) + shift with pm.Model() as m: lam = pm.HalfNormal("lam") shift = -1 pm.CustomDist( "custom_dist", lam, shift, dist=dist, observed=[-1, -1, 0], ) prior = pm.sample_prior_predictive() posterior = pm.sample()
提供一个 dist 函数,该函数创建一个由其他 PyMC 分布构建的 PyTensor 图。PyMC 可以自动推断出该变量的 logp 对应于一个修正的 PERT 分布。
import pymc as pm from pytensor.tensor import TensorVariable def pert( low: Tensorvariable, peak: Tensorvariable, high: Tensorvariable, lmbda: Tensorvariable, size: Tensorvariable, ) -> Tensorvariable: range = (high - low) s_alpha = 1 + lmbda * (peak - low) / range s_beta = 1 + lmbda * (high - peak) / range return pm.Beta.dist(s_alpha, s_beta, size=size) * range + low with pm.Model() as m: low = pm.Normal("low", 0, 10) peak = pm.Normal("peak", 50, 10) high = pm.Normal("high", 100, 10) lmbda = 4 pm.CustomDist("pert", low, peak, high, lmbda, dist=pert, observed=[30, 35, 73]) m.point_logps()
方法
CustomDist.__init__
(*args, **kwargs)CustomDist.check_valid_dist_random
(dist, ...)CustomDist.dist
(*dist_params[, dist, ...])CustomDist.is_symbolic_random
(random, ...)CustomDist.parse_dist_params
(dist_params)