vip_reparametrize#
- pymc_extras.model.transforms.autoreparam.vip_reparametrize(model: Model, var_names: Sequence[str]) tuple[Model, VIP] [source]#
使用变分信息参数化 (VIP) 重新参数化模型。
\[\begin{split}\begin{align*} \eta_{k} &\sim \text{normal}(\lambda_{k} \cdot \mu, \sigma^{\lambda_{k}})\\ \theta_{k} &= \mu + \sigma^{1 - \lambda_{k}} ( \eta_{k} - \lambda_{k} \cdot \mu) \sim \text{normal}(\mu, \sigma). \end{align*}\end{split}\]- 参数:
model (Model) – 具有变量中心参数化的模型。
var_names (Sequence[str]) – 要重新参数化的目标变量。
- 返回:
更新后的模型和 VIP 助手,用于重新参数化或推断模型的参数化。
- 返回类型:
Tuple[Model, VIP]
示例
传统的八所学校。
import pymc as pm import numpy as np J = 8 y = np.array([28.0, 8.0, -3.0, 7.0, -1.0, 1.0, 18.0, 12.0]) sigma = np.array([15.0, 10.0, 16.0, 11.0, 9.0, 11.0, 10.0, 18.0]) with pm.Model() as Centered_eight: mu = pm.Normal("mu", mu=0, sigma=5) tau = pm.HalfCauchy("tau", beta=5) theta = pm.Normal("theta", mu=mu, sigma=tau, shape=J) obs = pm.Normal("obs", mu=theta, sigma=sigma, observed=y)
具有中心参数化的常规模型定义足以使用 VIP。要更改模型参数化,请使用以下函数。
from pymc_extras.model.transforms.autoreparam import vip_reparametrize Reparam_eight, vip = vip_reparametrize(Centered_eight, ["theta"]) with Reparam_eight: # set all parameterizations to cenered (not needed) vip.set_all_lambda(1) # set all parameterizations to non-cenered (desired) vip.set_all_lambda(0) # or per variable vip.set_lambda(theta=0) # just set non-centered parameterization trace = pm.sample()
但是,手动设置并不总是很好的体验,我们可以学习它。
with Reparam_eight: # set all parameterizations to mix of centered and non-centered vip.set_all_lambda(0.5) # fit using ADVI mf = vip.fit(random_seed=42) # display lambdas print(vip.get_lambda()) # {'theta': array([0.01473405, 0.02221006, 0.03656685, 0.03798879, 0.04876761, # 0.0300203 , 0.02733082, 0.01817754])}
现在你可以再次使用采样
with Reparam_eight: trace = pm.sample()
有时启用剪裁是有意义的(默认情况下是关闭的)。 想法是将 \(\varepsilon\) 四舍五入到最接近的极值 (\(0\) 或 \(0\))
\[\begin{split}\hat \lambda_k = \begin{cases} 0, \quad &\lambda_k \le \varepsilon\\ \lambda_k, \quad &\varepsilon \lt \lambda_k \lt 1-\varepsilon\\ 1, \quad &\lambda_k \ge 1-\varepsilon \end{cases}\end{split}\]vip.truncate_all_lambda(0.1)
必须再次执行采样
with Reparam_eight: trace = pm.sample()
参考文献
- 概率程序的自动重新参数化,
Maria I. Gorinova, Dave Moore, Matthew D. Hoffman (2019)