@@ -268,28 +268,34 @@ def __init__(
268268 self .ar_layers = ar_layers
269269 self .max_lags = max_lags
270270 if self .n_lags > 0 :
271- self . ar_net = nn . ModuleList ()
271+ ar_net_layers = []
272272 d_inputs = self .n_lags
273273 for d_hidden_i in self .ar_layers :
274- self .ar_net .append (nn .Linear (d_inputs , d_hidden_i , bias = True ))
274+ ar_net_layers .append (nn .Linear (d_inputs , d_hidden_i , bias = True ))
275+ ar_net_layers .append (nn .ReLU ())
275276 d_inputs = d_hidden_i
276277 # final layer has input size d_inputs and output size equal to no. of forecasts * no. of quantiles
277- self .ar_net .append (nn .Linear (d_inputs , self .n_forecasts * len (self .quantiles ), bias = False ))
278+ ar_net_layers .append (nn .Linear (d_inputs , self .n_forecasts * len (self .quantiles ), bias = False ))
279+ self .ar_net = nn .Sequential (* ar_net_layers )
278280 for lay in self .ar_net :
279- nn .init .kaiming_normal_ (lay .weight , mode = "fan_in" )
281+ if isinstance (lay , nn .Linear ):
282+ nn .init .kaiming_normal_ (lay .weight , mode = "fan_in" )
280283
281284 # Lagged regressors
282285 self .lagged_reg_layers = lagged_reg_layers
283286 self .config_lagged_regressors = config_lagged_regressors
284287 if self .config_lagged_regressors is not None :
285- self . covar_net = nn . ModuleList ()
288+ covar_net_layers = []
286289 d_inputs = sum ([covar .n_lags for _ , covar in self .config_lagged_regressors .items ()])
287290 for d_hidden_i in self .lagged_reg_layers :
288- self .covar_net .append (nn .Linear (d_inputs , d_hidden_i , bias = True ))
291+ covar_net_layers .append (nn .Linear (d_inputs , d_hidden_i , bias = True ))
292+ covar_net_layers .append (nn .ReLU ())
289293 d_inputs = d_hidden_i
290- self .covar_net .append (nn .Linear (d_inputs , self .n_forecasts * len (self .quantiles ), bias = False ))
294+ covar_net_layers .append (nn .Linear (d_inputs , self .n_forecasts * len (self .quantiles ), bias = False ))
295+ self .covar_net = nn .Sequential (* covar_net_layers )
291296 for lay in self .covar_net :
292- nn .init .kaiming_normal_ (lay .weight , mode = "fan_in" )
297+ if isinstance (lay , nn .Linear ):
298+ nn .init .kaiming_normal_ (lay .weight , mode = "fan_in" )
293299
294300 # Regressors
295301 self .config_regressors = config_regressors
@@ -310,7 +316,9 @@ def __init__(
310316 def ar_weights (self ) -> torch .Tensor :
311317 """sets property auto-regression weights for regularization. Update if AR is modelled differently"""
312318 # TODO: this is wrong for deep networks, use utils_torch.interprete_model
313- return self .ar_net [0 ].weight
319+ for layer in self .ar_net :
320+ if isinstance (layer , nn .Linear ):
321+ return layer .weight
314322
315323 def get_covar_weights (self , covar_input = None ) -> torch .Tensor :
316324 """
@@ -393,49 +401,50 @@ def _compute_quantile_forecasts_from_diffs(self, diffs: torch.Tensor, predict_mo
393401 dim (batch, n_forecasts, no_quantiles)
394402 final forecasts
395403 """
396- if len (self .quantiles ) > 1 :
397- # generate the actual quantile forecasts from predicted differences
398- if any (quantile > 0.5 for quantile in self .quantiles ):
399- quantiles_divider_index = next (i for i , quantile in enumerate (self .quantiles ) if quantile > 0.5 )
400- else :
401- quantiles_divider_index = len (self .quantiles )
402-
403- n_upper_quantiles = diffs .shape [- 1 ] - quantiles_divider_index
404- n_lower_quantiles = quantiles_divider_index - 1
405-
406- out = torch .zeros_like (diffs )
407- out [:, :, 0 ] = diffs [:, :, 0 ] # set the median where 0 is the median quantile index
408-
409- if n_upper_quantiles > 0 : # check if upper quantiles exist
410- upper_quantile_diffs = diffs [:, :, quantiles_divider_index :]
411- if predict_mode : # check for quantile crossing and correct them in predict mode
412- upper_quantile_diffs [:, :, 0 ] = torch .max (
413- torch .tensor (0 , device = self .device ), upper_quantile_diffs [:, :, 0 ]
414- )
415- for i in range (n_upper_quantiles - 1 ):
416- next_diff = upper_quantile_diffs [:, :, i + 1 ]
417- diff = upper_quantile_diffs [:, :, i ]
418- upper_quantile_diffs [:, :, i + 1 ] = torch .max (next_diff , diff )
419- out [:, :, quantiles_divider_index :] = (
420- upper_quantile_diffs + diffs [:, :, 0 ].unsqueeze (dim = 2 ).repeat (1 , 1 , n_upper_quantiles ).detach ()
421- ) # set the upper quantiles
422-
423- if n_lower_quantiles > 0 : # check if lower quantiles exist
424- lower_quantile_diffs = diffs [:, :, 1 :quantiles_divider_index ]
425- if predict_mode : # check for quantile crossing and correct them in predict mode
426- lower_quantile_diffs [:, :, - 1 ] = torch .max (
427- torch .tensor (0 , device = self .device ), lower_quantile_diffs [:, :, - 1 ]
428- )
429- for i in range (n_lower_quantiles - 1 , 0 , - 1 ):
430- next_diff = lower_quantile_diffs [:, :, i - 1 ]
431- diff = lower_quantile_diffs [:, :, i ]
432- lower_quantile_diffs [:, :, i - 1 ] = torch .max (next_diff , diff )
433- lower_quantile_diffs = - lower_quantile_diffs
434- out [:, :, 1 :quantiles_divider_index ] = (
435- lower_quantile_diffs + diffs [:, :, 0 ].unsqueeze (dim = 2 ).repeat (1 , 1 , n_lower_quantiles ).detach ()
436- ) # set the lower quantiles
404+
405+ if len (self .quantiles ) <= 1 :
406+ return diffs
407+ # generate the actual quantile forecasts from predicted differences
408+ if any (quantile > 0.5 for quantile in self .quantiles ):
409+ quantiles_divider_index = next (i for i , quantile in enumerate (self .quantiles ) if quantile > 0.5 )
437410 else :
438- out = diffs
411+ quantiles_divider_index = len (self .quantiles )
412+
413+ n_upper_quantiles = diffs .shape [- 1 ] - quantiles_divider_index
414+ n_lower_quantiles = quantiles_divider_index - 1
415+
416+ out = torch .zeros_like (diffs )
417+ out [:, :, 0 ] = diffs [:, :, 0 ] # set the median where 0 is the median quantile index
418+
419+ if n_upper_quantiles > 0 : # check if upper quantiles exist
420+ upper_quantile_diffs = diffs [:, :, quantiles_divider_index :]
421+ if predict_mode : # check for quantile crossing and correct them in predict mode
422+ upper_quantile_diffs [:, :, 0 ] = torch .max (
423+ torch .tensor (0 , device = self .device ), upper_quantile_diffs [:, :, 0 ]
424+ )
425+ for i in range (n_upper_quantiles - 1 ):
426+ next_diff = upper_quantile_diffs [:, :, i + 1 ]
427+ diff = upper_quantile_diffs [:, :, i ]
428+ upper_quantile_diffs [:, :, i + 1 ] = torch .max (next_diff , diff )
429+ out [:, :, quantiles_divider_index :] = (
430+ upper_quantile_diffs + diffs [:, :, 0 ].unsqueeze (dim = 2 ).repeat (1 , 1 , n_upper_quantiles ).detach ()
431+ ) # set the upper quantiles
432+
433+ if n_lower_quantiles > 0 : # check if lower quantiles exist
434+ lower_quantile_diffs = diffs [:, :, 1 :quantiles_divider_index ]
435+ if predict_mode : # check for quantile crossing and correct them in predict mode
436+ lower_quantile_diffs [:, :, - 1 ] = torch .max (
437+ torch .tensor (0 , device = self .device ), lower_quantile_diffs [:, :, - 1 ]
438+ )
439+ for i in range (n_lower_quantiles - 1 , 0 , - 1 ):
440+ next_diff = lower_quantile_diffs [:, :, i - 1 ]
441+ diff = lower_quantile_diffs [:, :, i ]
442+ lower_quantile_diffs [:, :, i - 1 ] = torch .max (next_diff , diff )
443+ lower_quantile_diffs = - lower_quantile_diffs
444+ out [:, :, 1 :quantiles_divider_index ] = (
445+ lower_quantile_diffs + diffs [:, :, 0 ].unsqueeze (dim = 2 ).repeat (1 , 1 , n_lower_quantiles ).detach ()
446+ ) # set the lower quantiles
447+
439448 return out
440449
441450 def scalar_features_effects (self , features : torch .Tensor , params : nn .Parameter , indices = None ) -> torch .Tensor :
@@ -474,14 +483,9 @@ def auto_regression(self, lags: Union[torch.Tensor, float]) -> torch.Tensor:
474483 torch.Tensor
475484 Forecast component of dims: (batch, n_forecasts)
476485 """
477- x = lags
478- for i in range (len (self .ar_layers ) + 1 ):
479- if i > 0 :
480- x = nn .functional .relu (x )
481- x = self .ar_net [i ](x )
482-
486+ x = self .ar_net (lags )
483487 # segment the last dimension to match the quantiles
484- x = x .reshape (x .shape [0 ], self .n_forecasts , len (self .quantiles ))
488+ x = x .view (x .shape [0 ], self .n_forecasts , len (self .quantiles ))
485489 return x
486490
487491 def forward_covar_net (self , covariates ):
@@ -501,13 +505,9 @@ def forward_covar_net(self, covariates):
501505 x = torch .cat ([covar for _ , covar in covariates .items ()], axis = 1 )
502506 else :
503507 x = covariates
504- for i in range (len (self .lagged_reg_layers ) + 1 ):
505- if i > 0 :
506- x = nn .functional .relu (x )
507- x = self .covar_net [i ](x )
508-
508+ x = self .covar_net (x )
509509 # segment the last dimension to match the quantiles
510- x = x .reshape (x .shape [0 ], self .n_forecasts , len (self .quantiles ))
510+ x = x .view (x .shape [0 ], self .n_forecasts , len (self .quantiles ))
511511 return x
512512
513513 def forward (self , inputs : Dict , meta : Dict = None , compute_components_flag : bool = False ) -> torch .Tensor :
@@ -880,8 +880,7 @@ def _get_time_based_sample_weight(self, t):
880880 end_w = self .config_train .newer_samples_weight
881881 start_t = self .config_train .newer_samples_start
882882 time = (t .detach () - start_t ) / (1.0 - start_t )
883- time = torch .maximum (torch .zeros_like (time ), time )
884- time = torch .minimum (torch .ones_like (time ), time ) # time = 0 to 1
883+ time = torch .clamp (time , 0.0 , 1.0 ) # time = 0 to 1
885884 time = np .pi * (time - 1.0 ) # time = -pi to 0
886885 time = 0.5 * torch .cos (time ) + 0.5 # time = 0 to 1
887886 # scales end to be end weight times bigger than start weight
@@ -1019,24 +1018,21 @@ class DeepNet(nn.Module):
10191018 def __init__ (self , d_inputs , d_outputs , lagged_reg_layers = []):
10201019 # Perform initialization of the pytorch superclass
10211020 super (DeepNet , self ).__init__ ()
1022- self . layers = nn . ModuleList ()
1021+ layers = []
10231022 for d_hidden_i in lagged_reg_layers :
1024- self .layers .append (nn .Linear (d_inputs , d_hidden_i , bias = True ))
1023+ layers .append (nn .Linear (d_inputs , d_hidden_i , bias = True ))
1024+ layers .append (nn .ReLU ())
10251025 d_inputs = d_hidden_i
1026- self .layers .append (nn .Linear (d_inputs , d_outputs , bias = True ))
1026+ layers .append (nn .Linear (d_inputs , d_outputs , bias = True ))
1027+ self .layers = nn .Sequential (* layers )
10271028 for lay in self .layers :
10281029 nn .init .kaiming_normal_ (lay .weight , mode = "fan_in" )
10291030
10301031 def forward (self , x ):
10311032 """
10321033 This method defines the network layering and activation functions
10331034 """
1034- activation = nn .functional .relu
1035- for i in range (len (self .layers )):
1036- if i > 0 :
1037- x = activation (x )
1038- x = self .layers [i ](x )
1039- return x
1035+ return self .layers (x )
10401036
10411037 @property
10421038 def ar_weights (self ):
0 commit comments