如何在PyMC3中用Python函数创建Deterministic变量(替代@pm.deterministic)
Hey there! Great question—this is a super common gotcha when moving from older PyMC versions to PyMC3, since the @pm.deterministic decorator was completely removed in the switch. Let me break down the two main ways to replicate that functionality in PyMC3, with examples that align with what you'd see in Bayesian Methods for Hackers:
1. Simple Deterministic Calculations (No Explicit Registration Needed)
If your deterministic transformation is straightforward and you don't need to explicitly track it in your sampling trace, you can just compute it directly within your model context. PyMC3 automatically recognizes these as deterministic nodes tied to your random variables.
For example, if your old PyMC2 code looked like this:
@pm.deterministic def scaled_data(x=observed_data): return x * 0.5 + 2
In PyMC3, you'd rewrite it as:
with pm.Model() as model: # First define your random variables x = pm.Normal('x', mu=0, sigma=1, observed=observed_data) # Just compute the deterministic value directly scaled_data = x * 0.5 + 2
PyMC3 will handle tracking this node under the hood, so you can use it in other parts of your model (like likelihoods) without extra work.
2. Explicitly Registered Deterministic Variables (For Trace Tracking)
If you need to save the deterministic variable's values in your sampling trace (to visualize or analyze later), use the pm.Deterministic class. This replaces the decorator by explicitly registering the variable with your model and giving it a name.
Let's use a classic example from the book—say you're computing a ratio of two gamma-distributed variables:
Old PyMC2 code:
@pm.deterministic def theta(alpha=alpha_prior, beta=beta_prior): return alpha / (alpha + beta)
In PyMC3, this becomes:
with pm.Model() as model: # Define your priors first alpha_prior = pm.Gamma('alpha_prior', alpha=1, beta=1) beta_prior = pm.Gamma('beta_prior', alpha=1, beta=1) # Explicitly register the deterministic variable theta = pm.Deterministic('theta', alpha_prior / (alpha_prior + beta_prior))
Now, after sampling, you can access the trace of theta just like any other variable:
with model: trace = pm.sample(2000) # View the posterior of theta pm.plot_posterior(trace['theta'])
Bonus: Complex Deterministic Functions
If your deterministic logic is more involved (multiple steps, conditional logic, etc.), you can define a helper function and call it inside pm.Deterministic—just make sure to use PyMC's math functions (pm.math) instead of standard Python math to keep things compatible with PyMC3's tensor operations:
def calculate_log_odds(a, b): ratio = a / (a + b) # Use pm.math for tensor-compatible operations return pm.math.log(ratio / (1 - ratio)) with pm.Model() as model: alpha = pm.Gamma('alpha', alpha=2, beta=1) beta = pm.Gamma('beta', alpha=2, beta=1) log_odds = pm.Deterministic('log_odds', calculate_log_odds(alpha, beta))
The key takeaway is that PyMC3 simplifies deterministic variables by either letting you compute them on the fly or explicitly registering them when you need to track their posterior samples.
内容的提问来源于stack exchange,提问作者RSHAP




