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 例程使用。
- 参数:
- 名称 :
strstr - 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)