别再死磕线性回归了!用Python+GPyTorch搞定高斯过程预测(附完整代码)

张开发
2026/4/8 7:12:01 15 分钟阅读

分享文章

别再死磕线性回归了!用Python+GPyTorch搞定高斯过程预测(附完整代码)
用PythonGPyTorch解锁高斯过程预测的实战指南想象一下你正在处理一个房价预测问题。传统的线性回归模型给出了一个看似合理的趋势线但它无法告诉你这个预测的可信度有多高在数据稀疏的区域模型的表现会如何这正是高斯过程(Gaussian Process)大显身手的地方。与线性回归不同高斯过程不仅能给出预测值还能量化预测的不确定性——这在商业决策中往往比预测本身更有价值。1. 为什么选择高斯过程而非线性回归线性回归就像用直尺在散点图上画一条直线简单直观但过于理想化。现实世界的数据往往呈现出更复杂的模式非线性关系房价与面积的关系可能是先快后慢的曲线而非简单的直线不确定性量化在数据稀疏的区域如超大户型模型应该给出更不确定的预测自适应平滑度不同区域的数据可能需要不同程度的平滑处理高斯过程通过核函数(kernel)巧妙地解决了这些问题。以常用的RBF核为例# RBF核函数的数学表达式 k(x₁, x₂) σ² exp(-||x₁ - x₂||² / (2l²))其中l控制函数的平滑程度σ控制输出幅度。通过调整这些超参数同一个模型可以适应从剧烈波动到平缓变化的各种数据模式。提示在房价预测中较短的l适合社区房价波动大的城市较长的l适合房价稳定的郊区2. GPyTorch环境搭建与数据准备GPyTorch是基于PyTorch的高斯过程库结合了现代深度学习的灵活性与高斯过程的概率优势。安装非常简单pip install gpytorch pip install torch让我们用波士顿房价数据集演示完整流程。首先准备数据import numpy as np from sklearn.datasets import load_boston from sklearn.preprocessing import StandardScaler boston load_boston() X, y boston.data, boston.target # 选择最具代表性的特征房间数作为演示 X X[:, [5]] # RM: average number of rooms per dwelling y y.reshape(-1, 1) # 标准化数据 scaler StandardScaler() X scaler.fit_transform(X) y (y - y.mean()) / y.std() # 分割训练测试集 train_x torch.tensor(X[:400]).float() train_y torch.tensor(y[:400]).float() test_x torch.tensor(X[400:]).float()3. 构建高斯过程模型的关键步骤GPyTorch采用模块化设计核心组件包括均值函数通常设为常数或零核函数决定模型的灵活性与特性似然函数连接模型输出与观测数据以下是完整模型定义import torch import gpytorch class ExactGPModel(gpytorch.models.ExactGP): def __init__(self, train_x, train_y, likelihood): super().__init__(train_x, train_y, likelihood) self.mean_module gpytorch.means.ConstantMean() self.covar_module gpytorch.kernels.ScaleKernel( gpytorch.kernels.RBFKernel() ) def forward(self, x): mean_x self.mean_module(x) covar_x self.covar_module(x) return gpytorch.distributions.MultivariateNormal(mean_x, covar_x) # 初始化模型 likelihood gpytorch.likelihoods.GaussianLikelihood() model ExactGPModel(train_x, train_y, likelihood)4. 模型训练与超参数优化训练高斯过程本质上是优化核函数超参数和噪声水平# 切换到训练模式 model.train() likelihood.train() # 使用Adam优化器 optimizer torch.optim.Adam(model.parameters(), lr0.1) # 负对数边际似然作为损失函数 mll gpytorch.mlls.ExactMarginalLogLikelihood(likelihood, model) training_iter 50 for i in range(training_iter): optimizer.zero_grad() output model(train_x) loss -mll(output, train_y) loss.backward() optimizer.step() print(fIter {i1}/{training_iter} - Loss: {loss.item():.3f})训练完成后查看学习到的超参数lengthscale model.covar_module.base_kernel.lengthscale.item() outputscale model.covar_module.outputscale.item() noise likelihood.noise.item() print(f学习到的长度尺度(lengthscale): {lengthscale:.3f}) print(f学习到的输出尺度(outputscale): {outputscale:.3f}) print(f学习到的噪声水平(noise): {noise:.3f})这些参数有直观的解释长度尺度值越大表示函数变化越平缓输出尺度控制函数输出的幅度范围噪声水平观测数据中的随机波动程度5. 预测与结果可视化高斯过程的预测不仅给出均值还提供置信区间# 切换到评估模式 model.eval() likelihood.eval() with torch.no_grad(), gpytorch.settings.fast_pred_var(): observed_pred likelihood(model(test_x)) # 获取预测的均值、置信区间 lower, upper observed_pred.confidence_region()可视化结果能清晰展示高斯过程的优势import matplotlib.pyplot as plt plt.figure(figsize(10, 6)) # 绘制训练数据 plt.scatter(train_x.numpy(), train_y.numpy(), ck, label观测数据) # 绘制预测均值 plt.plot(test_x.numpy(), observed_pred.mean.numpy(), b, label预测均值) # 填充置信区间 plt.fill_between( test_x.numpy().flatten(), lower.numpy(), upper.numpy(), alpha0.3, colorb, label95%置信区间 ) plt.xlabel(标准化后的房间数) plt.ylabel(标准化后的房价) plt.legend() plt.show()你会看到在数据密集区域置信区间很窄预测确定性强在数据稀疏区域如极大或极小房间数置信区间自动变宽曲线能自然地跟随数据趋势无需预设函数形式6. 高级技巧与实战建议6.1 核函数的选择艺术不同核函数适合不同数据特性核函数类型适用场景特点RBF核平滑变化的数据无限可微产生平滑曲线Matern核适度波动的数据可调节平滑度(ν参数)周期核周期性数据能捕捉重复模式线性核线性关系退化为贝叶斯线性回归组合多个核函数往往能获得更好效果self.covar_module gpytorch.kernels.ScaleKernel( gpytorch.kernels.RBFKernel() gpytorch.kernels.LinearKernel() )6.2 处理非高斯噪声当数据存在异常值或重尾分布时可改用Student-T似然likelihood gpytorch.likelihoods.StudentTLikelihood()6.3 大规模数据优化对于超过1000个数据点的情况使用近似推断class ApproximateGPModel(gpytorch.models.ApproximateGP): def __init__(self, inducing_points): variational_distribution gpytorch.variational.CholeskyVariationalDistribution( inducing_points.size(0) ) variational_strategy gpytorch.variational.VariationalStrategy( self, inducing_points, variational_distribution ) super().__init__(variational_strategy) # 其余部分与ExactGP类似7. 完整代码示例以下是整合所有步骤的完整代码# 省略导入语句和数据集加载部分见前文 # 1. 模型定义 class ExactGPModel(gpytorch.models.ExactGP): def __init__(self, train_x, train_y, likelihood): super().__init__(train_x, train_y, likelihood) self.mean_module gpytorch.means.ConstantMean() self.covar_module gpytorch.kernels.ScaleKernel( gpytorch.kernels.RBFKernel() gpytorch.kernels.LinearKernel() ) def forward(self, x): mean_x self.mean_module(x) covar_x self.covar_module(x) return gpytorch.distributions.MultivariateNormal(mean_x, covar_x) # 2. 初始化 likelihood gpytorch.likelihoods.GaussianLikelihood() model ExactGPModel(train_x, train_y, likelihood) # 3. 训练 model.train() likelihood.train() optimizer torch.optim.Adam(model.parameters(), lr0.1) mll gpytorch.mlls.ExactMarginalLogLikelihood(likelihood, model) for i in range(50): optimizer.zero_grad() output model(train_x) loss -mll(output, train_y) loss.backward() optimizer.step() # 4. 预测与可视化 model.eval() likelihood.eval() with torch.no_grad(), gpytorch.settings.fast_pred_var(): observed_pred likelihood(model(test_x)) # 可视化代码见前文在实际项目中我发现合理设置初始超参数能显著加快收敛。例如对于标准化后的数据RBF核的初始长度尺度设为1通常是个不错的起点。当数据呈现明显趋势时组合线性核能更好地捕捉全局模式。

更多文章