python - Scikit-learn:避免高斯过程回归中的过度拟合
问题描述
我正在训练一个高斯过程来学习一组坐标x,y,z
和一些时间序列之间的映射。简而言之,我的问题是关于如何防止我的 GP 做 oerfitting,我正面临着一个奇怪的水平。
一些细节:
我的训练集由 1500 个样本组成。我的测试集包含 500 个样本。每个时间样本有20个时间分量;
对于 GP 使用什么内核,我没有偏好,我希望能帮助我理解哪一个可以更好地工作。此外,我一般对 GP 的经验很少,因此我不确定我在超参数方面做得如何。请参阅下文了解我的设置
length_scale
方式:我按照一些建议进行了设置,但我想知道这是否有意义;我的坐标是标准化的(平均 0,std 1),但我的时间序列不是;
我正在为每个时间分量训练一个高斯过程。
这是我的代码:
from __future__ import division
import numpy as np
from matplotlib import pyplot as plt
from sklearn.gaussian_process import GaussianProcessRegressor
from sklearn.gaussian_process.kernels import (RBF, Matern, RationalQuadratic, ExpSineSquared, DotProduct, ConstantKernel)
# ----------------------------------------------------------------------
number_of_training_samples = 1500
number_of_testing_samples = 500
# read coordinates STANDARDIZED
coords_training_stand = np.loadtxt('coordinates_training_standardized.txt')
coords_testing_stand = np.loadtxt('coordinates_testing_standardized.txt')
# read time series TRAIN/TEST
timeseries_training = np.loadtxt('timeseries_training.txt')
timeseries_testing = np.loadtxt('timeseries_testing.txt')
number_of_time_components = np.shape(timeseries_training)[1] # 20
# Instantiate a Gaussian Process model
kernel = 1.0 * Matern(nu=1.5, length_scale=np.ones(coords_training_stand.shape[1]))
gp = GaussianProcessRegressor(kernel=kernel)
# placeholder for predictions
pred_timeseries_training = np.zeros((np.shape(timeseries_training)))
pred_timeseries_testing = np.zeros((np.shape(timeseries_testing)))
for i in range(number_of_time_components):
print("time component", i)
gp.fit(coords_training_stand, timeseries_training[:,i])
y_pred, sigma = gp.predict(coords_training_stand, return_std=True)
y_pred_test, sigma_test = gp.predict(coords_testing_stand, return_std=True)
pred_timeseries_training[:,i] = y_pred
pred_timeseries_testing[:,i] = y_pred_test
# plot training
fig, ax = plt.subplots(5, figsize=(10,20))
for i in range(5):
ax[i].plot(timeseries_training[100*i, :20], color='blue', label='Original train')
ax[i].plot(pred_timeseries_training[100*i], color='black', label='GP pred train')
ax[i].set_xlabel('Time components', fontsize='x-large')
ax[i].set_ylabel('Amplitude', fontsize='x-large')
ax[i].set_title('Time series n. {:}'.format(100*i+1), fontsize='x-large')
ax[i].legend(fontsize='x-large')
plt.subplots_adjust(hspace=1)
plt.show()
plt.close()
# plot testing
fig, ax = plt.subplots(5, figsize=(10,20))
for i in range(5):
ax[i].plot(timeseries_testing[100*i, :20], color='blue', label='Original test')
ax[i].plot(pred_timeseries_testing[100*i], color='black', label='GP pred test')
ax[i].set_xlabel('Time components', fontsize='x-large')
ax[i].set_ylabel('Amplitude', fontsize='x-large')
ax[i].set_title('Time series n. {:}'.format(1500+100*i+1), fontsize='x-large')
ax[i].legend(fontsize='x-large')
plt.subplots_adjust(hspace=1)
plt.show()
plt.close()
这里是来自 TRAINING 集的几个样本和相应的 GP 预测的图(甚至看不到蓝线,对应于原始样本,因为它们完全被 GP 的预测覆盖):
这里是来自 TESTING 集的一些样本和相应的 GP 预测的图:
(仅在一种情况下 - 1801 - 预测是好的)。我认为存在非常强烈的过度拟合,我想了解如何避免它。
解决方案
我认为问题不在于高斯过程本身,而在于数据集。
时间序列样本是如何生成的?以及如何将数据集划分为训练集和测试集?
如果你得到一个大的时间序列,然后将它切割成小序列,那么模型就没有足够的真实例子来学习,你可能会遇到很大的过拟合问题。
举例说明:
我有一个大时间序列 t0, t1, t2, t3, ..., t99
我用 [t0,...,t19], [t1,...,t20], [t2,...,t21], ..., [t80,..., t99]
在这种情况下,我所有的样本几乎完全相同,这会导致过度拟合。如果验证集由从该数据集中抽取的一些随机样本组成,那么我将获得非常高的验证准确度,因为模型在数据集中看到几乎完全相同的东西。(我认为这就是你给的例如 1801 可能发生的事情)
因此,请确保数据集中的所有样本都是完全独立的。