Mauna Loa CO2数据的高斯过程回归(GPR)

此示例基于“用于机器学习的高斯过程”第5.4.3节[RW 2006]。他给出了一个在对数边际似然上用梯度上升法进行复杂核工程和超参数优化的例子。这些数据包括1958年至2001年期间在夏威 Mauna Loa 观测站收集的大气二氧化碳平均浓度(按体积计算,以百万分之数(ppmv)计)。目的是模拟二氧化碳浓度随时间t的变化。

内核由几个术语组成,它们负责解释信号的不同属性:

  • 一个长期的,平稳的上升趋势可以用RBF核来解释。长尺度较大的径向基函数(RBF)内核强制成平滑,没有强制趋势上升,这就留给GP选择。长度、比例尺和振幅是自由的超参数。

  • 季节性因素,由定期的 ExpSineSquared 内核解释,固定周期为1年。 该周期分量的长度尺度控制其平滑度是一个自由参数。 为了使准确周期性的衰减,采用带有RBF内核的产品。 该RBF组件的长度尺寸控制衰减时间,并且是另一个自由参数。

  • 较小的中期不规则性将由 RationalQuadratic 核来解释, RationalQuadratic 内核组件的长度尺度和 alpha 参数决定长度尺度的扩散性。 根据[RW2006],这些不规则性可以更好地由 RationalQuadratic 来解释, 而不是 RBF 核,这可能是因为它可以容纳几个长度尺度。

  • “noise(噪声)” 一词,由一个 RBF 内核贡献组成,它将解释相关的噪声分量,如局部天气现象以及 WhiteKernel 对白噪声的贡献。 相对幅度和RBF的长度尺度是进一步的自由参数。

在减去目标平均值后最大化对数边际似然产生下列内核,其中LML为-83.214:

34.4**2 * RBF(length_scale=41.8)
3.27**2 * RBF(length_scale=180) * ExpSineSquared(length_scale=1.44,
                                                   periodicity=1)
0.446**2 * RationalQuadratic(alpha=17.7, length_scale=0.957)
0.197**2 * RBF(length_scale=0.138) + WhiteKernel(noise_level=0.0336)

因此,大多数目标信号(34.4ppm)由长期上升趋势(长度为41.8年)解释。 周期分量的振幅为3.27ppm,衰减时间为180年,长度为1.44。 长时间的衰变时间表明我们在当地非常接近周期性的季节性成分。 相关噪声的幅度为0.197ppm,长度为0.138年,白噪声贡献为0.197ppm。 因此,整体噪声水平非常小,表明该模型可以很好地解释数据。 该图还显示,该模型直到2015年左右才能做出置信度比较高的预测。

GPML kernel: 66**2 * RBF(length_scale=67) + 2.4**2 * RBF(length_scale=90) * ExpSineSquared(length_scale=1.3, periodicity=1) + 0.66**2 * RationalQuadratic(alpha=0.78, length_scale=1.2) + 0.18**2 * RBF(length_scale=0.134) + WhiteKernel(noise_level=0.0361)
Log-marginal-likelihood: 155.006

Learned kernel: 2.59**2 * RBF(length_scale=51) + 0.257**2 * RBF(length_scale=137) * ExpSineSquared(length_scale=2.15, periodicity=1) + 0.118**2 * RationalQuadratic(alpha=2.32, length_scale=70.6) + 0.03**2 * RBF(length_scale=1.01) + WhiteKernel(noise_level=0.001)
Log-marginal-likelihood: 1161.609
# Authors: Jan Hendrik Metzen <jhm@informatik.uni-bremen.de>
#
# License: BSD 3 clause


import numpy as np

from matplotlib import pyplot as plt
from sklearn.datasets import fetch_openml
from sklearn.gaussian_process import GaussianProcessRegressor
from sklearn.gaussian_process.kernels \
    import RBF, WhiteKernel, RationalQuadratic, ExpSineSquared

print(__doc__)


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(-11)
    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 = 66.0**2 * RBF(length_scale=67.0)  # long term smooth rising trend
k2 = 2.4**2 * RBF(length_scale=90.0) \
    * ExpSineSquared(length_scale=1.3, periodicity=1.0)  # seasonal component
# medium term irregularity
k3 = 0.66**2 \
    * RationalQuadratic(length_scale=1.2, alpha=0.78)
k4 = 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, alpha=0,
                              optimizer=None, normalize_y=True)
gp.fit(X, y)

print("GPML kernel: %s" % gp.kernel_)
print("Log-marginal-likelihood: %.3f"
      % gp.log_marginal_likelihood(gp.kernel_.theta))

# Kernel with optimized parameters
k1 = 50.0**2 * RBF(length_scale=50.0)  # long term smooth rising trend
k2 = 2.0**2 * RBF(length_scale=100.0) \
    * ExpSineSquared(length_scale=1.0, periodicity=1.0,
                     periodicity_bounds="fixed")  # seasonal component
# medium term irregularities
k3 = 0.5**2 * RationalQuadratic(length_scale=1.0, alpha=1.0)
k4 = 0.1**2 * RBF(length_scale=0.1) \
    + WhiteKernel(noise_level=0.1**2,
                  noise_level_bounds=(1e-3, np.inf))  # noise terms
kernel = k1 + k2 + k3 + k4

gp = GaussianProcessRegressor(kernel=kernel, alpha=0,
                              normalize_y=True)
gp.fit(X, y)

print("\nLearned kernel: %s" % gp.kernel_)
print("Log-marginal-likelihood: %.3f"
      % gp.log_marginal_likelihood(gp.kernel_.theta))

X_ = np.linspace(X.min(), X.max() + 301000)[:, np.newaxis]
y_pred, y_std = gp.predict(X_, return_std=True)

# Illustration
plt.scatter(X, y, c='k')
plt.plot(X_, y_pred)
plt.fill_between(X_[:, 0], y_pred - y_std, y_pred + y_std,
                 alpha=0.5, color='k')
plt.xlim(X_.min(), X_.max())
plt.xlabel("Year")
plt.ylabel(r"CO$_2$ in ppm")
plt.title(r"Atmospheric CO$_2$ concentration at Mauna Loa")
plt.tight_layout()
plt.show()

脚本的总运行时间:(0分9.429秒)

Download Python source code: plot_gpr_co2.py

Download Jupyter notebook: plot_gpr_co2.ipynb