大数跨境

导师:“高斯过程回归搞懂了吗?”我:“Codex已经跑通了,RMSE也不高!”导师:“那我问你,模型在没有样本的地方还敢这么自信吗?”

导师:“高斯过程回归搞懂了吗?”我:“Codex已经跑通了,RMSE也不高!”导师:“那我问你,模型在没有样本的地方还敢这么自信吗?” 机器学习和人工智能AI
2026-10-20
5

哈喽,大家好~

有同学私信问到:“普通回归只能给我一个预测值,如果我还想知道这个预测靠不靠谱呢?”

其实这时候,高斯过程回归就很合适了。

趁这个机会,我们今天来聊一个自带“不确定性评估”的回归模型,高斯过程回归,简称 GPR。

它不仅能预测结果,还会给出预测区间,告诉我们模型在哪些地方有把握,哪些地方心里没底~

01高斯过程回归

普通线性回归会先假设一个函数形式,比如:

然后再根据数据学习参数 和 。

高斯过程回归的思路不太一样。它不急着确定函数长什么样,而是先假设:可能的函数有很多条,距离相近的样本,其函数值通常也更相似。

随着观测数据不断加入,不符合数据的函数会被淘汰,最后剩下的函数共同形成预测结果。

你可以把它理解成:GPR不是只画一条线,而是在综合很多条合理曲线之后,给出一条平均曲线和一个可信范围。

它比较适合以下场景:

  • 数据量不大,但特征与目标之间存在非线性关系;
  • 除了预测值,还关心预测的不确定性;
  • 样本获取成本高,例如实验优化、传感器建模和贝叶斯优化。

不过它也有一个明显缺点:训练复杂度约为 。数据达到几万甚至几十万条时,直接使用标准GPR就会比较吃力。

02核心原理

相似的输入,得到相似的输出~

高斯过程通常写成:

其中, 是均值函数,表示函数整体趋势; 是核函数,用来衡量两个输入 和 有多相似。

我们这里使用常见的RBF核:

控制函数变化幅度, 叫长度尺度。

越小,模型越关注附近样本,拟合曲线会更灵活; 越大,较远的样本也会互相影响,曲线会更平滑。

假设训练数据为 、 ,测试点为 ,那么预测均值为:

预测协方差为:

这里的 是训练样本之间的核矩阵, 描述训练点和测试点的相似度, 表示观测噪声方差。

一句话概括:测试点越接近训练数据,预测通常越稳定;离训练数据越远,不确定性就越大。

03完整案例

我们下面构造一组带有三个特点的数据:非线性、噪声随 增大、并且中间故意留出一段采样空白。

代码会生成两张分析图~

第一张观察最终拟合效果,第二张比较不同长度尺度对模型的影响。

import numpy as np
import matplotlib.pyplot as plt
from sklearn.gaussian_process import GaussianProcessRegressor
from sklearn.gaussian_process.kernels import RBF, ConstantKernel
from sklearn.metrics import mean_squared_error

np.random.seed(42)

# 真实函数
def true_func(x):
    return 0.45 * x * np.sin(1.6 * x) + 0.8 * np.cos(3.2 * x)

# 生成训练数据,中间[3.4, 4.5]没有样本
x1 = np.random.uniform(0, 3.4, 22)
x2 = np.random.uniform(4.5, 8, 20)
X = np.sort(np.r_[x1, x2]).reshape(-1, 1)

# 异方差噪声:x越大,噪声越明显
noise_std = 0.15 + 0.06 * X.ravel()
y = true_func(X.ravel()) + np.random.normal(0, noise_std)

X_test = np.linspace(-1, 9, 500).reshape(-1, 1)
y_true = true_func(X_test.ravel())

# 常数核控制幅度,RBF核控制平滑程度
kernel = ConstantKernel(
    1.0, (1e-2, 1e2)
) * RBF(
    length_scale=1.0,
    length_scale_bounds=(0.05, 10)
)

gpr = GaussianProcessRegressor(
    kernel=kernel,
    alpha=noise_std ** 2,   # 每个样本对应自己的噪声方差
    normalize_y=True,
    n_restarts_optimizer=8,
    random_state=42
)

gpr.fit(X, y)
mean, std = gpr.predict(X_test, return_std=True)

inside = (X_test.ravel() >= 0) & (X_test.ravel() <= 8)
rmse = mean_squared_error(
    y_true[inside], mean[inside]
) ** 0.5

print("优化后的核函数:", gpr.kernel_)
print("区间[0, 8]上的RMSE:", round(rmse, 4))

# 图1:预测曲线、不确定性和数据空白区
fig, ax = plt.subplots(figsize=(11, 6))
ax.plot(X_test, y_true, "--", color="#00C2FF",
        linewidth=2.2, label="True function")
ax.plot(X_test, mean, color="#FF2E88",
        linewidth=2.6, label="GPR mean")
ax.fill_between(
    X_test.ravel(),
    mean - 1.96 * std,
    mean + 1.96 * std,
    color="#FFD166",
    alpha=0.48,
    label="95% confidence band"
)
ax.scatter(X, y, s=55, color="#6C3BFF",
           edgecolor="white", linewidth=0.8,
           zorder=5, label="Observations")

ax.axvspan(3.4, 4.5, color="#00E5A8", alpha=0.16,
           label="Sampling gap")
ax.axvspan(-1, 0, color="#FF6B35", alpha=0.10)
ax.axvspan(8, 9, color="#FF6B35", alpha=0.10)

ax.set_title("Gaussian Process Regression with Uncertainty")
ax.set_xlabel("x")
ax.set_ylabel("y")
ax.grid(alpha=0.2)
ax.legend(ncol=2)
plt.tight_layout()
plt.show()

# 图2:不同长度尺度下的预测对比
length_scales = [0.25, 1.0, 3.0]
colors = ["#FF2E88", "#00B8D9", "#7C4DFF"]

fig, axes = plt.subplots(1, 3, figsize=(16, 4.8), sharey=True)

for ax, length, color in zip(axes, length_scales, colors):
    fixed_kernel = (
        ConstantKernel(1.0, constant_value_bounds="fixed")
        * RBF(length, length_scale_bounds="fixed")
    )

    model = GaussianProcessRegressor(
        kernel=fixed_kernel,
        alpha=noise_std ** 2,
        normalize_y=True,
        optimizer=None
    )
    model.fit(X, y)
    pred, pred_std = model.predict(X_test, return_std=True)

    ax.plot(X_test, y_true, "--", color="#222222",
            linewidth=1.6, label="True")
    ax.plot(X_test, pred, color=color,
            linewidth=2.4, label="Prediction")
    ax.fill_between(
        X_test.ravel(),
        pred - 1.96 * pred_std,
        pred + 1.96 * pred_std,
        color=color,
        alpha=0.22
    )
    ax.scatter(X, y, s=22, color="#FFB000", edgecolor="white")
    ax.axvspan(3.4, 4.5, color="#00E5A8", alpha=0.12)
    ax.set_title(f"length_scale = {length}")
    ax.set_xlabel("x")
    ax.grid(alpha=0.2)

axes[0].set_ylabel("y")
axes[0].legend()
fig.suptitle("How Length Scale Changes GPR", fontsize=15)
plt.tight_layout()
plt.show()

第一张图中,粉色曲线是预测均值,黄色区域是约95%的置信区间。中间绿色区域没有训练样本,因此置信区间会变宽;在训练范围之外,不确定性也会明显增加。

这正是GPR很有价值的地方:它不会在陌生区域假装自信。

第二张图展示了长度尺度 的影响~

时曲线变化很快,容易追随局部噪声; 时又过于平滑,容易漏掉真实波动;中间值通常能在拟合能力和平滑性之间取得更好的平衡。

实际使用时,可以让模型通过最大化对数边际似然自动寻找核参数,也可以结合交叉验证进一步检查泛化效果。

最后

高斯过程回归的核心,是利用核函数描述样本之间的相似性,同时输出预测均值和不确定性。它在小样本、非线性以及需要风险判断的任务中非常实用。

接下来大家可以尝试更换Matérn核,观察不光滑数据上的效果;也可以把多个核函数相加,分别建模长期趋势、周期变化和局部波动。数据量较大时,则可以继续了解稀疏高斯过程和近似推断。

【声明】内容源于网络
0
0
机器学习和人工智能AI
让我们一起期待 AI 带给我们的每一场变革!推送最新行业内最新最前沿人工智能技术!
内容 432
粉丝 0
机器学习和人工智能AI 让我们一起期待 AI 带给我们的每一场变革!推送最新行业内最新最前沿人工智能技术!
总阅读8.7k
粉丝0
内容432