Open In Colab

image.png

Tune forecaster on single node#

Introduction#

In this guidance, we demonstrate how to tune forecaster on single node. In tuning process, forecaster will find the best hyperparameter combination among user-defined search space, which is a common process if users pursue a forecaster with higher accuracy.

Chronos support forecasting model’s hyperparameter tuning in 2 sepaerated APIs (i.e. Forecaster.tune and AutoTSEstimator) for users with different demands:

Forecaster.tune

AutoTSEstimator

Single Node

Cluster

X

Performance-awared Tuning

X

Feature Selection

X

Customized Model

X

Forecaster.tune provides easier and more stright-forward API for users who are familiar with Chronos forecasters, it is recommened to try this method first.

We will take AutoformerForecaster and nyc_taxi dataset as an example in this guide.

Setup#

Before we begin, we need to install chronos if it isn’t already available, we choose to use pytorch as deep learning backend.

[ ]:
!pip install --pre --upgrade bigdl-chronos[pytorch,automl]
!pip uninstall -y torchtext # uninstall torchtext to avoid version conflict

Data preparation#

First, we load the nyc taxi dataset.

Currently, tune func only support Numpy Ndarray input.

[ ]:
from sklearn.preprocessing import StandardScaler
from bigdl.chronos.data import get_public_dataset

def get_tsdata():
    name = 'nyc_taxi'
    tsdata_train, tsdata_valid, _ = get_public_dataset(name)
    stand_scaler = StandardScaler()
    for tsdata in [tsdata_train, tsdata_valid]:
        tsdata.impute(mode="linear")\
              .scale(stand_scaler, fit=(tsdata is tsdata_train))
    return tsdata_train, tsdata_valid

tsdata_train, tsdata_valid = get_tsdata()

input_feature_num = 1
output_feature_num = 1
lookback = 20
horizon = 1
label_len = 10

train_data = tsdata_train.roll(lookback=lookback, horizon=horizon, label_len=label_len, time_enc=True).to_numpy()
val_data = tsdata_valid.roll(lookback=lookback, horizon=horizon, label_len=label_len,time_enc=True).to_numpy()

train_data and val_data is compose of (x, y, x_enc, y_enc) as we set time_enc=True which is only necessary for Autoformer.

Tuning#

The first step of tuning a forecaster is to define forecaster with space parameters.

There are several common space choices:

space.Categorical : search space for hyperparameters which are categorical, e.g. a = space.Categorical(‘a’, ‘b’, ‘c’, ‘d’)

space.Real : search space for numeric hyperparameter that takes continuous values, e.g. learning_rate = space.Real(0.01, 0.1, log=True)

space.Int : search space for numeric hyperparameter that takes integer values, e.g. range = space.Int(0, 100)

How to change these hyperparameters might be tricky and highly based on experience, but lr, d_model, d_ff and layers or similar parameters usually has a great impact on performance.

[ ]:
import bigdl.nano.automl.hpo.space as space
from bigdl.chronos.forecaster.autoformer_forecaster import AutoformerForecaster

autoformer = AutoformerForecaster(input_feature_num=input_feature_num,
                                  output_feature_num=output_feature_num,
                                  past_seq_len=lookback,
                                  future_seq_len=horizon,
                                  label_len=label_len,
                                  seed=1024,
                                  freq='t',
                                  loss="mse",
                                  metrics=['mae', 'mse', 'mape'],
                                  lr = space.Real(0.0001, 0.1, log=True),
                                  d_model=space.Categorical(32, 64, 128, 256),
                                  d_ff=space.Categorical(32, 64, 128, 256),
                                  e_layers=space.Categorical(1,2),
                                  n_head=space.Categorical(1,8))

Then just call tune on the training data and validation data!

In addition to data, there are three parameters which need to be specified : n_trials, target_metric and direction(or directions for multi-objective HPO).

n_trials: number of trials to run. The more trials, the longer the running time, the better results.

target_metric: the target metric to optimize, a string or an instance of torchmetrics.metric.Metric, default to ‘mse’. If you want to try a multi-objective HPO, you need to pass in a list, for example [‘mse’, ‘latency’] in which latency is a built-in metric for performance.

direction: in which direction to optimize the target metric, “maximize” or “minimize”, default to “minimize”. If you want to try a multi-objective HPO, you need to set direction=None, and specify directions which is a list containing direction for each metric, for example [‘minimize’, ‘minimize’].

there are other two parameters which you may change their default values : epochs and batch_size.

[ ]:
autoformer.tune(train_data, validation_data=val_data,
                n_trials=10, target_metric='mse', direction="minimize")

Then, you can see the whole trial history by calling search_summary().

[ ]:
autoformer.search_summary()

After tune, the model parameters of autoformer is initialized according to the best trial parameters. You need to fit the model again.

[ ]:
autoformer.fit(train_data, epochs=4, batch_size=32)
# evaluate on val set
evaluate = autoformer.evaluate(val_data)
print(evaluate)

Save and load(Optional)#

After tuning and fitting, you can save your model by calling save with a filename.

[ ]:
autoformer.save(checkpoint_file="best.ckpt")

Then, when you need to load the model weights, just call load() with corresponding filename.

[ ]:
autoformer.load(checkpoint_file="best.ckpt")

Or if there is a new session, just define a new forecaster with six necessary parameters: input_feature_num, output_feature_num, past_seq_len, future_seq_len, label_len, and freq, then load with corresponding filename.

[ ]:
new_autoformer = AutoformerForecaster(input_feature_num=input_feature_num,
                                      output_feature_num=output_feature_num,
                                      past_seq_len=lookback,
                                      future_seq_len=horizon,
                                      label_len=label_len,
                                      freq='s')
new_autoformer.load(checkpoint_file="best.ckpt")