高斯过程(GPs)在训练数据范围外的泛化能力疑问
高斯过程(GPs)在训练数据范围外的泛化能力疑问
嗨,我来帮你捋清楚这个问题~你观察到的现象其实是高斯过程(GP)的正常特性,并不是你的算法写错了!
为什么GP在训练范围外预测效果差?
高斯过程的预测核心依赖于**核函数(Kernel)**对输入点之间相似度的衡量。你使用的是平方指数核(也就是你代码里的gaussian_kernel),这个核的特点是:当两个输入点的距离越远,它们的相似度会以指数形式快速衰减。
当测试点超出训练数据的范围(比如你的-10到-5、5到10区间)时,这些点和所有训练点的距离都足够大,核函数输出的相似度几乎为0。这时候GP的预测均值会逐渐收敛到训练数据的均值,而预测方差会急剧增大(你代码里没画方差,但本质上是这样),所以看起来预测结果就“不靠谱”了——这完全是这种核函数的固有属性。
你的代码有没有问题?
我看了你的实现,逻辑是对的:
- 目标函数定义没问题,是多个周期函数的组合
- 训练数据的生成(加噪声)也符合常规做法
- 核函数和GPR的推导实现都正确,加入了噪声项
t3来避免过拟合
如何让GP在训练范围外也能有效预测?
如果你需要在训练数据覆盖的范围之外做可靠预测,可以试试这两个方向:
- 更换核函数:既然你的目标函数是周期性的,使用周期性核(Periodic Kernel),或者把平方指数核和周期性核组合起来。这样GP能学习到函数的周期规律,在训练范围外也能延续这个趋势。
- 补充训练数据:在训练数据里加入一些接近范围边缘甚至稍超出边缘的点,给GP提供一些“外推”的线索,但这种方法的效果不如换核函数直接。
下面是你提供的完整代码,方便参考:
import numpy as np import matplotlib.pyplot as plt def objective(x): return 2 * np.sin(x) + 3 * np.cos(2 * x) + 5 * np.sin(2 / 3 * x) x_train=np.arange(-5, 5, 1) y_train=objective(x_train) for i in range(len(x_train)): y_train[i] += np.random.normal(0, 0.5) plt.plot(x_train,y_train,"x",label="$y_{train}$") plt.legend() plt.show() def gaussian_kernel(x, x_train, t1=1, t2=0.4): xx = (x_train - x) ** 2 return t1 * np.exp(-xx / t2) def gpr(x_test, x_train, y_train, kernel, t3=0.1): mean = y_train.mean() K = [] for x in x_train: K.append(kernel(x, x_train)) K = np.array(K) + np.eye(len(x_train)) * t3 A = np.linalg.inv(K) yy = np.dot(A, y_train - mean) mu = [] var = [] for x in x_test: k = kernel(x, x_train) s = gaussian_kernel(x, [x]) + t3 mu.append(np.dot(k, yy)) var.append(s[0] - np.dot(k, np.dot(A, k.T))) mu = np.array(mu) + mean var = np.array(var) return mu, var x_test = np.arange(-10, 10, 0.01) mu, var = gpr(x_test, x_train, y_train, gaussian_kernel) plt.plot(x_test, mu) plt.plot(x_train, y_train, "x", c="C0") plt.show()
备注:内容来源于stack exchange,提问作者SpaceTAKA
相关产品推荐
相关产品推荐

