--- title: Naive2 model keywords: fastai sidebar: home_sidebar summary: "Common benchmark model." description: "Common benchmark model." nb_path: "nbs/models_naive2__naive2.ipynb" ---
{% raw %}
{% endraw %} {% raw %}
{% endraw %}

Naive Benchmark Model

API details.

{% raw %}

class Naive[source]

Naive()

Naive model. This benchmark model produces a forecast that is equal to the last observed value for a given time series.

{% endraw %} {% raw %}
{% endraw %}

Seasonal Naive Benchmark Model

API details.

{% raw %}

class SeasonalNaive[source]

SeasonalNaive()

Seasonal Naive model. This benchmark model produces a forecast that is equal to the last observed value of the same season for a given time series.

{% endraw %} {% raw %}
{% endraw %}

Naive2 Benchmark Model

API details.

The Naive2 benchmark model, as explained in the M4 guide is determined by the following process:- Test the time-series for seasonal patterns by performing a 90% auto-correlation.

  • Based on the test select between a Naive benchmark (random walk) or a spline detrended seasonal forecast.
{% raw %}

detrend[source]

detrend(insample_data)

Calculates a & b parameters of LRL :param insample_data: :return:

{% endraw %} {% raw %}

deseasonalize[source]

deseasonalize(original_ts, ppy)

Calculates and returns seasonal indices :param original_ts: original data :param ppy: periods per year :return:

{% endraw %} {% raw %}

moving_averages[source]

moving_averages(ts_init, window)

Calculates the moving averages for a given TS :param ts_init: the original time series :param window: window length :return: moving averages ts

{% endraw %} {% raw %}

seasonality_test[source]

seasonality_test(original_ts, ppy)

Seasonality test :param original_ts: time series :param ppy: periods per year :return: boolean value: whether the TS is seasonal

{% endraw %} {% raw %}

acf[source]

acf(data, k)

Autocorrelation function :param data: time series :param k: lag :return:

{% endraw %} {% raw %}
{% endraw %} {% raw %}

class Naive2[source]

Naive2(seasonality)

Naive2 model. Popular benchmark model for time series forecasting that automatically adapts to the potential seasonality of a series based on an autocorrelation test. If the series is seasonal the model composes the predictions of Naive and SeasonalNaive, else the model predicts on the simple Naive.

{% endraw %} {% raw %}
{% endraw %}

Naive Benchmark Usage Example

{% raw %}
import pandas as pd
from nixtlats.data.datasets.epf import EPF, EPFInfo
from nixtlats.data.tsloader import TimeSeriesLoader

import pylab as plt
from pylab import rcParams
plt.style.use('seaborn-whitegrid')
plt.rcParams['font.family'] = 'serif'

FONTSIZE = 17

# Load and plot data
Y_df, X_df, S_df = EPF.load_groups(directory='./data', groups=['NP'])

fig = plt.figure(figsize=(15, 6))
plt.plot(Y_df.ds, Y_df.y.values, color='#628793', linewidth=0.4)
plt.ylabel('Price [EUR/MWh]', fontsize=15)
plt.xlabel('Date', fontsize=15)
# plt.savefig('./results/NP.png', bbox_inches = 'tight')
plt.show()
100%|██████████| 2.12M/2.12M [00:00<00:00, 3.30MiB/s]
INFO:nixtla.data.datasets.utils:Successfully downloaded NP.csv, 2118914, bytes.
100%|██████████| 2.53M/2.53M [00:00<00:00, 3.46MiB/s]
INFO:nixtla.data.datasets.utils:Successfully downloaded PJM.csv, 2530311, bytes.
100%|██████████| 1.97M/1.97M [00:00<00:00, 2.74MiB/s]
INFO:nixtla.data.datasets.utils:Successfully downloaded BE.csv, 1974555, bytes.
100%|██████████| 2.00M/2.00M [00:00<00:00, 3.15MiB/s]
INFO:nixtla.data.datasets.utils:Successfully downloaded FR.csv, 1996871, bytes.
100%|██████████| 2.10M/2.10M [00:00<00:00, 2.82MiB/s]
INFO:nixtla.data.datasets.utils:Successfully downloaded DE.csv, 2095831, bytes.
{% endraw %} {% raw %}
from itertools import chain
from multiprocessing import Pool
from numpy.lib.stride_tricks import sliding_window_view
from nixtlats.losses.numpy import mae

def fit_predict_naive2(Y, output_size=24, seasonality=24):
    y_hat_list = []
    for idx in range(len(Y)):
        y_id = Y[idx, :]
        y_hat_id = Naive2(seasonality).fit(y_id).predict(output_size)
        y_hat_list += [y_hat_id]
    return y_hat_list

def parallelized_naive2(Y, n_cores=32):
    # Y
    n_partitions = n_cores**3//4  # number of partitions to split the array
    Y_split  = np.array_split(Y, n_partitions)
    pool = Pool(n_cores)
    Y_hat_list = list(chain.from_iterable(pool.map(fit_predict_naive2, Y_split)))
    pool.close()
    pool.join()
    Y_hat = np.vstack(Y_hat_list)
    return Y_hat
{% endraw %} {% raw %}
Y_windows = sliding_window_view(Y_df.y.values, window_shape=24*7)
day_idxs = (np.arange(len(Y_windows)) % 24) == 0
Y_windows = Y_windows[day_idxs, :]
print("Y_windows.shape", Y_windows.shape)
Y_windows.shape (2178, 168)
{% endraw %} {% raw %}
Y_hat = parallelized_naive2(Y=Y_windows)
Y_hat = Y_hat.reshape(-1)
Y_hat.shape
(52272,)
{% endraw %} {% raw %}
fig = plt.figure(figsize=(15, 6))
plt.plot(Y_df.ds[168:], Y_df.y.values[168:], color='#628793', linewidth=0.4, label='true')
plt.plot(Y_df.ds[168:], Y_hat[:len(Y_hat)-24], color='peru', linewidth=0.4, label='forecast')
plt.ylabel('Price [EUR/MWh]', fontsize=15)
plt.xlabel('Date', fontsize=15)
plt.legend()
# plt.savefig('./results/NP.png', bbox_inches = 'tight')
plt.show()
{% endraw %} {% raw %}
naive2_mae = mae(y=Y_df.y.values[168:], y_hat=Y_hat[:len(Y_hat)-24])
print(f'MAE: {naive2_mae}')
MAE: 2.5901857898968275
{% endraw %}