简介
本实验使用一个合成数据集来比较两种不同的贝叶斯回归器:自动相关性确定(Automatic Relevance Determination,ARD)和贝叶斯岭回归(Bayesian Ridge Regression)。实验的第一部分通过使用普通最小二乘法(OLS)模型作为基线,将模型的系数与真实系数进行比较。在最后一部分,实验使用多项式特征扩展来拟合 X 和 y 之间的非线性关系,绘制 ARD 和贝叶斯岭回归的预测值和不确定性。
虚拟机使用提示
虚拟机启动完成后,点击左上角切换到“笔记本”标签页,以访问 Jupyter Notebook 进行练习。
有时,你可能需要等待几秒钟让 Jupyter Notebook 完成加载。由于 Jupyter Notebook 的限制,操作验证无法自动化。
如果你在学习过程中遇到问题,随时向 Labby 提问。课程结束后提供反馈,我们会及时为你解决问题。
生成合成数据集
我们生成一个合成数据集,其中 X 和 y 呈线性关联。X 的十个特征将用于生成 y。其他特征对预测 y 没有帮助。此外,我们生成一个 n_samples == n_features 的数据集。这样的设置对 OLS 模型来说具有挑战性,可能会导致权重任意大。对权重施加先验和惩罚可以缓解这个问题。最后,添加高斯噪声。
from sklearn.datasets import make_regression
X, y, true_weights = make_regression(
n_samples=100,
n_features=100,
n_informative=10,
noise=8,
coef=True,
random_state=42,
)
拟合回归器
我们对两个贝叶斯模型和 OLS 进行拟合,以便稍后比较模型的系数。
import pandas as pd
from sklearn.linear_model import ARDRegression, LinearRegression, BayesianRidge
olr = LinearRegression().fit(X, y)
brr = BayesianRidge(compute_score=True, n_iter=30).fit(X, y)
ard = ARDRegression(compute_score=True, n_iter=30).fit(X, y)
df = pd.DataFrame(
{
"Weights of true generative process": true_weights,
"ARDRegression": ard.coef_,
"BayesianRidge": brr.coef_,
"LinearRegression": olr.coef_,
}
)
绘制真实系数与估计系数
我们将每个模型的系数与真实生成模型的权重进行比较。
import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib.colors import SymLogNorm
plt.figure(figsize=(10, 6))
ax = sns.heatmap(
df.T,
norm=SymLogNorm(linthresh=10e-4, vmin=-80, vmax=80),
cbar_kws={"label": "coefficients' values"},
cmap="seismic_r",
)
plt.ylabel("linear model")
plt.xlabel("coefficients")
plt.tight_layout(rect=(0, 0, 1, 0.95))
_ = plt.title("Models' coefficients")
绘制边际对数似然
我们绘制两个模型的边际对数似然。
import numpy as np
ard_scores = -np.array(ard.scores_)
brr_scores = -np.array(brr.scores_)
plt.plot(ard_scores, color="navy", label="ARD")
plt.plot(brr_scores, color="red", label="BayesianRidge")
plt.ylabel("Log-likelihood")
plt.xlabel("Iterations")
plt.xlim(1, 30)
plt.legend()
_ = plt.title("Models log-likelihood")
生成合成数据集
我们创建一个目标,它是输入特征的非线性函数。添加遵循标准均匀分布的噪声。
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import PolynomialFeatures, StandardScaler
rng = np.random.RandomState(0)
n_samples = 110
## 对数据进行排序,以便稍后绘图更方便
X = np.sort(-10 * rng.rand(n_samples) + 10)
noise = rng.normal(0, 1, n_samples) * 1.35
y = np.sqrt(X) * np.sin(X) + noise
full_data = pd.DataFrame({"input_feature": X, "target": y})
X = X.reshape((-1, 1))
## 外推
X_plot = np.linspace(10, 10.4, 10)
y_plot = np.sqrt(X_plot) * np.sin(X_plot)
X_plot = np.concatenate((X, X_plot.reshape((-1, 1))))
y_plot = np.concatenate((y - noise, y_plot))
拟合回归器
我们尝试使用 10 次多项式来可能地过拟合,尽管贝叶斯线性模型会对多项式系数的大小进行正则化。由于 ARDRegression 和 BayesianRidge 默认fit_intercept=True,那么 PolynomialFeatures 不应引入额外的偏差特征。通过设置return_std=True,贝叶斯回归器会返回模型参数后验分布的标准差。
ard_poly = make_pipeline(
PolynomialFeatures(degree=10, include_bias=False),
StandardScaler(),
ARDRegression(),
).fit(X, y)
brr_poly = make_pipeline(
PolynomialFeatures(degree=10, include_bias=False),
StandardScaler(),
BayesianRidge(),
).fit(X, y)
y_ard, y_ard_std = ard_poly.predict(X_plot, return_std=True)
y_brr, y_brr_std = brr_poly.predict(X_plot, return_std=True)
绘制带有分数标准误差的多项式回归
误差线表示查询点预测高斯分布的一个标准差。请注意,在两个模型中使用默认参数时,ARD 回归最能捕捉到真实情况,但进一步减小贝叶斯岭的lambda_init超参数可以减少其偏差。最后,由于多项式回归的固有局限性,两个模型在外推时都会失败。
ax = sns.scatterplot(
data=full_data, x="input_feature", y="target", color="black", alpha=0.75
)
ax.plot(X_plot, y_plot, color="black", label="Ground Truth")
ax.plot(X_plot, y_brr, color="red", label="BayesianRidge with polynomial features")
ax.plot(X_plot, y_ard, color="navy", label="ARD with polynomial features")
ax.fill_between(
X_plot.ravel(),
y_ard - y_ard_std,
y_ard + y_ard_std,
color="navy",
alpha=0.3,
)
ax.fill_between(
X_plot.ravel(),
y_brr - y_brr_std,
y_brr + y_brr_std,
color="red",
alpha=0.3,
)
ax.legend()
_ = ax.set_title("Polynomial fit of a non-linear feature")
总结
本实验使用合成数据集比较了两种不同的贝叶斯回归器。实验的第一部分通过使用普通最小二乘法(OLS)模型作为基线,将模型的系数与真实系数进行比较。在最后一部分,实验使用多项式特征扩展来拟合X和y之间的非线性关系,绘制了 ARD 和贝叶斯岭回归的预测结果和不确定性。