A basic architecture for time series forecasting.

CombinedLoss[source]

CombinedLoss(loss_func, lookback, ratio=[1, 1])

lookback = 7
y, y_hat = torch.arange(10).float()[None,None,:], torch.arange(10)[None,None,:].float()+torch.randn(10)
loss_fnc = CombinedLoss(F.mse_loss,lookback)
test_eq(F.mse_loss(y[:,:,:7],y_hat[:,:,:7])+F.mse_loss(y[:,:,7:],y_hat[:,:,7:]),loss_fnc(y, y_hat))

r = 10
loss_fnc = CombinedLoss(F.mse_loss, lookback, ratio = [1,r])
loss = loss_fnc(y, y_hat)
test_eq(F.mse_loss(y[:,:,:7],y_hat[:,:,:7])+F.mse_loss(y[:,:,7:],y_hat[:,:,7:])*r,loss)
horizon, lookback = 10,40
path = untar_data(URLs.m4_daily)
data = TSDataLoaders.from_folder(path, horizon = horizon, lookback = lookback, nrows = 3, step=3)
mdl = NBeatsNet(device = data.train.device, horizon=horizon, lookback=lookback, layers = [100])
loss_func = CombinedLoss(F.mse_loss, lookback)
learn = Learner(data, mdl, loss_func=loss_func, opt_func= Adam,)
learn.loss_func
learn.fit(2,.1)
torch.Size([1, 1020])
Train:644; Valid: 18; Test 3
epoch train_loss valid_loss time
0 5.485359 2.868603 00:01
1 4.385453 2.573905 00:01

Metrics

class NBeatsLossPart[source]

NBeatsLossPart(start, end, name, *args, loss_func=None, **kwargs) :: Metric

The loss according to the loss_func on a particular part of the time-serie.

class NBeatsBackward[source]

NBeatsBackward(lookback, *args, **kwargs) :: NBeatsLossPart

The loss according to the loss_func on the backwards part of the time-serie.

class NBeatsForward[source]

NBeatsForward(lookback, *args, **kwargs) :: NBeatsLossPart

The loss according to the loss_func on the forward part of the time-serie.

path = untar_data(URLs.m4_daily)
data = TSDataLoaders.from_folder(path, horizon = horizon, lookback = lookback, nrows = 1, step=3, )
mdl = NBeatsNet(device = data.train.device, horizon=horizon, lookback=lookback, layers = [100])
loss_func = F.mse_loss
learn = Learner(data, mdl, loss_func=loss_func, opt_func= Adam, metrics=L(None)+L(mae, smape, 
                                         NBeatsBackward(lookback), NBeatsForward(lookback)),)

learn.fit(3, .1)
torch.Size([1, 1020])
Train:327; Valid: 3; Test 1
epoch train_loss valid_loss mae smape b_loss f_loss time
0 1.201533 1.721093 0.935713 1.019105 0.031540 1.216456 00:00
1 1.050859 1.206644 0.808499 0.966173 0.023748 0.826671 00:00
2 0.983588 1.152934 0.793493 0.968807 0.022994 0.785033 00:00
learn.show_results()

class BackwardSMAPE[source]

BackwardSMAPE(lookback, *args, **kwargs) :: NBeatsLossPart

The SMAPE on the backwards part of the time-serie.

class ForwardSMAPE[source]

ForwardSMAPE(lookback, *args, **kwargs) :: NBeatsLossPart

The SMAPE on the forwards part of the time-serie.

path = untar_data(URLs.m4_daily)
data = TSDataLoaders.from_folder(path, horizon = horizon, lookback = lookback, nrows = 1, step=3, )
mdl = NBeatsNet(device = data.train.device, horizon=horizon, lookback=lookback, layers = [100])
loss_func = F.mse_loss
learn = Learner(data, mdl, loss_func=loss_func, opt_func= Adam, metrics=L(None)+L(mae, smape, 
                                         BackwardSMAPE(lookback), ForwardSMAPE(lookback)),)

learn.fit(3, .1)
torch.Size([1, 1020])
Train:334; Valid: 2; Test 1
epoch train_loss valid_loss mae smape b_loss f_loss time
0 1.626564 0.531735 0.611273 1.127493 0.056581 0.180685 00:00
1 1.354240 0.448775 0.545311 0.951489 0.050076 0.094422 00:00
2 1.241490 0.454662 0.575566 1.042800 0.050171 0.109699 00:00

Other

dct = {'foo':{'bar':1},'bar':2,'foo2':{'foo3':3},'ignore':{'bar':1000}}
r = _get_key_from_nested_dct(dct,'bar',['ignore'])
test_eq(r,{'foobar': 1, 'bar': 2})

class NBeatsTheta[source]

NBeatsTheta() :: Metric

The sqaure of the theta for every block.

horizon, lookback = 7,10
path = untar_data(URLs.m4_daily)
data = TSDataLoaders.from_folder(path, horizon = horizon, lookback = lookback, nrows = 1, step=3, max_std=5)

mdl = NBeatsNet(device = data.train.device, horizon=horizon, lookback=lookback, layers = [100])
loss_func = F.mse_loss
learn = Learner(data, mdl, loss_func=loss_func, opt_func= Adam, metrics=[NBeatsTheta()],
               )

learn.fit(3,.1)
test_eq(type(learn.metrics[0].value),Tensor)
torch.Size([1, 1020])
Train:327; Valid: 4; Test 1
epoch train_loss valid_loss theta time
0 3.218897 3.638505 1.559033 00:00
1 3.042957 3.146926 1.094095 00:00
2 2.959047 3.188194 1.110073 00:00

Callbacks

class NBeatsAttention[source]

NBeatsAttention() :: Callback

Basic class handling tweaks of the training loop by changing a Learner in various events

horizon, lookback = 7,10
items = L(np.arange(-5,100)[None,:],np.arange(500,550)[None,:],np.arange(-110,-56)[None,:]).map(tensor)
data = TSDataLoaders.from_items(items, horizon = horizon, lookback=lookback, step=1, after_batch = NormalizeTS()
                             )
mdl = NBeatsNet(device = data.train.device,horizon=horizon, lookback=lookback)
loss_func = F.mse_loss
learn = Learner(data, mdl, loss_func=loss_func, opt_func= Adam, metrics=L(mae, smape, NBeatsTheta(), 
                                         NBeatsBackward(lookback), NBeatsForward(lookback)),
                cbs=L( NBeatsAttention()
                     )
               )
learn.fit(3,.1)
df = learn.n_beats_attention.means()
df
torch.Size([1, 105])
Train:89; Valid: 33; Test 3
epoch train_loss valid_loss mae smape theta b_loss f_loss time
0 7.063035 6.239435 2.075063 1.390074 2.909513 0.335390 1.480233 00:00
1 7.443372 8.091285 2.275772 1.553161 3.219479 0.366179 2.059876 00:00
2 7.676329 6.378671 2.065759 1.593280 2.533737 0.286700 1.627907 00:00
trend0_0 trend0_1 seasonality1_0 seasonality1_1 seasonality1_2 seasonality1_3
theta_0_mean 0.0 0.0 2.2499769 0.24990746 -2.25 0.0
theta_0_std 0.0 0.0 0.0 0.0 0.0 0.0
theta_1_mean 0.005 1.846627e-06 -0.025963232 -0.5625 0.0 0.0
theta_1_std 0.0 0.0 5.350041e-09 0.0 0.0 0.0
theta_2_mean 0.0 0.0 0.0 0.25 -0.140625 0.0
theta_2_std 0.0 0.0 0.0 0.0 0.0 0.0
theta_3_mean -0.14988667 -0.0004500001 NaN 0.5625 2.25 2.25
theta_3_std 0.0 0.0 NaN 0.0 0.0 0.0
theta_4_mean 0.0 -0.14941214 NaN NaN 0.0 0.0
theta_4_std 0.0 0.0 NaN NaN 0.0 0.0
theta_5_mean 0.0 0.169529 NaN NaN NaN 0.0
theta_5_std 0.0 2.1400163e-08 NaN NaN NaN 0.0
att_mean 0.333318 0.232766 0.338758 1 0.6 0.166667
att_std 0.471383 0.347018 0.466685 0 0.489898 0.372678
theta_6_mean NaN 0.0 NaN NaN NaN NaN
theta_6_std NaN 0.0 NaN NaN NaN NaN
theta_7_mean NaN 0.0 NaN NaN NaN NaN
theta_7_std NaN 0.0 NaN NaN NaN NaN
learn.show_results()

class ClipLoss[source]

ClipLoss(clip=5) :: Callback

Callback that adds weights regularization the thetas in N-Beats training.

horizon, lookback = 2,10
items = L(np.arange(-5,30)[None,:],np.arange(50)[None,:]).map(tensor)
items[-1][:,-8:-5] = 1e10
data = TSDataLoaders.from_items(items, horizon = horizon, lookback=lookback, step=1, after_batch = NormalizeTS()
                             )
mdl = NBeatsNet(device = data.train.device,horizon=horizon, lookback=lookback)
loss_func = F.mse_loss
learn = Learner(data, mdl, loss_func=loss_func, opt_func= Adam, 
                cbs=L(ClipLoss()
                     )
               )

learn.fit(10,.1)
learn.recorder.plot_loss()
torch.Size([1, 35])
Train:49; Valid: 8; Test 2
epoch train_loss valid_loss time
0 1.439459 2.123430 00:00
1 2.391775 5.000000 00:00
2 3.278804 5.000000 00:00
3 3.722229 5.000000 00:00
4 3.988210 3.264698 00:00
5 4.165472 3.354544 00:00
6 4.292035 3.529953 00:00
7 4.386912 5.000000 00:00
8 4.460666 5.000000 00:00
9 4.519632 5.000000 00:00
learn.show_results()