예제 #1
0
    def from_dataset(
        cls,
        dataset: TimeSeriesDataSet,
        allowed_encoder_known_variable_names: List[str] = None,
        **kwargs,
    ):
        """
        Create model from dataset.

        Args:
            dataset: timeseries dataset
            allowed_encoder_known_variable_names: List of known variables that are allowed in encoder, defaults to all
            **kwargs: additional arguments such as hyperparameters for model (see ``__init__()``)

        Returns:
            DeepAR network
        """
        # assert fixed encoder and decoder length for the moment
        new_kwargs = {}
        if dataset.multi_target:
            new_kwargs.setdefault(
                "loss",
                MultiLoss([NormalDistributionLoss()] *
                          len(dataset.target_names)))
        new_kwargs.update(kwargs)
        assert not isinstance(dataset.target_normalizer, NaNLabelEncoder) and (
            not isinstance(dataset.target_normalizer, MultiNormalizer) or all([
                not isinstance(normalizer, NaNLabelEncoder)
                for normalizer in dataset.target_normalizer
            ])
        ), "target(s) should be continuous - categorical targets are not supported"  # todo: remove this restriction
        return super().from_dataset(dataset,
                                    allowed_encoder_known_variable_names=
                                    allowed_encoder_known_variable_names,
                                    **new_kwargs)
예제 #2
0
    def from_dataset(
        cls,
        dataset: TimeSeriesDataSet,
        allowed_encoder_known_variable_names: List[str] = None,
        **kwargs,
    ):
        """
        Create model from dataset.

        Args:
            dataset: timeseries dataset
            allowed_encoder_known_variable_names: List of known variables that are allowed in encoder, defaults to all
            **kwargs: additional arguments such as hyperparameters for model (see ``__init__()``)

        Returns:
            TemporalFusionTransformer
        """
        # add maximum encoder length
        new_kwargs = dict(max_encoder_length=dataset.max_encoder_length)

        # infer output size
        def get_output_size(normalizer, loss):
            if isinstance(loss, QuantileLoss):
                return len(loss.quantiles)
            elif isinstance(normalizer, NaNLabelEncoder):
                return len(normalizer.classes_)
            else:
                return 1

        loss = kwargs.get("loss", QuantileLoss())
        # handle multiple targets
        new_kwargs["n_targets"] = len(dataset.target_names)
        if new_kwargs["n_targets"] > 1:  # try to infer number of ouput sizes
            if not isinstance(loss, MultiLoss):
                loss = MultiLoss([deepcopy(loss)] * new_kwargs["n_targets"])
                new_kwargs["loss"] = loss
            if isinstance(loss, MultiLoss) and "output_size" not in kwargs:
                new_kwargs["output_size"] = [
                    get_output_size(normalizer, l) for normalizer, l in zip(
                        dataset.target_normalizer.normalizers, loss.metrics)
                ]
        elif "output_size" not in kwargs:
            new_kwargs["output_size"] = get_output_size(
                dataset.target_normalizer, loss)

        # update defaults
        new_kwargs.update(kwargs)

        # create class and return
        return super().from_dataset(dataset,
                                    allowed_encoder_known_variable_names=
                                    allowed_encoder_known_variable_names,
                                    **new_kwargs)
예제 #3
0
def test_integration(multiple_dataloaders_with_covariates, tmp_path, gpus):
    train_dataloader = multiple_dataloaders_with_covariates["train"]
    val_dataloader = multiple_dataloaders_with_covariates["val"]
    early_stop_callback = EarlyStopping(monitor="val_loss",
                                        min_delta=1e-4,
                                        patience=1,
                                        verbose=False,
                                        mode="min")

    # check training
    logger = TensorBoardLogger(tmp_path)
    checkpoint = ModelCheckpoint(filepath=tmp_path)
    trainer = pl.Trainer(
        checkpoint_callback=checkpoint,
        max_epochs=3,
        gpus=gpus,
        weights_summary="top",
        gradient_clip_val=0.1,
        callbacks=[early_stop_callback],
        fast_dev_run=True,
        logger=logger,
    )
    # test monotone constraints automatically
    if "discount_in_percent" in train_dataloader.dataset.reals:
        monotone_constaints = {"discount_in_percent": +1}
        cuda_context = torch.backends.cudnn.flags(enabled=False)
    else:
        monotone_constaints = {}
        cuda_context = nullcontext()

    with cuda_context:
        if isinstance(train_dataloader.dataset.target_normalizer,
                      NaNLabelEncoder):
            loss = CrossEntropy()
        elif isinstance(train_dataloader.dataset.target_normalizer,
                        MultiNormalizer):
            loss = MultiLoss([
                CrossEntropy()
                if isinstance(normalizer, NaNLabelEncoder) else QuantileLoss()
                for normalizer in
                train_dataloader.dataset.target_normalizer.normalizers
            ])
        else:
            loss = QuantileLoss()
        net = TemporalFusionTransformer.from_dataset(
            train_dataloader.dataset,
            learning_rate=0.15,
            hidden_size=4,
            attention_head_size=1,
            dropout=0.2,
            hidden_continuous_size=2,
            loss=loss,
            log_interval=5,
            log_val_interval=1,
            log_gradient_flow=True,
            monotone_constaints=monotone_constaints,
        )
        net.size()
        try:
            trainer.fit(
                net,
                train_dataloader=train_dataloader,
                val_dataloaders=val_dataloader,
            )

            # check loading
            net = TemporalFusionTransformer.load_from_checkpoint(
                checkpoint.best_model_path)

            # check prediction
            net.predict(val_dataloader,
                        fast_dev_run=True,
                        return_index=True,
                        return_decoder_lengths=True)
            # check prediction on gpu
            if not (isinstance(gpus, int) and gpus == 0):
                net.to("cuda")
                net.predict(val_dataloader,
                            fast_dev_run=True,
                            return_index=True,
                            return_decoder_lengths=True)

        finally:
            shutil.rmtree(tmp_path, ignore_errors=True)
예제 #4
0
def test_integration(multiple_dataloaders_with_covariates, tmp_path, gpus):
    train_dataloader = multiple_dataloaders_with_covariates["train"]
    val_dataloader = multiple_dataloaders_with_covariates["val"]
    early_stop_callback = EarlyStopping(monitor="val_loss", min_delta=1e-4, patience=1, verbose=False, mode="min")

    # check training
    logger = TensorBoardLogger(tmp_path)
    trainer = pl.Trainer(
        max_epochs=2,
        gpus=gpus,
        weights_summary="top",
        gradient_clip_val=0.1,
        callbacks=[early_stop_callback],
        checkpoint_callback=True,
        default_root_dir=tmp_path,
        limit_train_batches=2,
        limit_val_batches=2,
        logger=logger,
    )
    # test monotone constraints automatically
    if "discount_in_percent" in train_dataloader.dataset.reals:
        monotone_constaints = {"discount_in_percent": +1}
        cuda_context = torch.backends.cudnn.flags(enabled=False)
    else:
        monotone_constaints = {}
        cuda_context = nullcontext()

    with cuda_context:
        if isinstance(train_dataloader.dataset.target_normalizer, NaNLabelEncoder):
            loss = CrossEntropy()
        elif isinstance(train_dataloader.dataset.target_normalizer, MultiNormalizer):
            loss = MultiLoss(
                [
                    CrossEntropy() if isinstance(normalizer, NaNLabelEncoder) else QuantileLoss()
                    for normalizer in train_dataloader.dataset.target_normalizer.normalizers
                ]
            )
        else:
            loss = QuantileLoss()
        net = TemporalFusionTransformer.from_dataset(
            train_dataloader.dataset,
            learning_rate=0.15,
            hidden_size=4,
            attention_head_size=1,
            dropout=0.2,
            hidden_continuous_size=2,
            loss=loss,
            log_interval=5,
            log_val_interval=1,
            log_gradient_flow=True,
            monotone_constaints=monotone_constaints,
        )
        net.size()
        try:
            trainer.fit(
                net,
                train_dataloader=train_dataloader,
                val_dataloaders=val_dataloader,
            )

            # check loading
            net = TemporalFusionTransformer.load_from_checkpoint(trainer.checkpoint_callback.best_model_path)

            # check prediction
            predictions, x, index = net.predict(val_dataloader, return_index=True, return_x=True)
            pred_len = len(multiple_dataloaders_with_covariates["val"].dataset)

            # check that output is of correct shape
            def check(x):
                if isinstance(x, (tuple, list)):
                    for xi in x:
                        check(xi)
                elif isinstance(x, dict):
                    for xi in x.values():
                        check(xi)
                else:
                    assert pred_len == x.shape[0], "first dimension should be prediction length"

            check(predictions)
            check(x)
            check(index)

            # check prediction on gpu
            if not (isinstance(gpus, int) and gpus == 0):
                net.to("cuda")
                net.predict(val_dataloader, fast_dev_run=True, return_index=True, return_decoder_lengths=True)

        finally:
            shutil.rmtree(tmp_path, ignore_errors=True)
예제 #5
0
                and len(dataset.time_varying_unknown_categoricals) == 0
                and len(dataset.static_categoricals) == 0
                and len(dataset.static_reals) == 0
                and len(dataset.time_varying_unknown_reals) == len(
                    dataset.target_names
                )  # Expect as as many unknown reals as targets
                ), "Only covariate should be in 'time_varying_unknown_reals'"

        return super().from_dataset(dataset, **new_kwargs)


model = FullyConnectedMultiTargetModel.from_dataset(
    multi_target_dataset,
    hidden_size=10,
    n_hidden_layers=2,
    loss=MultiLoss(metrics=[MAE(), SMAPE()], weights=[2.0, 1.0]),
)
model.summarize("full")
model.hparams

# %% [markdown]
# Now, let's pass some data through our model and calculate the loss.

# %%
out = model(x)
out

# %%
y_hat = model.transform_output(
    out
)  # the model's transform_output method re-scales/de-normalizes the predictions to into the real target space
예제 #6
0
                    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",
    [
        {},
        dict(
            loss=MultiLoss([QuantileLoss(), MAE()]),
            data_loader_kwargs=dict(
                time_varying_unknown_reals=["volume", "discount"],
                target=["volume", "discount"],
            ),
        ),
        dict(
            loss=CrossEntropy(),
            data_loader_kwargs=dict(target="agency", ),
        ),
    ],
)
def test_integration(data_with_covariates, tmp_path, gpus, kwargs):
    _integration(data_with_covariates.assign(target=lambda x: x.volume),
                 tmp_path, gpus, **kwargs)