def test_hierarchical_cnn_encoders(use_residual, hybridize) -> None: num_ts = 2 ts_len = 10 num_static_feat = 2 num_dynamic_feat = 5 test_data = nd.arange(num_ts * ts_len).reshape(shape=(num_ts, ts_len, 1)) test_static_feat = nd.random.randn(num_ts, num_static_feat) test_dynamic_feat = nd.random.randn(num_ts, ts_len, num_dynamic_feat) chl_dim = [30, 30, 30] ks_seq = [3] * len(chl_dim) dial_seq = [1, 3, 9] cnn = HierarchicalCausalConv1DEncoder( dial_seq, ks_seq, chl_dim, use_residual, use_dynamic_feat=True, use_static_feat=True, ) cnn.collect_params().initialize() if hybridize: cnn.hybridize() true_shape = (num_ts, ts_len, 31) if use_residual else (num_ts, ts_len, 30) assert (cnn(test_data, test_static_feat, test_dynamic_feat)[1].shape == true_shape)
def __init__( self, freq: str, prediction_length: int, cardinality: List[int], embedding_dimension: int, decoder_mlp_layer: List[int], decoder_mlp_static_dim: int, scaler: Scaler = NOPScaler(), context_length: Optional[int] = None, quantiles: Optional[List[float]] = None, trainer: Trainer = Trainer(), num_parallel_samples: int = 100, ) -> None: encoder = HierarchicalCausalConv1DEncoder( dilation_seq=[1, 3, 9], kernel_size_seq=([3] * len([30, 30, 30])), channels_seq=[30, 30, 30], use_residual=True, use_dynamic_feat=True, use_static_feat=True, ) super(CNN2QRForecaster, self).__init__( freq=freq, prediction_length=prediction_length, encoder=encoder, cardinality=cardinality, embedding_dimension=embedding_dimension, decoder_mlp_layer=decoder_mlp_layer, decoder_mlp_static_dim=decoder_mlp_static_dim, context_length=context_length, scaler=scaler, quantiles=quantiles, trainer=trainer, num_parallel_samples=num_parallel_samples, )
def __init__( self, freq: str, prediction_length: int, context_length: Optional[int] = None, use_past_feat_dynamic_real: bool = False, use_feat_dynamic_real: bool = False, use_feat_static_cat: bool = False, cardinality: List[int] = None, embedding_dimension: List[int] = None, add_time_feature: bool = True, add_age_feature: bool = False, enable_encoder_dynamic_feature: bool = True, enable_decoder_dynamic_feature: bool = True, seed: Optional[int] = None, decoder_mlp_dim_seq: Optional[List[int]] = None, channels_seq: Optional[List[int]] = None, dilation_seq: Optional[List[int]] = None, kernel_size_seq: Optional[List[int]] = None, use_residual: bool = True, quantiles: Optional[List[float]] = None, distr_output: Optional[DistributionOutput] = None, trainer: Trainer = Trainer(), scaling: Optional[bool] = None, scaling_decoder_dynamic_feature: bool = False, num_forking: Optional[int] = None, max_ts_len: Optional[int] = None, is_iqf: bool = True, batch_size: int = 32, ) -> None: assert (distr_output is None) or (quantiles is None) assert ( prediction_length > 0 ), f"Invalid prediction length: {prediction_length}." assert decoder_mlp_dim_seq is None or all( d > 0 for d in decoder_mlp_dim_seq ), "Elements of `mlp_hidden_dimension_seq` should be > 0" assert channels_seq is None or all( d > 0 for d in channels_seq ), "Elements of `channels_seq` should be > 0" assert dilation_seq is None or all( d > 0 for d in dilation_seq ), "Elements of `dilation_seq` should be > 0" # TODO: add support for kernel size=1 assert kernel_size_seq is None or all( d > 1 for d in kernel_size_seq ), "Elements of `kernel_size_seq` should be > 0" assert quantiles is None or all( 0 <= d <= 1 for d in quantiles ), "Elements of `quantiles` should be >= 0 and <= 1" self.decoder_mlp_dim_seq = ( decoder_mlp_dim_seq if decoder_mlp_dim_seq is not None else [30] ) self.channels_seq = ( channels_seq if channels_seq is not None else [30, 30, 30] ) self.dilation_seq = ( dilation_seq if dilation_seq is not None else [1, 3, 9] ) self.kernel_size_seq = ( kernel_size_seq if kernel_size_seq is not None else [7, 3, 3] ) self.quantiles = ( quantiles if (quantiles is not None) or (distr_output is not None) else [0.025, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0.975] ) self.is_iqf = is_iqf assert ( len(self.channels_seq) == len(self.dilation_seq) == len(self.kernel_size_seq) ), ( f"mismatch CNN configurations: {len(self.channels_seq)} vs. " f"{len(self.dilation_seq)} vs. {len(self.kernel_size_seq)}" ) if seed: np.random.seed(seed) mx.random.seed(seed, trainer.ctx) # `use_static_feat` and `use_dynamic_feat` always True because network # always receives input; either from the input data or constants encoder = HierarchicalCausalConv1DEncoder( dilation_seq=self.dilation_seq, kernel_size_seq=self.kernel_size_seq, channels_seq=self.channels_seq, use_residual=use_residual, use_static_feat=True, use_dynamic_feat=True, prefix="encoder_", ) decoder = ForkingMLPDecoder( dec_len=prediction_length, final_dim=self.decoder_mlp_dim_seq[-1], hidden_dimension_sequence=self.decoder_mlp_dim_seq[:-1], prefix="decoder_", ) quantile_output = ( QuantileOutput(self.quantiles, is_iqf=self.is_iqf) if self.quantiles else None ) super().__init__( encoder=encoder, decoder=decoder, quantile_output=quantile_output, distr_output=distr_output, freq=freq, prediction_length=prediction_length, context_length=context_length, use_past_feat_dynamic_real=use_past_feat_dynamic_real, use_feat_dynamic_real=use_feat_dynamic_real, use_feat_static_cat=use_feat_static_cat, enable_encoder_dynamic_feature=enable_encoder_dynamic_feature, enable_decoder_dynamic_feature=enable_decoder_dynamic_feature, cardinality=cardinality, embedding_dimension=embedding_dimension, add_time_feature=add_time_feature, add_age_feature=add_age_feature, trainer=trainer, scaling=scaling, scaling_decoder_dynamic_feature=scaling_decoder_dynamic_feature, num_forking=num_forking, max_ts_len=max_ts_len, batch_size=batch_size, )