PyMC3从正态先验模拟正态贝叶斯后验结果不符,求助排查
我帮你找出了代码里几个关键的问题,正是这些错误导致你的后验结果和预期解析解不匹配:
1. 先验分布的标准差设置错误
你题目里明确说明均值的先验是N(160, 10),但代码里却写成了:
mu = pm.Normal('parameters', mu=160, sd=50)
这里的sd=50完全不符合先验设定。需要注意:正态分布的参数写法如果是N(μ, σ)(σ为标准差),那直接写sd=10;如果题目里的10是方差,那要转换成标准差sd=np.sqrt(10)≈3.16。结合你给出的后验N(195,6.57)的结果,这里应该是先验的标准差为10(方差100),所以先验代码必须修正。
2. 观测数据的似然分布参数错误
你的数据服从N(256, 2301),这里的2301是方差,而PyMC3的pm.Normal默认sd=1,这就导致你最初的代码里,似然的方差被错误设置为1——这会让数据的信息量被无限放大,后验完全被数据主导,得到均值接近256的结果。
当你错误地把2301作为sd传入时,似然的方差变成了2301²,这方差大到数据几乎没有任何信息量,后验就完全被先验主导,回到160。
正确的做法是把方差转换成标准差传入:
observed_data = pm.Normal('observed_data', mu=mu, sd=np.sqrt(2301), observed=df['Cholestoral'])
3. MCMC采样参数不足,可能影响收敛
你当前设置的draws=300、chains=2、tune=300,对于MCMC收敛来说样本量太少,容易导致结果不稳定。建议增加采样次数,比如:
trace = pm.sample(draws=2000, chains=4, tune=1000, cores=4)
这样能确保采样收敛,结果更可靠。
修正后的完整代码
import numpy as np import pandas as pd import pymc3 as pm # 假设df已经加载好目标数据 with pm.Model() as model: # 修正先验:N(160, 10),这里10为标准差 mu = pm.Normal('mu', mu=160, sd=10) # 修正似然:数据方差2301,转换为标准差传入 observed_data = pm.Normal('observed_data', mu=mu, sd=np.sqrt(2301), observed=df['Cholestoral']) # 增加采样数量确保收敛 trace = pm.sample(draws=2000, chains=4, tune=1000, cores=4, discard_tuned_samples=True) # 查看后验统计结果 pm.summary(trace).round(2) # 绘制trace图验证收敛与分布 pm.traceplot(trace)
验证后验结果
修正后,你应该能得到接近N(195,6.57)的后验分布。这里的6.57如果是方差,对应标准差≈2.56;如果是标准差,对应方差≈43.16。你可以通过pm.summary(trace)输出的mean和sd值,直接和解析计算结果对比,也可以用pm.plot_posterior(trace)直观查看后验分布的形态。
内容的提问来源于stack exchange,提问作者emanuele_f

