
.. DO NOT EDIT.
.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY.
.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE:
.. "auto_examples/gaussian_process/plot_gpr_co2.py"
.. LINE NUMBERS ARE GIVEN BELOW.

.. only:: html

    .. note::
        :class: sphx-glr-download-link-note

        :ref:`Go to the end <sphx_glr_download_auto_examples_gaussian_process_plot_gpr_co2.py>`
        to download the full example code or to run this example in your browser via JupyterLite or Binder.

.. rst-class:: sphx-glr-example-title

.. _sphx_glr_auto_examples_gaussian_process_plot_gpr_co2.py:


====================================================================================
Forecasting of CO2 level on Mona Loa dataset using Gaussian process regression (GPR)
====================================================================================

This example is based on Section 5.4.3 of "Gaussian Processes for Machine
Learning" [1]_. It illustrates an example of complex kernel engineering
and hyperparameter optimization using gradient ascent on the
log-marginal-likelihood. The data consists of the monthly average atmospheric
CO2 concentrations (in parts per million by volume (ppm)) collected at the
Mauna Loa Observatory in Hawaii, between 1958 and 2001. The objective is to
model the CO2 concentration as a function of the time :math:`t` and extrapolate
for years after 2001.

.. rubric:: References

.. [1] `Rasmussen, Carl Edward. "Gaussian processes in machine learning."
    Summer school on machine learning. Springer, Berlin, Heidelberg, 2003
    <http://www.gaussianprocess.org/gpml/chapters/RW.pdf>`_.

.. GENERATED FROM PYTHON SOURCE LINES 21-25

.. code-block:: Python


    # Authors: The scikit-learn developers
    # SPDX-License-Identifier: BSD-3-Clause








.. GENERATED FROM PYTHON SOURCE LINES 26-34

Build the dataset
-----------------

We will derive a dataset from the Mauna Loa Observatory that collected air
samples. We are interested in estimating the concentration of CO2 and
extrapolate it for further years. First, we load the original dataset available
in OpenML as a pandas dataframe. This will be replaced with Polars
once `fetch_openml` adds a native support for it.

.. GENERATED FROM PYTHON SOURCE LINES 34-39

.. code-block:: Python

    from sklearn.datasets import fetch_openml

    co2 = fetch_openml(data_id=41187, as_frame=True)
    co2.frame.head()






.. raw:: html

    <div class="output_subarea output_html rendered_html output_result">
    <div>
    <style scoped>
        .dataframe tbody tr th:only-of-type {
            vertical-align: middle;
        }

        .dataframe tbody tr th {
            vertical-align: top;
        }

        .dataframe thead th {
            text-align: right;
        }
    </style>
    <table border="1" class="dataframe">
      <thead>
        <tr style="text-align: right;">
          <th></th>
          <th>year</th>
          <th>month</th>
          <th>day</th>
          <th>weight</th>
          <th>flag</th>
          <th>station</th>
          <th>co2</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <th>0</th>
          <td>1958</td>
          <td>3</td>
          <td>29</td>
          <td>4</td>
          <td>0</td>
          <td>MLO</td>
          <td>316.1</td>
        </tr>
        <tr>
          <th>1</th>
          <td>1958</td>
          <td>4</td>
          <td>5</td>
          <td>6</td>
          <td>0</td>
          <td>MLO</td>
          <td>317.3</td>
        </tr>
        <tr>
          <th>2</th>
          <td>1958</td>
          <td>4</td>
          <td>12</td>
          <td>4</td>
          <td>0</td>
          <td>MLO</td>
          <td>317.6</td>
        </tr>
        <tr>
          <th>3</th>
          <td>1958</td>
          <td>4</td>
          <td>19</td>
          <td>6</td>
          <td>0</td>
          <td>MLO</td>
          <td>317.5</td>
        </tr>
        <tr>
          <th>4</th>
          <td>1958</td>
          <td>4</td>
          <td>26</td>
          <td>2</td>
          <td>0</td>
          <td>MLO</td>
          <td>316.4</td>
        </tr>
      </tbody>
    </table>
    </div>
    </div>
    <br />
    <br />

.. GENERATED FROM PYTHON SOURCE LINES 40-42

First, we process the original dataframe to create a date column and select
it along with the CO2 column.

.. GENERATED FROM PYTHON SOURCE LINES 42-49

.. code-block:: Python

    import polars as pl

    co2_data = pl.DataFrame(co2.frame[["year", "month", "day", "co2"]]).select(
        pl.date("year", "month", "day"), "co2"
    )
    co2_data.head()






.. raw:: html

    <div class="output_subarea output_html rendered_html output_result">
    <div><style>
    .dataframe > thead > tr,
    .dataframe > tbody > tr {
      text-align: right;
      white-space: pre-wrap;
    }
    </style>
    <small>shape: (5, 2)</small><table border="1" class="dataframe"><thead><tr><th>date</th><th>co2</th></tr><tr><td>date</td><td>f64</td></tr></thead><tbody><tr><td>1958-03-29</td><td>316.1</td></tr><tr><td>1958-04-05</td><td>317.3</td></tr><tr><td>1958-04-12</td><td>317.6</td></tr><tr><td>1958-04-19</td><td>317.5</td></tr><tr><td>1958-04-26</td><td>316.4</td></tr></tbody></table></div>
    </div>
    <br />
    <br />

.. GENERATED FROM PYTHON SOURCE LINES 50-52

.. code-block:: Python

    co2_data["date"].min(), co2_data["date"].max()





.. rst-class:: sphx-glr-script-out

 .. code-block:: none


    (datetime.date(1958, 3, 29), datetime.date(2001, 12, 29))



.. GENERATED FROM PYTHON SOURCE LINES 53-56

We see that we get CO2 concentration for some days from March, 1958 to
December, 2001. We can plot the raw information to have a better
understanding.

.. GENERATED FROM PYTHON SOURCE LINES 56-63

.. code-block:: Python

    import matplotlib.pyplot as plt

    plt.plot(co2_data["date"], co2_data["co2"])
    plt.xlabel("date")
    plt.ylabel("CO$_2$ concentration (ppm)")
    _ = plt.title("Raw air samples measurements from the Mauna Loa Observatory")




.. image-sg:: /auto_examples/gaussian_process/images/sphx_glr_plot_gpr_co2_001.png
   :alt: Raw air samples measurements from the Mauna Loa Observatory
   :srcset: /auto_examples/gaussian_process/images/sphx_glr_plot_gpr_co2_001.png
   :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 64-67

We will preprocess the dataset by taking a monthly average and drop months
for which no measurements were collected. Such a processing will have a
smoothing effect on the data.

.. GENERATED FROM PYTHON SOURCE LINES 67-81

.. code-block:: Python


    co2_data = (
        co2_data.sort(by="date")
        .group_by_dynamic("date", every="1mo")
        .agg(pl.col("co2").mean())
        .drop_nulls()
    )
    plt.plot(co2_data["date"], co2_data["co2"])
    plt.xlabel("date")
    plt.ylabel("Monthly average of CO$_2$ concentration (ppm)")
    _ = plt.title(
        "Monthly average of air samples measurements\nfrom the Mauna Loa Observatory"
    )




.. image-sg:: /auto_examples/gaussian_process/images/sphx_glr_plot_gpr_co2_002.png
   :alt: Monthly average of air samples measurements from the Mauna Loa Observatory
   :srcset: /auto_examples/gaussian_process/images/sphx_glr_plot_gpr_co2_002.png
   :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 82-88

The idea in this example will be to predict the CO2 concentration in function
of the date. We are as well interested in extrapolating for upcoming year
after 2001.

As a first step, we will divide the data and the target to estimate. The data
being a date, we will convert it into a numeric.

.. GENERATED FROM PYTHON SOURCE LINES 88-93

.. code-block:: Python

    X = co2_data.select(
        pl.col("date").dt.year() + pl.col("date").dt.month() / 12
    ).to_numpy()
    y = co2_data["co2"].to_numpy()








.. GENERATED FROM PYTHON SOURCE LINES 94-108

Design the proper kernel
------------------------

To design the kernel to use with our Gaussian process, we can make some
assumption regarding the data at hand. We observe that they have several
characteristics: we see a long term rising trend, a pronounced seasonal
variation and some smaller irregularities. We can use different appropriate
kernel that would capture these features.

First, the long term rising trend could be fitted using a radial basis
function (RBF) kernel with a large length-scale parameter. The RBF kernel
with a large length-scale enforces this component to be smooth. A trending
increase is not enforced as to give a degree of freedom to our model. The
specific length-scale and the amplitude are free hyperparameters.

.. GENERATED FROM PYTHON SOURCE LINES 108-112

.. code-block:: Python

    from sklearn.gaussian_process.kernels import RBF

    long_term_trend_kernel = 50.0**2 * RBF(length_scale=50.0)








.. GENERATED FROM PYTHON SOURCE LINES 113-120

The seasonal variation is explained by the periodic exponential sine squared
kernel with a fixed periodicity of 1 year. The length-scale of this periodic
component, controlling its smoothness, is a free parameter. In order to allow
decaying away from exact periodicity, the product with an RBF kernel is
taken. The length-scale of this RBF component controls the decay time and is
a further free parameter. This type of kernel is also known as locally
periodic kernel.

.. GENERATED FROM PYTHON SOURCE LINES 120-128

.. code-block:: Python

    from sklearn.gaussian_process.kernels import ExpSineSquared

    seasonal_kernel = (
        2.0**2
        * RBF(length_scale=100.0)
        * ExpSineSquared(length_scale=1.0, periodicity=1.0, periodicity_bounds="fixed")
    )








.. GENERATED FROM PYTHON SOURCE LINES 129-134

The small irregularities are to be explained by a rational quadratic kernel
component, whose length-scale and alpha parameter, which quantifies the
diffuseness of the length-scales, are to be determined. A rational quadratic
kernel is equivalent to an RBF kernel with several length-scale and will
better accommodate the different irregularities.

.. GENERATED FROM PYTHON SOURCE LINES 134-138

.. code-block:: Python

    from sklearn.gaussian_process.kernels import RationalQuadratic

    irregularities_kernel = 0.5**2 * RationalQuadratic(length_scale=1.0, alpha=1.0)








.. GENERATED FROM PYTHON SOURCE LINES 139-144

Finally, the noise in the dataset can be accounted with a kernel consisting
of an RBF kernel contribution, which shall explain the correlated noise
components such as local weather phenomena, and a white kernel contribution
for the white noise. The relative amplitudes and the RBF's length scale are
further free parameters.

.. GENERATED FROM PYTHON SOURCE LINES 144-150

.. code-block:: Python

    from sklearn.gaussian_process.kernels import WhiteKernel

    noise_kernel = 0.1**2 * RBF(length_scale=0.1) + WhiteKernel(
        noise_level=0.1**2, noise_level_bounds=(1e-5, 1e5)
    )








.. GENERATED FROM PYTHON SOURCE LINES 151-152

Thus, our final kernel is an addition of all previous kernel.

.. GENERATED FROM PYTHON SOURCE LINES 152-157

.. code-block:: Python

    co2_kernel = (
        long_term_trend_kernel + seasonal_kernel + irregularities_kernel + noise_kernel
    )
    co2_kernel





.. rst-class:: sphx-glr-script-out

 .. code-block:: none


    50**2 * RBF(length_scale=50) + 2**2 * RBF(length_scale=100) * ExpSineSquared(length_scale=1, periodicity=1) + 0.5**2 * RationalQuadratic(alpha=1, length_scale=1) + 0.1**2 * RBF(length_scale=0.1) + WhiteKernel(noise_level=0.01)



.. GENERATED FROM PYTHON SOURCE LINES 158-167

Model fitting and extrapolation
-------------------------------

Now, we are ready to use a Gaussian process regressor and fit the available
data. To follow the example from the literature, we will subtract the mean
from the target. We could have used `normalize_y=True`. However, doing so
would have also scaled the target (dividing `y` by its standard deviation).
Thus, the hyperparameters of the different kernel would have had different
meaning since they would not have been expressed in ppm.

.. GENERATED FROM PYTHON SOURCE LINES 167-173

.. code-block:: Python

    from sklearn.gaussian_process import GaussianProcessRegressor

    y_mean = y.mean()
    gaussian_process = GaussianProcessRegressor(kernel=co2_kernel, normalize_y=False)
    gaussian_process.fit(X, y - y_mean)






.. raw:: html

    <div class="output_subarea output_html rendered_html output_result">
    <style>#sk-container-id-39 {
      /* Definition of color scheme common for light and dark mode */
      --sklearn-color-text: #000;
      --sklearn-color-text-muted: #666;
      --sklearn-color-line: gray;
      /* Definition of color scheme for unfitted estimators */
      --sklearn-color-unfitted-level-0: #fff5e6;
      --sklearn-color-unfitted-level-1: #f6e4d2;
      --sklearn-color-unfitted-level-2: #ffe0b3;
      --sklearn-color-unfitted-level-3: chocolate;
      /* Definition of color scheme for fitted estimators */
      --sklearn-color-fitted-level-0: #f0f8ff;
      --sklearn-color-fitted-level-1: #d4ebff;
      --sklearn-color-fitted-level-2: #b3dbfd;
      --sklearn-color-fitted-level-3: cornflowerblue;
    }

    #sk-container-id-39.light {
      /* Specific color for light theme */
      --sklearn-color-text-on-default-background: black;
      --sklearn-color-background: white;
      --sklearn-color-border-box: black;
      --sklearn-color-icon: #696969;
    }

    #sk-container-id-39.dark {
      --sklearn-color-text-on-default-background: white;
      --sklearn-color-background: #111;
      --sklearn-color-border-box: white;
      --sklearn-color-icon: #878787;
    }

    #sk-container-id-39 {
      color: var(--sklearn-color-text);
    }

    #sk-container-id-39 pre {
      padding: 0;
    }

    #sk-container-id-39 input.sk-hidden--visually {
      border: 0;
      clip: rect(1px 1px 1px 1px);
      clip: rect(1px, 1px, 1px, 1px);
      height: 1px;
      margin: -1px;
      overflow: hidden;
      padding: 0;
      position: absolute;
      width: 1px;
    }

    #sk-container-id-39 div.sk-dashed-wrapped {
      border: 1px dashed var(--sklearn-color-line);
      margin: 0 0.4em 0.5em 0.4em;
      box-sizing: border-box;
      padding-bottom: 0.4em;
      background-color: var(--sklearn-color-background);
    }

    #sk-container-id-39 div.sk-container {
      /* jupyter's `normalize.less` sets `[hidden] { display: none; }`
         but bootstrap.min.css set `[hidden] { display: none !important; }`
         so we also need the `!important` here to be able to override the
         default hidden behavior on the sphinx rendered scikit-learn.org.
         See: https://github.com/scikit-learn/scikit-learn/issues/21755 */
      display: inline-block !important;
      position: relative;
    }

    #sk-container-id-39 div.sk-text-repr-fallback {
      display: none;
    }

    div.sk-parallel-item,
    div.sk-serial,
    div.sk-item {
      /* draw centered vertical line to link estimators */
      background-image: linear-gradient(var(--sklearn-color-text-on-default-background), var(--sklearn-color-text-on-default-background));
      background-size: 2px 100%;
      background-repeat: no-repeat;
      background-position: center center;
    }

    /* Parallel-specific style estimator block */

    #sk-container-id-39 div.sk-parallel-item::after {
      content: "";
      width: 100%;
      border-bottom: 2px solid var(--sklearn-color-text-on-default-background);
      flex-grow: 1;
    }

    #sk-container-id-39 div.sk-parallel {
      display: flex;
      align-items: stretch;
      justify-content: center;
      background-color: var(--sklearn-color-background);
      position: relative;
    }

    #sk-container-id-39 div.sk-parallel-item {
      display: flex;
      flex-direction: column;
    }

    #sk-container-id-39 div.sk-parallel-item:first-child::after {
      align-self: flex-end;
      width: 50%;
    }

    #sk-container-id-39 div.sk-parallel-item:last-child::after {
      align-self: flex-start;
      width: 50%;
    }

    #sk-container-id-39 div.sk-parallel-item:only-child::after {
      width: 0;
    }

    /* Serial-specific style estimator block */

    #sk-container-id-39 div.sk-serial {
      display: flex;
      flex-direction: column;
      align-items: center;
      background-color: var(--sklearn-color-background);
      padding-right: 1em;
      padding-left: 1em;
    }


    /* Toggleable style: style used for estimator/Pipeline/ColumnTransformer box that is
    clickable and can be expanded/collapsed.
    - Pipeline and ColumnTransformer use this feature and define the default style
    - Estimators will overwrite some part of the style using the `sk-estimator` class
    */

    /* Pipeline and ColumnTransformer style (default) */

    #sk-container-id-39 div.sk-toggleable {
      /* Default theme specific background. It is overwritten whether we have a
      specific estimator or a Pipeline/ColumnTransformer */
      background-color: var(--sklearn-color-background);
    }

    /* Toggleable label */
    #sk-container-id-39 label.sk-toggleable__label {
      cursor: pointer;
      display: flex;
      width: 100%;
      margin-bottom: 0;
      padding: 0.5em;
      box-sizing: border-box;
      text-align: center;
      align-items: center;
      justify-content: center;
      gap: 0.5em;
    }

    #sk-container-id-39 label.sk-toggleable__label .caption {
      font-size: 0.6rem;
      font-weight: lighter;
      color: var(--sklearn-color-text-muted);
    }

    #sk-container-id-39 label.sk-toggleable__label-arrow:before {
      /* Arrow on the left of the label */
      content: "▸";
      float: left;
      margin-right: 0.25em;
      color: var(--sklearn-color-icon);
    }

    #sk-container-id-39 label.sk-toggleable__label-arrow:hover:before {
      color: var(--sklearn-color-text);
    }

    /* Toggleable content - dropdown */

    #sk-container-id-39 div.sk-toggleable__content {
      display: none;
      text-align: left;
      /* unfitted */
      background-color: var(--sklearn-color-unfitted-level-0);
    }

    #sk-container-id-39 div.sk-toggleable__content.fitted {
      /* fitted */
      background-color: var(--sklearn-color-fitted-level-0);
    }

    #sk-container-id-39 div.sk-toggleable__content pre {
      margin: 0.2em;
      border-radius: 0.25em;
      color: var(--sklearn-color-text);
      /* unfitted */
      background-color: var(--sklearn-color-unfitted-level-0);
    }

    #sk-container-id-39 div.sk-toggleable__content.fitted pre {
      /* unfitted */
      background-color: var(--sklearn-color-fitted-level-0);
    }

    #sk-container-id-39 input.sk-toggleable__control:checked~div.sk-toggleable__content {
      /* Expand drop-down */
      display: block;
      width: 100%;
      overflow: visible;
    }

    #sk-container-id-39 input.sk-toggleable__control:checked~label.sk-toggleable__label-arrow:before {
      content: "▾";
    }

    /* Pipeline/ColumnTransformer-specific style */

    #sk-container-id-39 div.sk-label input.sk-toggleable__control:checked~label.sk-toggleable__label {
      color: var(--sklearn-color-text);
      background-color: var(--sklearn-color-unfitted-level-2);
    }

    #sk-container-id-39 div.sk-label.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {
      background-color: var(--sklearn-color-fitted-level-2);
    }

    /* Estimator-specific style */

    /* Colorize estimator box */
    #sk-container-id-39 div.sk-estimator input.sk-toggleable__control:checked~label.sk-toggleable__label {
      /* unfitted */
      background-color: var(--sklearn-color-unfitted-level-2);
    }

    #sk-container-id-39 div.sk-estimator.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {
      /* fitted */
      background-color: var(--sklearn-color-fitted-level-2);
    }

    #sk-container-id-39 div.sk-label label.sk-toggleable__label,
    #sk-container-id-39 div.sk-label label {
      /* The background is the default theme color */
      color: var(--sklearn-color-text-on-default-background);
    }

    /* On hover, darken the color of the background */
    #sk-container-id-39 div.sk-label:hover label.sk-toggleable__label {
      color: var(--sklearn-color-text);
      background-color: var(--sklearn-color-unfitted-level-2);
    }

    /* Label box, darken color on hover, fitted */
    #sk-container-id-39 div.sk-label.fitted:hover label.sk-toggleable__label.fitted {
      color: var(--sklearn-color-text);
      background-color: var(--sklearn-color-fitted-level-2);
    }

    /* Estimator label */

    #sk-container-id-39 div.sk-label label {
      font-family: monospace;
      font-weight: bold;
      line-height: 1.2em;
    }

    #sk-container-id-39 div.sk-label-container {
      text-align: center;
    }

    /* Estimator-specific */
    #sk-container-id-39 div.sk-estimator {
      font-family: monospace;
      border: 1px dotted var(--sklearn-color-border-box);
      border-radius: 0.25em;
      box-sizing: border-box;
      margin-bottom: 0.5em;
      /* unfitted */
      background-color: var(--sklearn-color-unfitted-level-0);
    }

    #sk-container-id-39 div.sk-estimator.fitted {
      /* fitted */
      background-color: var(--sklearn-color-fitted-level-0);
    }

    /* on hover */
    #sk-container-id-39 div.sk-estimator:hover {
      /* unfitted */
      background-color: var(--sklearn-color-unfitted-level-2);
    }

    #sk-container-id-39 div.sk-estimator.fitted:hover {
      /* fitted */
      background-color: var(--sklearn-color-fitted-level-2);
    }

    /* Specification for estimator info (e.g. "i" and "?") */

    /* Common style for "i" and "?" */

    .sk-estimator-doc-link,
    a:link.sk-estimator-doc-link,
    a:visited.sk-estimator-doc-link {
      float: right;
      font-size: smaller;
      line-height: 1em;
      font-family: monospace;
      background-color: var(--sklearn-color-unfitted-level-0);
      border-radius: 1em;
      height: 1em;
      width: 1em;
      text-decoration: none !important;
      margin-left: 0.5em;
      text-align: center;
      /* unfitted */
      border: var(--sklearn-color-unfitted-level-3) 1pt solid;
      color: var(--sklearn-color-unfitted-level-3);
    }

    .sk-estimator-doc-link.fitted,
    a:link.sk-estimator-doc-link.fitted,
    a:visited.sk-estimator-doc-link.fitted {
      /* fitted */
      background-color: var(--sklearn-color-fitted-level-0);
      border: var(--sklearn-color-fitted-level-3) 1pt solid;
      color: var(--sklearn-color-fitted-level-3);
    }

    /* On hover */
    div.sk-estimator:hover .sk-estimator-doc-link:hover,
    .sk-estimator-doc-link:hover,
    div.sk-label-container:hover .sk-estimator-doc-link:hover,
    .sk-estimator-doc-link:hover {
      /* unfitted */
      background-color: var(--sklearn-color-unfitted-level-3);
      border: var(--sklearn-color-fitted-level-0) 1pt solid;
      color: var(--sklearn-color-unfitted-level-0);
      text-decoration: none;
    }

    div.sk-estimator.fitted:hover .sk-estimator-doc-link.fitted:hover,
    .sk-estimator-doc-link.fitted:hover,
    div.sk-label-container:hover .sk-estimator-doc-link.fitted:hover,
    .sk-estimator-doc-link.fitted:hover {
      /* fitted */
      background-color: var(--sklearn-color-fitted-level-3);
      border: var(--sklearn-color-fitted-level-0) 1pt solid;
      color: var(--sklearn-color-fitted-level-0);
      text-decoration: none;
    }

    /* Span, style for the box shown on hovering the info icon */
    .sk-estimator-doc-link span {
      display: none;
      z-index: 9999;
      position: relative;
      font-weight: normal;
      right: .2ex;
      padding: .5ex;
      margin: .5ex;
      width: min-content;
      min-width: 20ex;
      max-width: 50ex;
      color: var(--sklearn-color-text);
      box-shadow: 2pt 2pt 4pt #999;
      /* unfitted */
      background: var(--sklearn-color-unfitted-level-0);
      border: .5pt solid var(--sklearn-color-unfitted-level-3);
    }

    .sk-estimator-doc-link.fitted span {
      /* fitted */
      background: var(--sklearn-color-fitted-level-0);
      border: var(--sklearn-color-fitted-level-3);
    }

    .sk-estimator-doc-link:hover span {
      display: block;
    }

    /* "?"-specific style due to the `<a>` HTML tag */

    #sk-container-id-39 a.estimator_doc_link {
      float: right;
      font-size: 1rem;
      line-height: 1em;
      font-family: monospace;
      background-color: var(--sklearn-color-unfitted-level-0);
      border-radius: 1rem;
      height: 1rem;
      width: 1rem;
      text-decoration: none;
      /* unfitted */
      color: var(--sklearn-color-unfitted-level-1);
      border: var(--sklearn-color-unfitted-level-1) 1pt solid;
    }

    #sk-container-id-39 a.estimator_doc_link.fitted {
      /* fitted */
      background-color: var(--sklearn-color-fitted-level-0);
      border: var(--sklearn-color-fitted-level-1) 1pt solid;
      color: var(--sklearn-color-fitted-level-1);
    }

    /* On hover */
    #sk-container-id-39 a.estimator_doc_link:hover {
      /* unfitted */
      background-color: var(--sklearn-color-unfitted-level-3);
      color: var(--sklearn-color-background);
      text-decoration: none;
    }

    #sk-container-id-39 a.estimator_doc_link.fitted:hover {
      /* fitted */
      background-color: var(--sklearn-color-fitted-level-3);
    }

    .estimator-table {
        font-family: monospace;
    }

    .estimator-table summary {
        padding: .5rem;
        cursor: pointer;
    }

    .estimator-table summary::marker {
        font-size: 0.7rem;
    }

    .estimator-table details[open] {
        padding-left: 0.1rem;
        padding-right: 0.1rem;
        padding-bottom: 0.3rem;
    }

    .estimator-table .parameters-table {
        margin-left: auto !important;
        margin-right: auto !important;
        margin-top: 0;
    }

    .estimator-table .parameters-table tr:nth-child(odd) {
        background-color: #fff;
    }

    .estimator-table .parameters-table tr:nth-child(even) {
        background-color: #f6f6f6;
    }

    .estimator-table .parameters-table tr:hover {
        background-color: #e0e0e0;
    }

    .estimator-table table td {
        border: 1px solid rgba(106, 105, 104, 0.232);
    }

    /*
        `table td`is set in notebook with right text-align.
        We need to overwrite it.
    */
    .estimator-table table td.param {
        text-align: left;
        position: relative;
        padding: 0;
    }

    .user-set td {
        color:rgb(255, 94, 0);
        text-align: left !important;
    }

    .user-set td.value {
        color:rgb(255, 94, 0);
        background-color: transparent;
    }

    .default td {
        color: black;
        text-align: left !important;
    }

    .user-set td i,
    .default td i {
        color: black;
    }

    /*
        Styles for parameter documentation links
        We need styling for visited so jupyter doesn't overwrite it
    */
    a.param-doc-link,
    a.param-doc-link:link,
    a.param-doc-link:visited {
        text-decoration: underline dashed;
        text-underline-offset: .3em;
        color: inherit;
        display: block;
        padding: .5em;
    }

    /* "hack" to make the entire area of the cell containing the link clickable */
    a.param-doc-link::before {
        position: absolute;
        content: "";
        inset: 0;
    }

    .param-doc-description {
        display: none;
        position: absolute;
        z-index: 9999;
        left: 0;
        padding: .5ex;
        margin-left: 1.5em;
        color: var(--sklearn-color-text);
        box-shadow: .3em .3em .4em #999;
        width: max-content;
        text-align: left;
        max-height: 10em;
        overflow-y: auto;

        /* unfitted */
        background: var(--sklearn-color-unfitted-level-0);
        border: thin solid var(--sklearn-color-unfitted-level-3);
    }

    /* Fitted state for parameter tooltips */
    .fitted .param-doc-description {
        /* fitted */
        background: var(--sklearn-color-fitted-level-0);
        border: thin solid var(--sklearn-color-fitted-level-3);
    }

    .param-doc-link:hover .param-doc-description {
        display: block;
    }

    .copy-paste-icon {
        background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NDggNTEyIj48IS0tIUZvbnQgQXdlc29tZSBGcmVlIDYuNy4yIGJ5IEBmb250YXdlc29tZSAtIGh0dHBzOi8vZm9udGF3ZXNvbWUuY29tIExpY2Vuc2UgLSBodHRwczovL2ZvbnRhd2Vzb21lLmNvbS9saWNlbnNlL2ZyZWUgQ29weXJpZ2h0IDIwMjUgRm9udGljb25zLCBJbmMuLS0+PHBhdGggZD0iTTIwOCAwTDMzMi4xIDBjMTIuNyAwIDI0LjkgNS4xIDMzLjkgMTQuMWw2Ny45IDY3LjljOSA5IDE0LjEgMjEuMiAxNC4xIDMzLjlMNDQ4IDMzNmMwIDI2LjUtMjEuNSA0OC00OCA0OGwtMTkyIDBjLTI2LjUgMC00OC0yMS41LTQ4LTQ4bDAtMjg4YzAtMjYuNSAyMS41LTQ4IDQ4LTQ4ek00OCAxMjhsODAgMCAwIDY0LTY0IDAgMCAyNTYgMTkyIDAgMC0zMiA2NCAwIDAgNDhjMCAyNi41LTIxLjUgNDgtNDggNDhMNDggNTEyYy0yNi41IDAtNDgtMjEuNS00OC00OEwwIDE3NmMwLTI2LjUgMjEuNS00OCA0OC00OHoiLz48L3N2Zz4=);
        background-repeat: no-repeat;
        background-size: 14px 14px;
        background-position: 0;
        display: inline-block;
        width: 14px;
        height: 14px;
        cursor: pointer;
    }
    </style><body><div id="sk-container-id-39" class="sk-top-container"><div class="sk-text-repr-fallback"><pre>GaussianProcessRegressor(kernel=50**2 * RBF(length_scale=50) + 2**2 * RBF(length_scale=100) * ExpSineSquared(length_scale=1, periodicity=1) + 0.5**2 * RationalQuadratic(alpha=1, length_scale=1) + 0.1**2 * RBF(length_scale=0.1) + WhiteKernel(noise_level=0.01))</pre><b>In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. <br />On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.</b></div><div class="sk-container" hidden><div class="sk-item"><div class="sk-estimator fitted sk-toggleable"><input class="sk-toggleable__control sk-hidden--visually" id="sk-estimator-id-162" type="checkbox" checked><label for="sk-estimator-id-162" class="sk-toggleable__label fitted sk-toggleable__label-arrow"><div><div>GaussianProcessRegressor</div></div><div><a class="sk-estimator-doc-link fitted" rel="noreferrer" target="_blank" href="https://scikit-learn.org/1.8/modules/generated/sklearn.gaussian_process.GaussianProcessRegressor.html">?<span>Documentation for GaussianProcessRegressor</span></a><span class="sk-estimator-doc-link fitted">i<span>Fitted</span></span></div></label><div class="sk-toggleable__content fitted" data-param-prefix="">
            <div class="estimator-table">
                <details>
                    <summary>Parameters</summary>
                    <table class="parameters-table">
                      <tbody>
                    
            <tr class="user-set">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('kernel',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">
            <a class="param-doc-link"
                rel="noreferrer" target="_blank" href="https://scikit-learn.org/1.8/modules/generated/sklearn.gaussian_process.GaussianProcessRegressor.html#:~:text=kernel,-kernel%20instance%2C%20default%3DNone">
                kernel
                <span class="param-doc-description">kernel: kernel instance, default=None<br><br>The kernel specifying the covariance function of the GP. If None is<br>passed, the kernel ``ConstantKernel(1.0, constant_value_bounds="fixed")<br>* RBF(1.0, length_scale_bounds="fixed")`` is used as default. Note that<br>the kernel hyperparameters are optimized during fitting unless the<br>bounds are marked as "fixed".</span>
            </a>
        </td>
                <td class="value">50**2 * RBF(l...se_level=0.01)</td>
            </tr>
    

            <tr class="default">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('alpha',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">
            <a class="param-doc-link"
                rel="noreferrer" target="_blank" href="https://scikit-learn.org/1.8/modules/generated/sklearn.gaussian_process.GaussianProcessRegressor.html#:~:text=alpha,-float%20or%20ndarray%20of%20shape%20%28n_samples%2C%29%2C%20default%3D1e-10">
                alpha
                <span class="param-doc-description">alpha: float or ndarray of shape (n_samples,), default=1e-10<br><br>Value added to the diagonal of the kernel matrix during fitting.<br>This can prevent a potential numerical issue during fitting, by<br>ensuring that the calculated values form a positive definite matrix.<br>It can also be interpreted as the variance of additional Gaussian<br>measurement noise on the training observations. Note that this is<br>different from using a `WhiteKernel`. If an array is passed, it must<br>have the same number of entries as the data used for fitting and is<br>used as datapoint-dependent noise level. Allowing to specify the<br>noise level directly as a parameter is mainly for convenience and<br>for consistency with :class:`~sklearn.linear_model.Ridge`.<br>For an example illustrating how the alpha parameter controls<br>the noise variance in Gaussian Process Regression, see<br>:ref:`sphx_glr_auto_examples_gaussian_process_plot_gpr_noisy_targets.py`.</span>
            </a>
        </td>
                <td class="value">1e-10</td>
            </tr>
    

            <tr class="default">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('optimizer',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">
            <a class="param-doc-link"
                rel="noreferrer" target="_blank" href="https://scikit-learn.org/1.8/modules/generated/sklearn.gaussian_process.GaussianProcessRegressor.html#:~:text=optimizer,-%22fmin_l_bfgs_b%22%2C%20callable%20or%20None%2C%20default%3D%22fmin_l_bfgs_b%22">
                optimizer
                <span class="param-doc-description">optimizer: "fmin_l_bfgs_b", callable or None, default="fmin_l_bfgs_b"<br><br>Can either be one of the internally supported optimizers for optimizing<br>the kernel's parameters, specified by a string, or an externally<br>defined optimizer passed as a callable. If a callable is passed, it<br>must have the signature::<br><br>    def optimizer(obj_func, initial_theta, bounds):<br>        # * 'obj_func': the objective function to be minimized, which<br>        #   takes the hyperparameters theta as a parameter and an<br>        #   optional flag eval_gradient, which determines if the<br>        #   gradient is returned additionally to the function value<br>        # * 'initial_theta': the initial value for theta, which can be<br>        #   used by local optimizers<br>        # * 'bounds': the bounds on the values of theta<br>        ....<br>        # Returned are the best found hyperparameters theta and<br>        # the corresponding value of the target function.<br>        return theta_opt, func_min<br><br>Per default, the L-BFGS-B algorithm from `scipy.optimize.minimize`<br>is used. If None is passed, the kernel's parameters are kept fixed.<br>Available internal optimizers are: `{'fmin_l_bfgs_b'}`.</span>
            </a>
        </td>
                <td class="value">&#x27;fmin_l_bfgs_b&#x27;</td>
            </tr>
    

            <tr class="default">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('n_restarts_optimizer',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">
            <a class="param-doc-link"
                rel="noreferrer" target="_blank" href="https://scikit-learn.org/1.8/modules/generated/sklearn.gaussian_process.GaussianProcessRegressor.html#:~:text=n_restarts_optimizer,-int%2C%20default%3D0">
                n_restarts_optimizer
                <span class="param-doc-description">n_restarts_optimizer: int, default=0<br><br>The number of restarts of the optimizer for finding the kernel's<br>parameters which maximize the log-marginal likelihood. The first run<br>of the optimizer is performed from the kernel's initial parameters,<br>the remaining ones (if any) from thetas sampled log-uniform randomly<br>from the space of allowed theta-values. If greater than 0, all bounds<br>must be finite. Note that `n_restarts_optimizer == 0` implies that one<br>run is performed.</span>
            </a>
        </td>
                <td class="value">0</td>
            </tr>
    

            <tr class="default">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('normalize_y',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">
            <a class="param-doc-link"
                rel="noreferrer" target="_blank" href="https://scikit-learn.org/1.8/modules/generated/sklearn.gaussian_process.GaussianProcessRegressor.html#:~:text=normalize_y,-bool%2C%20default%3DFalse">
                normalize_y
                <span class="param-doc-description">normalize_y: bool, default=False<br><br>Whether or not to normalize the target values `y` by removing the mean<br>and scaling to unit-variance. This is recommended for cases where<br>zero-mean, unit-variance priors are used. Note that, in this<br>implementation, the normalisation is reversed before the GP predictions<br>are reported.<br><br>.. versionchanged:: 0.23</span>
            </a>
        </td>
                <td class="value">False</td>
            </tr>
    

            <tr class="default">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('copy_X_train',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">
            <a class="param-doc-link"
                rel="noreferrer" target="_blank" href="https://scikit-learn.org/1.8/modules/generated/sklearn.gaussian_process.GaussianProcessRegressor.html#:~:text=copy_X_train,-bool%2C%20default%3DTrue">
                copy_X_train
                <span class="param-doc-description">copy_X_train: bool, default=True<br><br>If True, a persistent copy of the training data is stored in the<br>object. Otherwise, just a reference to the training data is stored,<br>which might cause predictions to change if the data is modified<br>externally.</span>
            </a>
        </td>
                <td class="value">True</td>
            </tr>
    

            <tr class="default">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('n_targets',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">
            <a class="param-doc-link"
                rel="noreferrer" target="_blank" href="https://scikit-learn.org/1.8/modules/generated/sklearn.gaussian_process.GaussianProcessRegressor.html#:~:text=n_targets,-int%2C%20default%3DNone">
                n_targets
                <span class="param-doc-description">n_targets: int, default=None<br><br>The number of dimensions of the target values. Used to decide the number<br>of outputs when sampling from the prior distributions (i.e. calling<br>:meth:`sample_y` before :meth:`fit`). This parameter is ignored once<br>:meth:`fit` has been called.<br><br>.. versionadded:: 1.3</span>
            </a>
        </td>
                <td class="value">None</td>
            </tr>
    

            <tr class="default">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('random_state',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">
            <a class="param-doc-link"
                rel="noreferrer" target="_blank" href="https://scikit-learn.org/1.8/modules/generated/sklearn.gaussian_process.GaussianProcessRegressor.html#:~:text=random_state,-int%2C%20RandomState%20instance%20or%20None%2C%20default%3DNone">
                random_state
                <span class="param-doc-description">random_state: int, RandomState instance or None, default=None<br><br>Determines random number generation used to initialize the centers.<br>Pass an int for reproducible results across multiple function calls.<br>See :term:`Glossary <random_state>`.</span>
            </a>
        </td>
                <td class="value">None</td>
            </tr>
    

            <tr class="user-set">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('kernel__k1',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">kernel__k1</td>
                <td class="value">50**2 * RBF(l...ength_scale=1)</td>
            </tr>
    

            <tr class="user-set">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('kernel__k2',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">kernel__k2</td>
                <td class="value">0.1**2 * RBF(...se_level=0.01)</td>
            </tr>
    

            <tr class="user-set">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('kernel__k1__k1',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">kernel__k1__k1</td>
                <td class="value">50**2 * RBF(l...periodicity=1)</td>
            </tr>
    

            <tr class="user-set">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('kernel__k1__k2',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">kernel__k1__k2</td>
                <td class="value">0.5**2 * Rati...ength_scale=1)</td>
            </tr>
    

            <tr class="user-set">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('kernel__k1__k1__k1',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">kernel__k1__k1__k1</td>
                <td class="value">50**2 * RBF(length_scale=50)</td>
            </tr>
    

            <tr class="user-set">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('kernel__k1__k1__k2',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">kernel__k1__k1__k2</td>
                <td class="value">2**2 * RBF(le...periodicity=1)</td>
            </tr>
    

            <tr class="user-set">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('kernel__k1__k1__k1__k1',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">kernel__k1__k1__k1__k1</td>
                <td class="value">50**2</td>
            </tr>
    

            <tr class="user-set">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('kernel__k1__k1__k1__k2',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">kernel__k1__k1__k1__k2</td>
                <td class="value">RBF(length_scale=50)</td>
            </tr>
    

            <tr class="user-set">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('kernel__k1__k1__k1__k1__constant_value',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">kernel__k1__k1__k1__k1__constant_value</td>
                <td class="value">2500.0</td>
            </tr>
    

            <tr class="user-set">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('kernel__k1__k1__k1__k1__constant_value_bounds',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">kernel__k1__k1__k1__k1__constant_value_bounds</td>
                <td class="value">(1e-05, ...)</td>
            </tr>
    

            <tr class="user-set">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('kernel__k1__k1__k1__k2__length_scale',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">kernel__k1__k1__k1__k2__length_scale</td>
                <td class="value">50.0</td>
            </tr>
    

            <tr class="user-set">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('kernel__k1__k1__k1__k2__length_scale_bounds',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">kernel__k1__k1__k1__k2__length_scale_bounds</td>
                <td class="value">(1e-05, ...)</td>
            </tr>
    

            <tr class="user-set">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('kernel__k1__k1__k2__k1',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">kernel__k1__k1__k2__k1</td>
                <td class="value">2**2 * RBF(length_scale=100)</td>
            </tr>
    

            <tr class="user-set">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('kernel__k1__k1__k2__k2',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">kernel__k1__k1__k2__k2</td>
                <td class="value">ExpSineSquare...periodicity=1)</td>
            </tr>
    

            <tr class="user-set">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('kernel__k1__k1__k2__k1__k1',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">kernel__k1__k1__k2__k1__k1</td>
                <td class="value">2**2</td>
            </tr>
    

            <tr class="user-set">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('kernel__k1__k1__k2__k1__k2',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">kernel__k1__k1__k2__k1__k2</td>
                <td class="value">RBF(length_scale=100)</td>
            </tr>
    

            <tr class="user-set">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('kernel__k1__k1__k2__k1__k1__constant_value',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">kernel__k1__k1__k2__k1__k1__constant_value</td>
                <td class="value">4.0</td>
            </tr>
    

            <tr class="user-set">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('kernel__k1__k1__k2__k1__k1__constant_value_bounds',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">kernel__k1__k1__k2__k1__k1__constant_value_bounds</td>
                <td class="value">(1e-05, ...)</td>
            </tr>
    

            <tr class="user-set">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('kernel__k1__k1__k2__k1__k2__length_scale',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">kernel__k1__k1__k2__k1__k2__length_scale</td>
                <td class="value">100.0</td>
            </tr>
    

            <tr class="user-set">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('kernel__k1__k1__k2__k1__k2__length_scale_bounds',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">kernel__k1__k1__k2__k1__k2__length_scale_bounds</td>
                <td class="value">(1e-05, ...)</td>
            </tr>
    

            <tr class="user-set">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('kernel__k1__k1__k2__k2__length_scale',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">kernel__k1__k1__k2__k2__length_scale</td>
                <td class="value">1.0</td>
            </tr>
    

            <tr class="user-set">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('kernel__k1__k1__k2__k2__periodicity',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">kernel__k1__k1__k2__k2__periodicity</td>
                <td class="value">1.0</td>
            </tr>
    

            <tr class="user-set">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('kernel__k1__k1__k2__k2__length_scale_bounds',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">kernel__k1__k1__k2__k2__length_scale_bounds</td>
                <td class="value">(1e-05, ...)</td>
            </tr>
    

            <tr class="user-set">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('kernel__k1__k1__k2__k2__periodicity_bounds',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">kernel__k1__k1__k2__k2__periodicity_bounds</td>
                <td class="value">&#x27;fixed&#x27;</td>
            </tr>
    

            <tr class="user-set">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('kernel__k1__k2__k1',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">kernel__k1__k2__k1</td>
                <td class="value">0.5**2</td>
            </tr>
    

            <tr class="user-set">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('kernel__k1__k2__k2',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">kernel__k1__k2__k2</td>
                <td class="value">RationalQuadr...ength_scale=1)</td>
            </tr>
    

            <tr class="user-set">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('kernel__k1__k2__k1__constant_value',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">kernel__k1__k2__k1__constant_value</td>
                <td class="value">0.25</td>
            </tr>
    

            <tr class="user-set">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('kernel__k1__k2__k1__constant_value_bounds',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">kernel__k1__k2__k1__constant_value_bounds</td>
                <td class="value">(1e-05, ...)</td>
            </tr>
    

            <tr class="user-set">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('kernel__k1__k2__k2__length_scale',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">kernel__k1__k2__k2__length_scale</td>
                <td class="value">1.0</td>
            </tr>
    

            <tr class="user-set">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('kernel__k1__k2__k2__alpha',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">kernel__k1__k2__k2__alpha</td>
                <td class="value">1.0</td>
            </tr>
    

            <tr class="user-set">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('kernel__k1__k2__k2__length_scale_bounds',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">kernel__k1__k2__k2__length_scale_bounds</td>
                <td class="value">(1e-05, ...)</td>
            </tr>
    

            <tr class="user-set">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('kernel__k1__k2__k2__alpha_bounds',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">kernel__k1__k2__k2__alpha_bounds</td>
                <td class="value">(1e-05, ...)</td>
            </tr>
    

            <tr class="user-set">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('kernel__k2__k1',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">kernel__k2__k1</td>
                <td class="value">0.1**2 * RBF(length_scale=0.1)</td>
            </tr>
    

            <tr class="user-set">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('kernel__k2__k2',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">kernel__k2__k2</td>
                <td class="value">WhiteKernel(noise_level=0.01)</td>
            </tr>
    

            <tr class="user-set">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('kernel__k2__k1__k1',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">kernel__k2__k1__k1</td>
                <td class="value">0.1**2</td>
            </tr>
    

            <tr class="user-set">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('kernel__k2__k1__k2',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">kernel__k2__k1__k2</td>
                <td class="value">RBF(length_scale=0.1)</td>
            </tr>
    

            <tr class="user-set">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('kernel__k2__k1__k1__constant_value',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">kernel__k2__k1__k1__constant_value</td>
                <td class="value">0.010000000000000002</td>
            </tr>
    

            <tr class="user-set">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('kernel__k2__k1__k1__constant_value_bounds',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">kernel__k2__k1__k1__constant_value_bounds</td>
                <td class="value">(1e-05, ...)</td>
            </tr>
    

            <tr class="user-set">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('kernel__k2__k1__k2__length_scale',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">kernel__k2__k1__k2__length_scale</td>
                <td class="value">0.1</td>
            </tr>
    

            <tr class="user-set">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('kernel__k2__k1__k2__length_scale_bounds',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">kernel__k2__k1__k2__length_scale_bounds</td>
                <td class="value">(1e-05, ...)</td>
            </tr>
    

            <tr class="user-set">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('kernel__k2__k2__noise_level',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">kernel__k2__k2__noise_level</td>
                <td class="value">0.010000000000000002</td>
            </tr>
    

            <tr class="user-set">
                <td><i class="copy-paste-icon"
                     onclick="copyToClipboard('kernel__k2__k2__noise_level_bounds',
                              this.parentElement.nextElementSibling)"
                ></i></td>
                <td class="param">kernel__k2__k2__noise_level_bounds</td>
                <td class="value">(1e-05, ...)</td>
            </tr>
    
                      </tbody>
                    </table>
                </details>
            </div>
        </div></div></div></div></div><script>function copyToClipboard(text, element) {
        // Get the parameter prefix from the closest toggleable content
        const toggleableContent = element.closest('.sk-toggleable__content');
        const paramPrefix = toggleableContent ? toggleableContent.dataset.paramPrefix : '';
        const fullParamName = paramPrefix ? `${paramPrefix}${text}` : text;

        const originalStyle = element.style;
        const computedStyle = window.getComputedStyle(element);
        const originalWidth = computedStyle.width;
        const originalHTML = element.innerHTML.replace('Copied!', '');

        navigator.clipboard.writeText(fullParamName)
            .then(() => {
                element.style.width = originalWidth;
                element.style.color = 'green';
                element.innerHTML = "Copied!";

                setTimeout(() => {
                    element.innerHTML = originalHTML;
                    element.style = originalStyle;
                }, 2000);
            })
            .catch(err => {
                console.error('Failed to copy:', err);
                element.style.color = 'red';
                element.innerHTML = "Failed!";
                setTimeout(() => {
                    element.innerHTML = originalHTML;
                    element.style = originalStyle;
                }, 2000);
            });
        return false;
    }

    document.querySelectorAll('.copy-paste-icon').forEach(function(element) {
        const toggleableContent = element.closest('.sk-toggleable__content');
        const paramPrefix = toggleableContent ? toggleableContent.dataset.paramPrefix : '';
        const paramName = element.parentElement.nextElementSibling
            .textContent.trim().split(' ')[0];
        const fullParamName = paramPrefix ? `${paramPrefix}${paramName}` : paramName;

        element.setAttribute('title', fullParamName);
    });


    /**
     * Adapted from Skrub
     * https://github.com/skrub-data/skrub/blob/403466d1d5d4dc76a7ef569b3f8228db59a31dc3/skrub/_reporting/_data/templates/report.js#L789
     * @returns "light" or "dark"
     */
    function detectTheme(element) {
        const body = document.querySelector('body');

        // Check VSCode theme
        const themeKindAttr = body.getAttribute('data-vscode-theme-kind');
        const themeNameAttr = body.getAttribute('data-vscode-theme-name');

        if (themeKindAttr && themeNameAttr) {
            const themeKind = themeKindAttr.toLowerCase();
            const themeName = themeNameAttr.toLowerCase();

            if (themeKind.includes("dark") || themeName.includes("dark")) {
                return "dark";
            }
            if (themeKind.includes("light") || themeName.includes("light")) {
                return "light";
            }
        }

        // Check Jupyter theme
        if (body.getAttribute('data-jp-theme-light') === 'false') {
            return 'dark';
        } else if (body.getAttribute('data-jp-theme-light') === 'true') {
            return 'light';
        }

        // Guess based on a parent element's color
        const color = window.getComputedStyle(element.parentNode, null).getPropertyValue('color');
        const match = color.match(/^rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)\s*$/i);
        if (match) {
            const [r, g, b] = [
                parseFloat(match[1]),
                parseFloat(match[2]),
                parseFloat(match[3])
            ];

            // https://en.wikipedia.org/wiki/HSL_and_HSV#Lightness
            const luma = 0.299 * r + 0.587 * g + 0.114 * b;

            if (luma > 180) {
                // If the text is very bright we have a dark theme
                return 'dark';
            }
            if (luma < 75) {
                // If the text is very dark we have a light theme
                return 'light';
            }
            // Otherwise fall back to the next heuristic.
        }

        // Fallback to system preference
        return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
    }


    function forceTheme(elementId) {
        const estimatorElement = document.querySelector(`#${elementId}`);
        if (estimatorElement === null) {
            console.error(`Element with id ${elementId} not found.`);
        } else {
            const theme = detectTheme(estimatorElement);
            estimatorElement.classList.add(theme);
        }
    }

    forceTheme('sk-container-id-39');</script></body>
    </div>
    <br />
    <br />

.. GENERATED FROM PYTHON SOURCE LINES 174-181

Now, we will use the Gaussian process to predict on:

- training data to inspect the goodness of fit;
- future data to see the extrapolation done by the model.

Thus, we create synthetic data from 1958 to the current month. In addition,
we need to add the subtracted mean computed during training.

.. GENERATED FROM PYTHON SOURCE LINES 181-191

.. code-block:: Python

    import datetime

    import numpy as np

    today = datetime.datetime.now()
    current_month = today.year + today.month / 12
    X_test = np.linspace(start=1958, stop=current_month, num=1_000).reshape(-1, 1)
    mean_y_pred, std_y_pred = gaussian_process.predict(X_test, return_std=True)
    mean_y_pred += y_mean








.. GENERATED FROM PYTHON SOURCE LINES 192-208

.. code-block:: Python

    plt.plot(X, y, color="black", linestyle="dashed", label="Measurements")
    plt.plot(X_test, mean_y_pred, color="tab:blue", alpha=0.4, label="Gaussian process")
    plt.fill_between(
        X_test.ravel(),
        mean_y_pred - std_y_pred,
        mean_y_pred + std_y_pred,
        color="tab:blue",
        alpha=0.2,
    )
    plt.legend()
    plt.xlabel("Year")
    plt.ylabel("Monthly average of CO$_2$ concentration (ppm)")
    _ = plt.title(
        "Monthly average of air samples measurements\nfrom the Mauna Loa Observatory"
    )




.. image-sg:: /auto_examples/gaussian_process/images/sphx_glr_plot_gpr_co2_003.png
   :alt: Monthly average of air samples measurements from the Mauna Loa Observatory
   :srcset: /auto_examples/gaussian_process/images/sphx_glr_plot_gpr_co2_003.png
   :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 209-216

Our fitted model is capable to fit previous data properly and extrapolate to
future year with confidence.

Interpretation of kernel hyperparameters
----------------------------------------

Now, we can have a look at the hyperparameters of the kernel.

.. GENERATED FROM PYTHON SOURCE LINES 216-218

.. code-block:: Python

    gaussian_process.kernel_





.. rst-class:: sphx-glr-script-out

 .. code-block:: none


    44.8**2 * RBF(length_scale=51.6) + 2.64**2 * RBF(length_scale=91.5) * ExpSineSquared(length_scale=1.48, periodicity=1) + 0.536**2 * RationalQuadratic(alpha=2.89, length_scale=0.968) + 0.188**2 * RBF(length_scale=0.122) + WhiteKernel(noise_level=0.0367)



.. GENERATED FROM PYTHON SOURCE LINES 219-227

Thus, most of the target signal, with the mean subtracted, is explained by a
long-term rising trend for ~45 ppm and a length-scale of ~52 years. The
periodic component has an amplitude of ~2.6ppm, a decay time of ~90 years and
a length-scale of ~1.5. The long decay time indicates that we have a
component very close to a seasonal periodicity. The correlated noise has an
amplitude of ~0.2 ppm with a length scale of ~0.12 years and a white-noise
contribution of ~0.04 ppm. Thus, the overall noise level is very small,
indicating that the data can be very well explained by the model.


.. rst-class:: sphx-glr-timing

   **Total running time of the script:** (0 minutes 4.736 seconds)


.. _sphx_glr_download_auto_examples_gaussian_process_plot_gpr_co2.py:

.. only:: html

  .. container:: sphx-glr-footer sphx-glr-footer-example

    .. container:: binder-badge

      .. image:: images/binder_badge_logo.svg
        :target: https://mybinder.org/v2/gh/scikit-learn/scikit-learn/1.8.X?urlpath=lab/tree/notebooks/auto_examples/gaussian_process/plot_gpr_co2.ipynb
        :alt: Launch binder
        :width: 150 px

    .. container:: lite-badge

      .. image:: images/jupyterlite_badge_logo.svg
        :target: ../../lite/lab/index.html?path=auto_examples/gaussian_process/plot_gpr_co2.ipynb
        :alt: Launch JupyterLite
        :width: 150 px

    .. container:: sphx-glr-download sphx-glr-download-jupyter

      :download:`Download Jupyter notebook: plot_gpr_co2.ipynb <plot_gpr_co2.ipynb>`

    .. container:: sphx-glr-download sphx-glr-download-python

      :download:`Download Python source code: plot_gpr_co2.py <plot_gpr_co2.py>`

    .. container:: sphx-glr-download sphx-glr-download-zip

      :download:`Download zipped: plot_gpr_co2.zip <plot_gpr_co2.zip>`


.. include:: plot_gpr_co2.recommendations


.. only:: html

 .. rst-class:: sphx-glr-signature

    `Gallery generated by Sphinx-Gallery <https://sphinx-gallery.github.io>`_
