initial commit
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
## 实现一下重要抽样
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
import scipy as stats
|
||||
import seaborn as sns
|
||||
|
||||
np.random.seed(42)
|
||||
|
||||
def baysian_linear_regression_inportance_sampling():
|
||||
"""
|
||||
使用贝叶斯线性回归方法进行重要抽样
|
||||
|
||||
本例需要估计一个简单的线性回归模型的后验分布
|
||||
|
||||
y = β0 + β1*x + ε, ε ~ N(0, σ²)
|
||||
= [1 x] * [β0 β1]' + ε
|
||||
"""
|
||||
|
||||
# 1. 定义关键数据
|
||||
x = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
|
||||
y = np.array([2.1, 3.9, 6.2, 8.1, 9.8, 12.3, 13.9, 16.2, 17.8, 20.1])
|
||||
n = len(x)
|
||||
|
||||
print(f"数据点数量:{n}")
|
||||
print(f"x: {x}")
|
||||
print(f"y: {y}")
|
||||
|
||||
# 2. 定义先验分布
|
||||
# β0 ~ N(0, 10)
|
||||
beta0_prior_mean = 0
|
||||
beta0_prior_var = 10
|
||||
|
||||
# β1 ~ N(1, 5)
|
||||
beta1_prior_mean = 1
|
||||
beta1_prior_var = 5
|
||||
|
||||
# σ² ~ Inverse-Gamma(2, 1)
|
||||
sigma2_prior_a = 2
|
||||
sigma2_prior_b = 1
|
||||
|
||||
# 3. 定义重要抽样分布
|
||||
# 使用最小二乘进行估计
|
||||
X = np.column_stack([np.ones(n), x])
|
||||
beta_estimate = np.linalg.inv(X.T @ X) @ X.T @ y
|
||||
y_pred = X @ beta_estimate
|
||||
residuals = y - y_pred
|
||||
RSS = residuals.T @ residuals
|
||||
sigma2_estimate = RSS / (n - 2)
|
||||
|
||||
print(f"最小二乘结果:β0 = {beta_estimate[0]}, β1 = {beta_estimate[1]}, σ² = {sigma2_estimate}")
|
||||
print(f"残差平方和 RSS = {RSS}")
|
||||
|
||||
|
||||
|
||||
# 4. 定义联合后验分布(未归一化)
|
||||
def unnormalized_log_posterior(param):
|
||||
"""
|
||||
计算后验概率密度的未归一化值
|
||||
|
||||
param: [β0, β1, log_sigma2)]
|
||||
"""
|
||||
|
||||
beta0, beta1, log_sigma2 = param
|
||||
|
||||
sigma2 = np.exp(log_sigma2)
|
||||
|
||||
# 计算似然函数值
|
||||
y_pred = beta0 + beta1 * x
|
||||
residuals = y - y_pred
|
||||
log_likelihood = -0.5 * n * np.log(2 * np.pi * sigma2) * -0.5 * np.sum(residuals**2) / sigma2
|
||||
|
||||
# 计算先验概率
|
||||
log_prior_beta0 = stats.norm.logpdf(beta0, loc = beta0_prior_mean, scale = np.sqrt(beta0_prior_var))
|
||||
log_prior_beta1 = stats.norm.logpdf(beta1, loc = beta1_prior_mean, scale = np.sqrt(beta1_prior_var))
|
||||
log_prior_sigma2 = stats.invgamma.logpdf(sigma2, a = sigma2_prior_a, scale = sigma2_prior_b) + log_sigma2
|
||||
|
||||
return log_likelihood + log_prior_beta0 + log_prior_beta1 + log_prior_sigma2
|
||||
|
||||
# 5. 定义重要抽样分布
|
||||
proposal_mean = np.array([beta_estimate[0], beta_estimate[1], np.log(sigma2_estimate)])
|
||||
proposal_cov = np.diag([1.0, 1.0, 1.0])
|
||||
|
||||
def log_proposal_density(param):
|
||||
return stats.multivariable_normal.logpdf(param, mean = proposal_mean, cov = proposal_cov)
|
||||
|
||||
# 6. 进行重要抽样
|
||||
num_samples = 10000
|
||||
samples = np.zeros((num_samples, 3))
|
||||
weights = np.zeros(num_samples)
|
||||
log_weights = np.zeros(num_samples)
|
||||
|
||||
for i in range(num_samples):
|
||||
samples[i] = np.random.multivariate_normal(proposal_mean, proposal_cov)
|
||||
unnormalized_log_posterior = unnormalized_log_posterior(samples[i])
|
||||
log_proposal = log_proposal_density(samples[i])
|
||||
log_weights[i] = unnormalized_log_posterior - log_proposal
|
||||
|
||||
weights = np.exp(log_weights)
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
baysian_linear_regression_inportance_sampling()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user