<jupyter_start><jupyter_text>Quick start skforecastThis code is a quick example of how to create, validate and optimize a recursive multi-step forecaster, `ForecasterAutoreg`, using **skforecast**. For more detailed documentation, visit [User Guides](https://joaquinamatrodrigo.github.io/skforecast/latest/user_guides/input-data.html).  Libraries<jupyter_code># Libraries
# ==============================================================================
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error

from skforecast.ForecasterAutoreg import ForecasterAutoreg
from skforecast.model_selection import backtesting_forecaster
from skforecast.model_selection import grid_search_forecaster<jupyter_output><empty_output><jupyter_text>Data<jupyter_code># Download data
# ==============================================================================
url = ('https://raw.githubusercontent.com/JoaquinAmatRodrigo/skforecast/master/data/h2o.csv')
data = pd.read_csv(url, sep=',', header=0, names=['y', 'datetime'])

# Data preprocessing
# ==============================================================================
data['datetime'] = pd.to_datetime(data['datetime'], format='%Y/%m/%d')
data = data.set_index('datetime')
data = data.asfreq('MS')
data = data['y']
data = data.sort_index()

# Train-test dates
# ==============================================================================
end_train = '2005-06-01 23:59:00'

print(f"Train dates : {data.index.min()} --- {data.loc[:end_train].index.max()}  (n={len(data.loc[:end_train])})")
print(f"Test dates  : {data.loc[end_train:].index.min()} --- {data.index.max()}  (n={len(data.loc[end_train:])})")

# Plot
# ==============================================================================
fig, ax=plt.subplots(figsize=(9, 4))
data.loc[:end_train].plot(ax=ax, label='train')
data.loc[end_train:].plot(ax=ax, label='test')
ax.legend();<jupyter_output>Train dates : 1991-07-01 00:00:00 --- 2005-06-01 00:00:00  (n=168)
Test dates  : 2005-07-01 00:00:00 --- 2008-06-01 00:00:00  (n=36)<jupyter_text>Train forecasterFor more detailed documentation, visit: [User guide ForecasterAutoreg](https://joaquinamatrodrigo.github.io/skforecast/latest/user_guides/autoregresive-forecaster.html).<jupyter_code># Create and fit Recursive multi-step forecaster (ForecasterAutoreg)
# ==============================================================================
forecaster = ForecasterAutoreg(
                    regressor = RandomForestRegressor(random_state=123),
                    lags      = 15
             )

forecaster.fit(y=data.loc[:end_train])
forecaster<jupyter_output><empty_output><jupyter_text>PredictionThis method predicts $n$ steps in the future.<jupyter_code># Predict
# ==============================================================================
predictions = forecaster.predict(steps=len(data.loc[end_train:]))
predictions.head(3)
# Plot predictions
# ==============================================================================
fig, ax=plt.subplots(figsize=(9, 4))
data.loc[:end_train].plot(ax=ax, label='train')
data.loc[end_train:].plot(ax=ax, label='test')
predictions.plot(ax=ax, label='predictions')
ax.legend();
# Prediction error
# ==============================================================================
error_mse = mean_squared_error(
                y_true = data.loc[end_train:],
                y_pred = predictions
            )
print(f"Test error (mse): {error_mse}")<jupyter_output>Test error (mse): 0.00429855684785846<jupyter_text>Backtesting: forecaster validationBacktesting is a term used in modeling to refer to testing a predictive model on historical data. Backtesting involves moving backward in time, step-by-step, in as many stages as is necessary. Therefore, it is a special type of cross-validation applied to previous period(s). For more detailed documentation, visit: [User guide Backtesting forecaster](https://joaquinamatrodrigo.github.io/skforecast/latest/user_guides/backtesting.html).<jupyter_code># Backtesting
# ==============================================================================
metric, predictions_backtest = backtesting_forecaster(
                                    forecaster = forecaster,
                                    y          = data,
                                    initial_train_size = len(data.loc[:end_train]),
                                    fixed_train_size   = False,
                                    steps      = 10,
                                    metric     = 'mean_squared_error',
                                    refit      = True,
                                    verbose    = True
                               )

print(f"Backtest error: {metric}")<jupyter_output>Information of backtesting process
----------------------------------
Number of observations used for initial training: 168
Number of observations used for backtesting: 36
    Number of folds: 4
    Number of steps per fold: 10
    Last fold only includes 6 observations.

Data partition in fold: 0
    Training:   1991-07-01 00:00:00 -- 2005-06-01 00:00:00
    Validation: 2005-07-01 00:00:00 -- 2006-04-01 00:00:00
Data partition in fold: 1
    Training:   1991-07-01 00:00:00 -- 2006-04-01 00:00:00
    Validation: 2006-05-01 00:00:00 -- 2007-02-01 00:00:00
Data partition in fold: 2
    Training:   1991-07-01 00:00:00 -- 2007-02-01 00:00:00
    Validation: 2007-03-01 00:00:00 -- 2007-12-01 00:00:00
Data partition in fold: 3
    Training:   1991-07-01 00:00:00 -- 2007-12-01 00:00:00
    Validation: 2008-01-01 00:00:00 -- 2008-06-01 00:00:00

Backtest error: 0.004810878299401304<jupyter_text>Grid search: forecaster optimizationSkforecast library combines grid search strategy with backtesting to identify the combination of lags and hyperparameters that achieve the best prediction performance. For more detailed documentation, visit: [Grid search forecaster](https://joaquinamatrodrigo.github.io/skforecast/latest/user_guides/grid-search-forecaster.html).<jupyter_code># Grid search hyperparameter and lags
# ==============================================================================

# Regressor hyperparameters
param_grid = {'n_estimators': [50, 100],
              'max_depth': [5, 10, 15]}

# Lags used as predictors
lags_grid = [3, 10, [1, 2, 3, 20]]

results_grid = grid_search_forecaster(
                        forecaster  = forecaster,
                        y           = data,
                        param_grid  = param_grid,
                        lags_grid   = lags_grid,
                        steps       = 10,
                        refit       = True,
                        metric      = 'mean_squared_error',
                        initial_train_size = len(data.loc[:end_train]),
                        fixed_train_size   = False,
                        return_best = True,
                        verbose     = False
               )
# Grid results
# ==============================================================================
results_grid
%%html
<style>
.jupyter-wrapper .jp-CodeCell .jp-Cell-inputWrapper .jp-InputPrompt {display: none;}
</style><jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.231872070581748, 'fraction_numerical': 0.052798456024262475, 'mean_word_length': 3.4867037724180583, 'pattern_counts': {'":': 0, '<': 24, '<?xml version=': 0, '>': 24, 'https://': 5, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 11, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '6', 'dir': 'jupyter-structured-clean-dedup', 'id': '40549', 'license': 'MIT', 'n_tokens_mistral': 2374, 'n_tokens_neox': 1962, 'n_words': 447, 'path': 'docs/user_guides/quick-start-skforecast.ipynb', 'repo_name': 'JavierEscobarOrtiz/skforecast', 'size': '7254'}