关于高斯推断,我有一些基本问题。
我有以下数据:
(Log) dose, Number of animals, Number of deaths
-0.86, 5, 0
-0.30, 5, 1
-0.05, 5, 3
0.73, 5, 5
编辑:我假设剂量响应logit(θ)=α+βx的简单回归模型,其中logit(θ)= log(θ/(1-θ))。 θ表示给定剂量x的死亡概率。
我想在(α,β)上创建一个联合正态先验分布,其中α〜N(0,22),β〜N(10,102),并且corr(α,β)= 0.5,然后计算后验先验点周围的点(α:0±4,β:10±20)中的点密度。
首先,我创建了以下的联合正态先验分布:
import numpy as np
from scipy import stats
x = np.array([-0.86, -0.30, -0.05, 0.73])
n = np.array([5, 5, 5, 5])
y = np.array([0, 1, 3, 5])
prior = stats.multivariate_normal([0, 10], [[0.5, 0], [0, 0.5]])
这对吗?
第二,如何计算网格中的后验密度?
答案 0 :(得分:1)
要回答第一个问题,您不正确地设置了正态分布的参数。特别是,您的协方差矩阵并未根据您的描述进行指定。
鉴于标准偏差s_1 = 22
和s_2 = 102
以及所需的相关系数0.5,正确的协方差矩阵为:
--- ---
| s_1*s_1 0.5*s_1*s_2 |
| |
| 0.5*s_1*s_2 s_2*s_2 |
--- ---
即,对角线上的方差和对角线上的协方差。在Numpy / Scipy中,应该是
mu = np.array([0, 10])
s = np.array([[22, 102]])
Rho = np.array([[1, 0.5], [0.5, 1]])
Sigma = Rho * np.outer(s, s)
prior = stats.multivariate_normal(mean=mu, cov=Sigma)
要获得适当归一化的后验密度,需要对连续变量(例如θ)进行边际化(积分),这仅在特殊情况下是可解析解决的,我认为这不是您的情况。因此,您可以算出积分并计算数值逼近,也可以使用某种近似推论方法,例如MCMC或变分推论。有很多很棒的工具,例如PyMC3和PyStan。
仅获取网格上离散点的后验值需要在模型变量上施加条件值。但是,如今,大多数概率编程工具都具有很高的表达能力,因此推断整个后验将变得更加容易,如果您确实有一些特殊的兴趣网格值,请稍后进行检查。
以下是您在PyMC3中的完整后验推断:
import numpy as np
import pymc3 as pm
import theano
import theano.tensor as tt
import matplotlib.pyplot as plt
import arviz as az
# Data
X = np.array([-0.86, -0.30, -0.05, 0.73])
N = np.array([5, 5, 5, 5])
Y = np.array([0, 1, 3, 5])
# augment X for simpler regression expression
X_aug = tt.stack(np.ones_like(X), X).T
# Prior params
mu = np.array([0, 10])
sd = np.array([22, 102])
Rho = np.array([[1, 0.5],[0.5, 1]])
Sigma = np.outer(sd, sd) * Rho
with pm.Model() as binomial_regression:
# regression coefficients (strong prior)
beta = pm.MvNormal('beta', mu=mu, cov=Sigma, shape=2)
# death probability
theta_i = pm.Deterministic('theta_i', pm.invlogit(X_aug.dot(beta)))
# outcomes
y_i = pm.Binomial('y_i', n=N, p=theta_i, observed=Y)
trace = pm.sample(10000, tune=100000, target_accept=0.8, random_seed=2018)
这可以进行抽样,但是需要大量的调整步骤以减少差异:
自动分配NUTS采样器...
使用jitter + adapt_diag初始化NUTS ...
多进程采样(2个作业中的2个链)NUTS:
beta采样2条链:100%|██████████| 220000/220000 [03:52 <00:00, 947.57draws / s]
调整后有1个背离。增加
target_accept
或重新设定参数。对于某些参数,有效样本的数量小于25%。
ax, _, _ = az.jointplot(trace, var_names=['beta'], kind='hexbin')
ax.set_xlabel("Intercept Coefficient ($\\beta_0$)")
ax.set_ylabel("Slope Coefficient ($\\beta_1$)")
plt.show()
答案 1 :(得分:1)
基于merv的好答案,对我自己回答,我认为封闭的解决方案是:
p(yi |α,β,ni,xi)∝ [logit −1 (α+βxi)] y * [1 − logit - 1 (α+βx) n−y ]
因此后验可以计算如下:
import numpy as np
from scipy import optimize, stats
import matplotlib.pyplot as plt
x = np.array([-0.86, -0.30, -0.05, 0.73])
n = np.array([5, 5, 5, 5])
y = np.array([0, 1, 3, 5])
ngrid = 100
mu_1, mu_2, sd_1, sd_2 = 0, 10, 2**2, 10**2
A = np.linspace(-4, 4, ngrid)
B = np.linspace(-10, 30, ngrid)
mu = np.array([0, 10])
s = np.array([[22, 102]])
Rho = np.array([[1, 0.5], [0.5, 1]])
Sigma = Rho * np.outer(s, s)
prior = stats.multivariate_normal([mu_1, mu_2], Sigma)
def prop_likelihood(input_values):
ilogit_abx = 1 / (np.exp(-(input_values[...,0][...,None]*np.ones(x.shape) + input_values[...,1][...,None] * x)) + 1)
return np.prod(ilogit_abx**y * (1 - ilogit_abx)**(n - y), axis=ilogit_abx.ndim -1)
grid_a , grid_b = np.meshgrid(A,B)
grid = np.empty(grid_a.shape + (2,))
grid[:, :, 0] = grid_a
grid[:, :, 1] = grid_b
posterior_density = prior.pdf(grid)*prop_likelihood(grid)
然后可以举例说明:
fig, ax = plt.subplots(figsize=(10, 5)
ax.imshow(
posterior_density,
origin='lower',
aspect='auto',
extent=(A[0], A[-1], B[0], B[-1])
)
ax.set_xlim([-4, 4])
ax.set_ylim([-10, 30])
ax.set_xlabel(r'$\alpha$')
ax.set_ylabel(r'$\beta$')
ax.set_title('Posterior heatmap')
ax.grid('off')
分析解决方案:
def opt(params):
a, b = params[0], params[1]
z = np.exp(a + b * x) / (1 + np.exp(a + b * x))
e = - np.sum(y * np.log(z) + (n - y) * np.log(1 - z))
return e
optim_res = optimize.minimize(opt, np.array([0.0, 0.0]))
mu_opt = optim_res['x']
sigma_opt = optim_res['hess_inv']
posterior_optimized = stats.multivariate_normal(mean=mu_opt, cov=sigma_opt)
然后可以绘制哪个
fig, ax = plt.subplots(figsize=(10, 5)
ax.imshow(
posterior_optimized.pdf(grid),
origin='lower',
aspect='auto',
extent=(A[0], A[-1], B[0], B[-1])
)
ax.set_xlim([-4, 4])
ax.set_ylim([-10, 30])
ax.set_xlabel(r'$\alpha$')
ax.set_ylabel(r'$\beta$')
ax.set_title('Posterior heatmap from analytical solution')
ax.grid('off')
有一些区别。不确定解析优化功能是否正确。
希望这对其他人有帮助。