def test_prediction_with_dataloder_raw(data_with_covariates, tmp_path): # tests correct concatenation of raw output test_data = data_with_covariates.copy() np.random.seed(2) test_data = test_data.sample(frac=0.5) dataset = TimeSeriesDataSet( test_data, time_idx="time_idx", max_encoder_length=8, max_prediction_length=10, min_prediction_length=1, min_encoder_length=1, target="volume", group_ids=["agency", "sku"], constant_fill_strategy=dict(volume=0.0), allow_missing_timesteps=True, time_varying_unknown_reals=["volume"], time_varying_known_reals=["time_idx"], target_normalizer=GroupNormalizer(groups=["agency", "sku"]), ) net = TemporalFusionTransformer.from_dataset( dataset, learning_rate=1e-6, hidden_size=4, attention_head_size=1, dropout=0.2, hidden_continuous_size=2, log_interval=1, log_val_interval=1, log_gradient_flow=True, ) logger = TensorBoardLogger(tmp_path) trainer = pl.Trainer(max_epochs=1, gradient_clip_val=1e-6, logger=logger) trainer.fit(net, train_dataloaders=dataset.to_dataloader(batch_size=4, num_workers=0)) # choose small batch size to provoke issue res = net.predict(dataset.to_dataloader(batch_size=2, num_workers=0), mode="raw") # check that interpretation works net.interpret_output(res)["attention"] assert net.interpret_output(res.iget( slice(1)))["attention"].size() == torch.Size( (1, net.hparams.max_encoder_length))
def test_distribution_loss(data_with_covariates, tmp_path, gpus): data_with_covariates = data_with_covariates.assign( volume=lambda x: x.volume.round()) dataloaders_with_covariates = make_dataloaders( data_with_covariates, target="volume", time_varying_known_reals=["price_actual"], time_varying_unknown_reals=["volume"], static_categoricals=["agency"], add_relative_time_idx=True, target_normalizer=GroupNormalizer(groups=["agency", "sku"], center=False), ) _integration(dataloaders_with_covariates, tmp_path, gpus, loss=NegativeBinomialDistributionLoss())
def _create_dataset(self, df, valid_p=0.2): df = df_utils.check_dataframe(df) df = self._handle_missing_data(df) df = df[["ds", "y"]] df["time_idx"] = range(df.shape[0]) df["series"] = 0 self.n_data = df.shape[0] self.set_auto_batch_epoch(self.n_data) training_cutoff = df.shape[0] - int(valid_p * df.shape[0]) training = TimeSeriesDataSet( df.iloc[:training_cutoff], time_idx="time_idx", target="y", categorical_encoders={"series": NaNLabelEncoder().fit(df.series)}, group_ids=["series"], min_encoder_length=self.context_length, max_encoder_length=self.context_length, max_prediction_length=self.prediction_length, min_prediction_length=self.prediction_length, time_varying_unknown_reals=["y"], target_normalizer=GroupNormalizer(groups=["series"]), randomize_length=None, add_relative_time_idx=False, add_target_scales=False, ) validation = TimeSeriesDataSet.from_dataset( training, df, min_prediction_idx=training_cutoff) train_dataloader = training.to_dataloader(train=True, batch_size=self.batch_size, num_workers=self.num_workers) val_dataloader = validation.to_dataloader(train=False, batch_size=self.batch_size, num_workers=self.num_workers) return training, train_dataloader, val_dataloader
def test_mqf2_loss(data_with_covariates, tmp_path, gpus): data_with_covariates = data_with_covariates.assign( volume=lambda x: x.volume.round()) dataloaders_with_covariates = make_dataloaders( data_with_covariates, target="volume", time_varying_known_reals=["price_actual"], time_varying_unknown_reals=["volume"], static_categoricals=["agency"], add_relative_time_idx=True, target_normalizer=GroupNormalizer(groups=["agency", "sku"], center=False, transformation="softplus"), ) prediction_length = dataloaders_with_covariates[ "train"].dataset.min_prediction_length _integration( dataloaders_with_covariates, tmp_path, gpus, loss=MQF2DistributionLoss(prediction_length=prediction_length))
shutil.rmtree(tmp_path, ignore_errors=True) net.predict(val_dataloader, fast_dev_run=True, return_index=True, return_decoder_lengths=True) @pytest.mark.parametrize( "kwargs", [ {}, { "cell_type": "GRU" }, dict(data_loader_kwargs=dict(target_normalizer=GroupNormalizer( groups=["agency", "sku"], center=False)), ), dict(data_loader_kwargs=dict(lags={"volume": [2, 5]}, target="volume", time_varying_unknown_reals=["volume"], min_encoder_length=2)), dict(data_loader_kwargs=dict( time_varying_unknown_reals=["volume", "discount"], target=["volume", "discount"], lags={ "volume": [2], "discount": [2] }, )), ], ) def test_integration(data_with_covariates, tmp_path, gpus, kwargs):
def predict(self, future_dataframe): """ Predicts based on the future_dataframe. Should be called only after make_future_dataframe is called Args: future_dataframe: DataFrame form make_future_dataframe function Returns: forecast dataframe """ if self.fitted is False: log.warning("Model has not been fitted. Predictions will be random.") future_dataframe = future_dataframe.copy(deep=True) testing = TimeSeriesDataSet( future_dataframe, time_idx="time_idx", target="y", categorical_encoders={"series": NaNLabelEncoder().fit(future_dataframe.series)}, group_ids=["series"], min_encoder_length=self.context_length, max_encoder_length=self.context_length, max_prediction_length=self.prediction_length, min_prediction_length=self.prediction_length, time_varying_known_reals=["time_idx"], time_varying_unknown_reals=["y"], target_normalizer=GroupNormalizer(groups=["series"], transformation="softplus", center=False), add_relative_time_idx=True, add_target_scales=True, add_encoder_length=True, ) new_raw_predictions, new_x = self.model.predict(testing, mode="raw", return_x=True) y_predicted = self.model.to_prediction(new_raw_predictions).detach().cpu() # [0, : new_x["decoder_lengths"][0]] y_predicted = y_predicted.detach().numpy() def pad_with(vector, pad_width, iaxis, kwargs): pad_value = kwargs.get("padder", np.nan) vector[: pad_width[0]] = pad_value vector[-pad_width[1] :] = pad_value y_pred_padded = np.pad(y_predicted, self.prediction_length, pad_with)[ self.prediction_length : -1, self.prediction_length : -self.prediction_length ] y_pred_padded = np.vstack([np.roll(y_pred_padded[:, i], i, axis=0) for i in range(y_pred_padded.shape[1])]).T result = pd.DataFrame( np.ones(shape=(len(future_dataframe), (2 + self.prediction_length))) * np.nan, columns=["ds", "y"] + [f"yhat{i}" for i in range(1, self.prediction_length + 1)], ) result["ds"] = future_dataframe["ds"] result.loc[: len(future_dataframe) - (self.periods + 1), "y"] = ( future_dataframe["y"].iloc[: len(future_dataframe) - (self.periods)].values ) first_part = result.iloc[: self.context_length] second_part = result.iloc[self.context_length :] second_part.loc[:, [col for col in second_part.columns[2:]]] = y_pred_padded result = pd.concat([first_part, second_part]) for i in range(1, self.prediction_length + 1): result[f"residual{i}"] = result[f"yhat{i}"] - result["y"] return result
net.predict(val_dataloader, fast_dev_run=True, return_index=True, return_decoder_lengths=True) finally: shutil.rmtree(tmp_path, ignore_errors=True) net.predict(val_dataloader, fast_dev_run=True, return_index=True, return_decoder_lengths=True) @pytest.mark.parametrize( "kwargs", [ {}, {"cell_type": "GRU"}, dict( loss=LogNormalDistributionLoss(), clip_target=True, data_loader_kwargs=dict(target_normalizer=GroupNormalizer(groups=["agency", "sku"], transformation="log")), ), dict( loss=NegativeBinomialDistributionLoss(), clip_target=False, data_loader_kwargs=dict(target_normalizer=GroupNormalizer(groups=["agency", "sku"], center=False)), ), dict( loss=BetaDistributionLoss(), clip_target=True, data_loader_kwargs=dict( target_normalizer=GroupNormalizer(groups=["agency", "sku"], transformation="logit") ), ), dict( data_loader_kwargs=dict(