使用gridsearch优化scikit中的自定义高斯过程内核

时间:2019-11-19 16:33:04

标签: python-3.x machine-learning scikit-learn regression

我正在使用高斯进程,当我使用scikit-learn GP模块时,我很难使用gridsearchcv创建和优化自定义内核。描述此问题的最佳方法是使用classic Mauna Loa example,其中使用已经定义的内核(例如RBFRationalQuadratic的组合来构造适当的内核)。在该示例中,自定义内核的参数未进行优化,而是按照给定的方式进行处理。如果我想运行一个更通用的情况,该情况下我想使用交叉验证来估计那些超参数?我应该如何构造自定义内核,然后构造相应的param_grid对象以进行网格搜索?

以一种非常幼稚的方式,我可以使用这样的东西来构建自定义内核:

def custom_kernel(a,ls,l,alpha,nl):
    kernel = a*RBF(length_scale=ls) \
    + b*RationalQuadratic(length_scale=l,alpha=alpha) \
    + WhiteKernel(noise_level=nl)
    return kernel

但是,当然不能使用以下命令从gridsearchcv调用此函数: GaussianProcessRegressor(kernel=custom_kernel(a,ls,l,alpha,nl))

this SO question中提出了一条可能的前进之路,但是我想知道有没有一种比从头开始编码内核(及其超参数)更容易解决此问题的方法,因为我正在寻找一种结合使用的方法标准内核,还有我想将它们混合的可能性。

1 个答案:

答案 0 :(得分:3)

这就是我走了多远。它回答了这个问题,但是对于Mauna Loa示例来说确实很慢,但是这可能是一个很难使用的数据集:

from sklearn.gaussian_process import GaussianProcessRegressor
from sklearn.model_selection import GridSearchCV
from sklearn.gaussian_process.kernels import ConstantKernel,RBF,WhiteKernel,RationalQuadratic,ExpSineSquared
import numpy as np
from sklearn.datasets import fetch_openml

# from https://scikit-learn.org/stable/auto_examples/gaussian_process/plot_gpr_co2.html
def load_mauna_loa_atmospheric_co2():
    ml_data = fetch_openml(data_id=41187)
    months = []
    ppmv_sums = []
    counts = []

    y = ml_data.data[:, 0]
    m = ml_data.data[:, 1]
    month_float = y + (m - 1) / 12
    ppmvs = ml_data.target

    for month, ppmv in zip(month_float, ppmvs):
        if not months or month != months[-1]:
            months.append(month)
            ppmv_sums.append(ppmv)
            counts.append(1)
        else:
            # aggregate monthly sum to produce average
            ppmv_sums[-1] += ppmv
            counts[-1] += 1

    months = np.asarray(months).reshape(-1, 1)
    avg_ppmvs = np.asarray(ppmv_sums) / counts
    return months, avg_ppmvs

X, y = load_mauna_loa_atmospheric_co2()

# Kernel with parameters given in GPML book
k1 = ConstantKernel(constant_value=66.0**2) * RBF(length_scale=67.0)  # long term smooth rising trend
k2 = ConstantKernel(constant_value=2.4**2) * RBF(length_scale=90.0) \
    * ExpSineSquared(length_scale=1.3, periodicity=1.0)  # seasonal component
# medium term irregularity
k3 = ConstantKernel(constant_value=0.66**2) \
    * RationalQuadratic(length_scale=1.2, alpha=0.78)
k4 = ConstantKernel(constant_value=0.18**2) * RBF(length_scale=0.134) \
    + WhiteKernel(noise_level=0.19**2)  # noise terms
kernel_gpml = k1 + k2 + k3 + k4
gp = GaussianProcessRegressor(kernel=kernel_gpml)

# print parameters
print(gp.get_params())

param_grid = {'alpha': np.logspace(-2, 4, 5),
              'kernel__k1__k1__k1__k1__constant_value': np.logspace(-2, 4, 5),
              'kernel__k1__k1__k1__k2__length_scale': np.logspace(-2, 2, 5),
              'kernel__k2__k2__noise_level':np.logspace(-2, 1, 5)
              }
grid_gp = GridSearchCV(gp,cv=5,param_grid=param_grid,n_jobs=4)
grid_gp.fit(X, y)

帮助我的是,首先将模型初始化为gp = GaussianProcessRegressor(kernel=kernel_gpml),然后使用get_params属性来获取模型超参数的列表。

最后,我注意到Rasmussen和Williams在他们的book中似乎使用了“留一法”交叉验证来调整超参数。