Beispiel #1
0
    def __init__(
        self,
        freq: str,
        prediction_length: int,
        trainer: Trainer = Trainer(),
        context_length: Optional[int] = None,
        num_layers: int = 2,
        num_cells: int = 40,
        cell_type: str = 'lstm',
        num_eval_samples: int = 100,
        dropout_rate: float = 0.1,
        use_feat_dynamic_real: bool = False,
        use_feat_static_cat: bool = False,
        cardinality: Optional[List[int]] = None,
        embedding_dimension: int = 20,
        distr_output: DistributionOutput = StudentTOutput(),
        scaling: bool = True,
        lags_seq: Optional[List[int]] = None,
        time_features: Optional[List[TimeFeature]] = None,
    ) -> None:
        super().__init__(trainer=trainer)

        assert (prediction_length >
                0), "The value of `prediction_length` should be > 0"
        assert (context_length is None or context_length > 0
                ), "The value of `context_length` should be > 0"
        assert num_layers > 0, "The value of `num_layers` should be > 0"
        assert num_cells > 0, "The value of `num_cells` should be > 0"
        assert (num_eval_samples >
                0), "The value of `num_eval_samples` should be > 0"
        assert dropout_rate >= 0, "The value of `dropout_rate` should be >= 0"
        assert (cardinality is not None or not use_feat_static_cat
                ), "You must set `cardinality` if `use_feat_static_cat=True`"
        assert cardinality is None or [
            c > 0 for c in cardinality
        ], "Elements of `cardinality` should be > 0"
        assert (embedding_dimension >
                0), "The value of `embedding_dimension` should be > 0"

        self.freq = freq
        self.context_length = (context_length if context_length is not None
                               else prediction_length)
        self.prediction_length = prediction_length
        self.distr_output = distr_output
        self.num_layers = num_layers
        self.num_cells = num_cells
        self.cell_type = cell_type
        self.num_sample_paths = num_eval_samples
        self.dropout_rate = dropout_rate
        self.use_feat_dynamic_real = use_feat_dynamic_real
        self.use_feat_static_cat = use_feat_static_cat
        self.cardinality = cardinality if use_feat_static_cat else [1]
        self.embedding_dimension = embedding_dimension
        self.scaling = scaling
        self.lags_seq = (lags_seq if lags_seq is not None else
                         get_lags_for_frequency(freq_str=freq))
        self.time_features = (time_features if time_features is not None else
                              time_features_from_frequency_str(self.freq))

        self.history_length = self.context_length + max(self.lags_seq)
 def get_distribution_type(self):
     """ get distribution type of dataset """
     if self.count_data:
         return NegativeBinomialOutput()
     elif self.count_data == False:
         return StudentTOutput()
     elif "http://schema.org/Integer" in self.target_semantic_types:
         if np.min(self.frame.iloc[:, self.target_col]) >= 0:
             return NegativeBinomialOutput()
         else:
             return StudentTOutput()
     elif "http://schema.org/Float" in self.target_semantic_types:
         return StudentTOutput()
     else:
         raise ValueError(
             "Target column is not of type 'Integer' or 'Float'")
Beispiel #3
0
    def __init__(
            self,
            freq: str,
            context_length: int,
            prediction_length: int,
            trainer: Trainer = Trainer(),
            num_layers: int = 1,
            num_cells: int = 50,
            cell_type: str = "lstm",
            num_eval_samples: int = 100,
            cardinality: List[int] = list([1]),
            embedding_dimension: int = 10,
            distr_output: DistributionOutput = StudentTOutput(),
    ) -> None:
        model = RNN(mode=cell_type,
                    num_layers=num_layers,
                    num_hidden=num_cells)

        super(CanonicalRNNEstimator, self).__init__(
            model=model,
            is_sequential=True,
            freq=freq,
            context_length=context_length,
            prediction_length=prediction_length,
            trainer=trainer,
            num_eval_samples=num_eval_samples,
            cardinality=cardinality,
            embedding_dimension=embedding_dimension,
            distr_output=distr_output,
        )
Beispiel #4
0
    def __init__(
            self,
            freq: str,
            context_length: int,
            prediction_length: int,
            trainer: Trainer = Trainer(),
            hidden_dim_sequence=list([50]),
            num_eval_samples: int = 100,
            cardinality: List[int] = list([1]),
            embedding_dimension: int = 10,
            distr_output: DistributionOutput = StudentTOutput(),
    ) -> None:
        model = nn.HybridSequential()

        for layer, layer_dim in enumerate(hidden_dim_sequence):
            model.add(
                nn.Dense(
                    layer_dim,
                    flatten=False,
                    activation="relu",
                    prefix="mlp_%d_" % layer,
                ))

        super(MLPForecasterEstimator, self).__init__(
            model=model,
            is_sequential=False,
            freq=freq,
            context_length=context_length,
            prediction_length=prediction_length,
            trainer=trainer,
            num_eval_samples=num_eval_samples,
            cardinality=cardinality,
            embedding_dimension=embedding_dimension,
            distr_output=distr_output,
        )
Beispiel #5
0
    def __init__(
        self,
        freq: str,
        prediction_length: int,
        trainer: Trainer = Trainer(),
        num_hidden_dimensions: List[int] = list([40, 40]),
        context_length: Optional[int] = None,
        distr_output: DistributionOutput = StudentTOutput(),
        batch_normalization: bool = False,
        mean_scaling: bool = True,
        num_eval_samples: int = 100,
    ) -> None:
        """
        Defines an estimator. All parameters should be serializable.
        """
        super().__init__(trainer=trainer)

        assert (prediction_length >
                0), "The value of `prediction_length` should be > 0"
        assert (context_length is None or context_length > 0
                ), "The value of `context_length` should be > 0"
        assert all([d > 0 for d in num_hidden_dimensions
                    ]), "Elements of `num_hidden_dimensions` should be > 0"
        assert (num_eval_samples >
                0), "The value of `num_eval_samples` should be > 0"

        self.num_hidden_dimensions = num_hidden_dimensions
        self.prediction_length = prediction_length
        self.context_length = (context_length if context_length is not None
                               else prediction_length)
        self.freq = freq
        self.distr_output = distr_output
        self.batch_normalization = batch_normalization
        self.num_sample_paths = num_eval_samples
        self.mean_scaling = mean_scaling
Beispiel #6
0
    def __init__(
            self,
            freq: str,
            prediction_length: int,
            num_hidden_global: int = 50,
            num_layers_global: int = 1,
            num_factors: int = 10,
            num_hidden_local: int = 5,
            num_layers_local: int = 1,
            cell_type: str = "lstm",
            trainer: Trainer = Trainer(),
            context_length: Optional[int] = None,
            num_eval_samples: int = 100,
            cardinality: List[int] = list([1]),
            embedding_dimension: int = 10,
            distr_output: DistributionOutput = StudentTOutput(),
    ) -> None:
        super().__init__(trainer=trainer)

        assert (prediction_length >
                0), "The value of `prediction_length` should be > 0"
        assert (context_length is None or context_length > 0
                ), "The value of `context_length` should be > 0"
        assert num_layers_global > 0, "The value of `num_layers` should be > 0"
        assert num_hidden_global > 0, "The value of `num_hidden` should be > 0"
        assert num_factors > 0, "The value of `num_factors` should be > 0"
        assert (num_hidden_local >
                0), "The value of `num_hidden_local` should be > 0"
        assert (num_layers_local >
                0), "The value of `num_layers_local` should be > 0"
        assert [c > 0 for c in cardinality
                ], "Elements of `cardinality` should be > 0"
        assert (embedding_dimension >
                0), "The value of `embedding_dimension` should be > 0"
        assert (num_eval_samples >
                0), "The value of `num_eval_samples` should be > 0"

        self.freq = freq
        self.context_length = (context_length if context_length is not None
                               else prediction_length)
        self.prediction_length = prediction_length
        self.distr_output = distr_output
        self.num_sample_paths = num_eval_samples
        self.cardinality = cardinality
        self.embedding_dimensions = [embedding_dimension for _ in cardinality]

        self.global_model = RNNModel(
            mode=cell_type,
            num_hidden=num_hidden_global,
            num_layers=num_layers_global,
            num_output=num_factors,
        )

        # TODO: Allow the local model to be defined as an arbitrary local model, e.g. DF-GP and DF-LDS
        self.local_model = RNNModel(
            mode=cell_type,
            num_hidden=num_hidden_local,
            num_layers=num_layers_local,
            num_output=1,
        )
Beispiel #7
0
    def __init__(
            self,
            model: HybridBlock,
            is_sequential: bool,
            freq: str,
            context_length: int,
            prediction_length: int,
            trainer: Trainer = Trainer(),
            num_eval_samples: int = 100,
            cardinality: List[int] = list([1]),
            embedding_dimension: int = 10,
            distr_output: DistributionOutput = StudentTOutput(),
    ) -> None:
        super().__init__(trainer=trainer)

        # TODO: error checking
        self.freq = freq
        self.context_length = context_length
        self.prediction_length = prediction_length
        self.distr_output = distr_output
        self.num_sample_paths = num_eval_samples
        self.cardinality = cardinality
        self.embedding_dimensions = [embedding_dimension for _ in cardinality]
        self.model = model
        self.is_sequential = is_sequential
Beispiel #8
0
def test_studentT_likelihood(
    mu_sigma_nu: Tuple[float, float, float], hybridize: bool
) -> None:
    '''
    Test to check that maximizing the likelihood recovers the parameters
    '''
    # test instance
    mu, sigma, nu = mu_sigma_nu

    # generate samples
    mus = mx.nd.zeros((NUM_SAMPLES, 1)) + mu
    sigmas = mx.nd.zeros((NUM_SAMPLES, 1)) + sigma
    nus = mx.nd.zeros((NUM_SAMPLES, 1)) + nu

    distr = StudentT(mus, sigmas, nus)
    samples = distr.sample()

    # nu takes very long to learn, so we initialize it at the true value.
    # transform used is softplus(x) + 2
    init_bias = [
        mu - START_TOL_MULTIPLE * TOL * mu,
        inv_softplus(sigma - START_TOL_MULTIPLE * TOL * sigma),
        inv_softplus(nu - 2),
    ]

    mu_hat, sigma_hat, nu_hat = maximum_likelihood_estimate_sgd(
        StudentTOutput(),
        samples,
        init_biases=init_bias,
        hybridize=hybridize,
        num_epochs=PositiveInt(10),
        learning_rate=1e-2,
    )

    assert (
        np.abs(mu_hat - mu) < TOL * mu
    ), f"mu did not match: mu = {mu}, mu_hat = {mu_hat}"
    assert (
        np.abs(sigma_hat - sigma) < TOL * sigma
    ), f"sigma did not match: sigma = {sigma}, sigma_hat = {sigma_hat}"
    assert (
        np.abs(nu_hat - nu) < TOL * nu
    ), "nu0 did not match: nu0 = %s, nu_hat = %s" % (nu, nu_hat)
Beispiel #9
0
    def __init__(
            self,
            freq: str,
            context_length: int,
            prediction_length: int,
            num_layers: int = 1,
            num_hidden: int = 50,
            num_factor: int = 10,
            num_hidden_noise: int = 5,
            num_layers_noise: int = 1,
            cell_type: str = "lstm",
            trainer: Trainer = Trainer(),
            num_eval_samples: int = 100,
            cardinality: List[int] = list([1]),
            embedding_dimension: int = 10,
            distr_output: DistributionOutput = StudentTOutput(),
    ) -> None:
        super().__init__(trainer=trainer)

        # TODO: error checking
        self.freq = freq
        self.context_length = context_length
        self.prediction_length = prediction_length
        self.distr_output = distr_output
        self.num_sample_paths = num_eval_samples
        self.cardinality = cardinality
        self.embedding_dimensions = [embedding_dimension for _ in cardinality]

        self.global_factor = RNNModel(
            mode=cell_type,
            num_hidden=num_hidden,
            num_layers=num_layers,
            num_output=num_factor,
        )

        self.noise_process = RNNModel(
            mode=cell_type,
            num_hidden=num_hidden_noise,
            num_layers=num_layers_noise,
            num_output=1,
        )
def test_distribution():
    """
    Makes sure additional tensors can be accessed and have expected shapes
    """
    prediction_length = ds_info.prediction_length
    estimator = DeepAREstimator(
        freq=freq,
        prediction_length=prediction_length,
        trainer=Trainer(epochs=1, num_batches_per_epoch=1),
        distr_output=StudentTOutput(),
    )

    train_output = estimator.train_model(train_ds)

    # todo adapt loader to anomaly detection use-case
    batch_size = 2
    num_samples = 3

    training_data_loader = TrainDataLoader(
        dataset=train_ds,
        transform=train_output.transformation,
        batch_size=batch_size,
        num_batches_per_epoch=estimator.trainer.num_batches_per_epoch,
        ctx=mx.cpu(),
    )

    seq_len = 2 * ds_info.prediction_length

    for data_entry in islice(training_data_loader, 1):
        input_names = get_hybrid_forward_input_names(train_output.trained_net)

        distr = train_output.trained_net.distribution(
            *[data_entry[k] for k in input_names]
        )

        assert distr.sample(num_samples).shape == (
            num_samples,
            batch_size,
            seq_len,
        )
    UniformOutput,
)


@pytest.mark.parametrize(
    "distr_out, data, scale, expected_batch_shape, expected_event_shape",
    [
        (
            GaussianOutput(),
            mx.nd.random.normal(shape=(3, 4, 5, 6)),
            [None, mx.nd.ones(shape=(3, 4, 5))],
            (3, 4, 5),
            (),
        ),
        (
            StudentTOutput(),
            mx.nd.random.normal(shape=(3, 4, 5, 6)),
            [None, mx.nd.ones(shape=(3, 4, 5))],
            (3, 4, 5),
            (),
        ),
        (
            MultivariateGaussianOutput(dim=5),
            mx.nd.random.normal(shape=(3, 4, 10)),
            [None, mx.nd.ones(shape=(3, 4, 5))],
            (3, 4),
            (5,),
        ),
        (
            LaplaceOutput(),
            mx.nd.random.normal(shape=(3, 4, 5, 6)),
Beispiel #12
0
    def __init__(
        self,
        freq: str,
        prediction_length: int,
        context_length: Optional[int] = None,
        trainer: Trainer = Trainer(),
        dropout_rate: float = 0.1,
        cardinality: Optional[List[int]] = None,
        embedding_dimension: int = 20,
        distr_output: DistributionOutput = StudentTOutput(),
        model_dim: int = 32,
        inner_ff_dim_scale: int = 4,
        pre_seq: str = "dn",
        post_seq: str = "drn",
        act_type: str = "softrelu",
        num_heads: int = 8,
        scaling: bool = True,
        lags_seq: Optional[List[int]] = None,
        time_features: Optional[List[TimeFeature]] = None,
        use_feat_dynamic_real: bool = False,
        use_feat_static_cat: bool = False,
        num_parallel_samples: int = 100,
    ) -> None:
        super().__init__(trainer=trainer)

        assert (
            prediction_length > 0
        ), "The value of `prediction_length` should be > 0"
        assert (
            context_length is None or context_length > 0
        ), "The value of `context_length` should be > 0"
        assert dropout_rate >= 0, "The value of `dropout_rate` should be >= 0"
        assert (
            cardinality is not None or not use_feat_static_cat
        ), "You must set `cardinality` if `use_feat_static_cat=True`"
        assert cardinality is None or [
            c > 0 for c in cardinality
        ], "Elements of `cardinality` should be > 0"
        assert (
            embedding_dimension > 0
        ), "The value of `embedding_dimension` should be > 0"
        assert (
            num_parallel_samples > 0
        ), "The value of `num_parallel_samples` should be > 0"

        self.freq = freq
        self.prediction_length = prediction_length
        self.context_length = (
            context_length if context_length is not None else prediction_length
        )
        self.distr_output = distr_output
        self.dropout_rate = dropout_rate
        self.use_feat_dynamic_real = use_feat_dynamic_real
        self.use_feat_static_cat = use_feat_static_cat
        self.cardinality = cardinality if use_feat_static_cat else [1]
        self.embedding_dimension = embedding_dimension
        self.num_parallel_samples = num_parallel_samples
        self.lags_seq = (
            lags_seq
            if lags_seq is not None
            else get_lags_for_frequency(freq_str=freq)
        )
        self.time_features = (
            time_features
            if time_features is not None
            else time_features_from_frequency_str(self.freq)
        )
        self.history_length = self.context_length + max(self.lags_seq)
        self.scaling = scaling

        self.config = {
            "model_dim": model_dim,
            "pre_seq": pre_seq,
            "post_seq": post_seq,
            "dropout_rate": dropout_rate,
            "inner_ff_dim_scale": inner_ff_dim_scale,
            "act_type": act_type,
            "num_heads": num_heads,
        }

        self.encoder = TransformerEncoder(
            self.context_length, self.config, prefix="enc_"
        )
        self.decoder = TransformerDecoder(
            self.prediction_length, self.config, prefix="dec_"
        )
Beispiel #13
0
    def __init__(
        self,
        freq: str,
        prediction_length: int,
        trainer: Trainer = Trainer(),
        context_length: Optional[int] = None,
        num_layers: int = 2,
        num_cells: int = 40,
        cell_type: str = "lstm",
        dropout_rate: float = 0.1,
        use_feat_dynamic_real: bool = False,
        use_feat_static_cat: bool = False,
        use_feat_static_real: bool = False,
        cardinality: Optional[List[int]] = None,
        embedding_dimension: Optional[List[int]] = None,
        distr_output: DistributionOutput = StudentTOutput(),
        scaling: bool = True,
        lags_seq: Optional[List[int]] = None,
        time_features: Optional[List[TimeFeature]] = None,
        num_parallel_samples: int = 100,
        imputation_method: Optional[MissingValueImputation] = None,
        dtype: DType = np.float32,
    ) -> None:
        super().__init__(trainer=trainer, dtype=dtype)

        assert (
            prediction_length > 0
        ), "The value of `prediction_length` should be > 0"
        assert (
            context_length is None or context_length > 0
        ), "The value of `context_length` should be > 0"
        assert num_layers > 0, "The value of `num_layers` should be > 0"
        assert num_cells > 0, "The value of `num_cells` should be > 0"
        assert dropout_rate >= 0, "The value of `dropout_rate` should be >= 0"
        assert (cardinality and use_feat_static_cat) or (
            not (cardinality or use_feat_static_cat)
        ), "You should set `cardinality` if and only if `use_feat_static_cat=True`"
        assert cardinality is None or all(
            [c > 0 for c in cardinality]
        ), "Elements of `cardinality` should be > 0"
        assert embedding_dimension is None or all(
            [e > 0 for e in embedding_dimension]
        ), "Elements of `embedding_dimension` should be > 0"
        assert (
            num_parallel_samples > 0
        ), "The value of `num_parallel_samples` should be > 0"

        self.freq = freq
        self.context_length = (
            context_length if context_length is not None else prediction_length
        )
        self.prediction_length = prediction_length
        self.distr_output = distr_output
        self.distr_output.dtype = dtype
        self.num_layers = num_layers
        self.num_cells = num_cells
        self.cell_type = cell_type
        self.dropout_rate = dropout_rate
        self.use_feat_dynamic_real = use_feat_dynamic_real
        self.use_feat_static_cat = use_feat_static_cat
        self.use_feat_static_real = use_feat_static_real
        self.cardinality = (
            cardinality if cardinality and use_feat_static_cat else [1]
        )
        self.embedding_dimension = (
            embedding_dimension
            if embedding_dimension is not None
            else [min(50, (cat + 1) // 2) for cat in self.cardinality]
        )
        self.scaling = scaling
        self.lags_seq = (
            lags_seq
            if lags_seq is not None
            else get_lags_for_frequency(freq_str=freq)
        )
        self.time_features = (
            time_features
            if time_features is not None
            else time_features_from_frequency_str(self.freq)
        )

        self.history_length = self.context_length + max(self.lags_seq)

        self.num_parallel_samples = num_parallel_samples

        self.imputation_method = (
            imputation_method
            if imputation_method is not None
            else DummyValueImputation(self.distr_output.value_in_support)
        )
    DirichletMultinomialOutput,
)


@pytest.mark.parametrize(
    "distr_out, data, scale, expected_batch_shape, expected_event_shape",
    [
        (
            GaussianOutput(),
            mx.nd.random.normal(shape=(3, 4, 5, 6)),
            [None, mx.nd.ones(shape=(3, 4, 5))],
            (3, 4, 5),
            (),
        ),
        (
            StudentTOutput(),
            mx.nd.random.normal(shape=(3, 4, 5, 6)),
            [None, mx.nd.ones(shape=(3, 4, 5))],
            (3, 4, 5),
            (),
        ),
        (
            GammaOutput(),
            mx.nd.random.gamma(shape=(3, 4, 5, 6)),
            [None, mx.nd.ones(shape=(3, 4, 5))],
            (3, 4, 5),
            (),
        ),
        (
            MultivariateGaussianOutput(dim=5),
            mx.nd.random.normal(shape=(3, 4, 10)),
Beispiel #15
0
        )
        < 0.05
    )

    # can only calculated cdf for gaussians currently
    if isinstance(distr1, Gaussian) and isinstance(distr2, Gaussian):
        emp_cdf, edges = empirical_cdf(samples_mix.asnumpy())
        calc_cdf = mixture.cdf(mx.nd.array(edges)).asnumpy()
        assert np.allclose(calc_cdf[1:, :], emp_cdf, atol=1e-2)


@pytest.mark.parametrize(
    "distribution_outputs",
    [
        ((GaussianOutput(), GaussianOutput()),),
        ((GaussianOutput(), StudentTOutput(), LaplaceOutput()),),
        ((MultivariateGaussianOutput(3), MultivariateGaussianOutput(3)),),
    ],
)
def test_mixture_output(distribution_outputs) -> None:
    mdo = MixtureDistributionOutput(*distribution_outputs)

    args_proj = mdo.get_args_proj()
    args_proj.initialize()

    input = mx.nd.ones(shape=(512, 30))

    distr_args = args_proj(input)
    d = mdo.distribution(distr_args)

    samples = d.sample(num_samples=NUM_SAMPLES)
Beispiel #16
0
def train(args):

    # Parse arguments
    epochs = args.epochs
    pred_length = args.pred_length
    num_layers = args.num_layers
    num_cells = args.num_cells
    dropout_rate = args.dropout_rate
    batch_size = args.batch_size
    lr = args.lr
    model_dir = args.model_dir
    data_dir = args.data_dir
    num_gpus = args.num_gpus
    output_dir = args.output_dir
    device = "gpu" if num_gpus > 0 else "cpu"
    FREQ = 'D'

    # Get training data
    target_df = pd.read_csv(os.path.join(data_dir, 'target_train.csv'))
    target_df.set_index(target_df.columns[0], inplace=True)
    target = target_df.values
    num_steps, num_series = target_df.shape
    start_dt = target_df.index[0]

    custom_ds_metadata = {
        'num_series': num_series,
        'num_steps': num_steps,
        'prediction_length': pred_length,
        'freq': FREQ,
        'start': [start_dt for _ in range(num_series)]
    }

    # Prepare GlounTS Dataset
    train_lst = []
    for i in range(0, num_series):
        target_vec = target[:-pred_length, i]
        dic = {FieldName.TARGET: target_vec, FieldName.START: start_dt}

        train_lst.append(dic)

    test_lst = []
    for i in range(0, num_series):
        target_vec = target[:, i]
        dic = {FieldName.TARGET: target_vec, FieldName.START: start_dt}
        test_lst.append(dic)

    train_ds = ListDataset(train_lst, freq=FREQ)
    test_ds = ListDataset(test_lst, freq=FREQ)
    train_entry = next(iter(train_ds))
    train_entry.keys()

    # Define Estimator
    trainer = Trainer(ctx=device,
                      epochs=epochs,
                      learning_rate=lr,
                      batch_size=batch_size)

    deepar_estimator = DeepAREstimator(freq=FREQ,
                                       prediction_length=pred_length,
                                       num_cells=num_cells,
                                       dropout_rate=dropout_rate,
                                       num_layers=num_layers,
                                       distr_output=StudentTOutput(),
                                       trainer=trainer)

    # Train the model
    deepar_predictor = deepar_estimator.train(train_ds)

    # Evaluate trained model on test data
    forecast_it, ts_it = make_evaluation_predictions(test_ds,
                                                     deepar_predictor,
                                                     num_samples=100)
    forecasts = list(forecast_it)
    tss = list(ts_it)
    evaluator = Evaluator(quantiles=[0.1, 0.5, 0.9])
    agg_metrics, item_metrics = evaluator(iter(tss),
                                          iter(forecasts),
                                          num_series=len(test_ds))

    metrics = [
        'RMSE', 'MAPE', 'wQuantileLoss[0.1]', 'wQuantileLoss[0.5]',
        'wQuantileLoss[0.9]', 'mean_wQuantileLoss'
    ]
    metrics_dic = dict(
        (key, value) for key, value in agg_metrics.items() if key in metrics)
    print(json.dumps(metrics_dic, indent=2))

    # Save the model
    deepar_predictor.serialize(pathlib.Path(model_dir))
    return deepar_predictor
def train(args):
    
    # Parse arguments
    epochs = args.epochs
    pred_length = args.pred_length
    num_layers = args.num_layers
    num_cells = args.num_cells
    dropout_rate = args.dropout_rate
    batch_size = args.batch_size
    lr = args.lr
    
    model_dir = args.model_dir
    data_dir = args.data_dir
    num_gpus = args.num_gpus
    output_dir = args.output_dir
    
    device = "gpu" if num_gpus > 0 else "cpu"
    FREQ = 'D'    
    
    target_col = 'Weekly_Sales_sum'
    related_cols = ['Temperature', 'Fuel_Price', 'CPI', 'Unemployment']
       
    # Get training data
    target_train_df = pd.read_csv(os.path.join(data_dir, 'target_train.csv'), index_col=0, header=[0,1])
    related_train_df = pd.read_csv(os.path.join(data_dir, 'related_train.csv'), index_col=0, header=[0,1])
    store_df = pd.read_csv(os.path.join(data_dir, 'item.csv'), index_col=0)
    
    num_steps, num_series = target_train_df.shape
    target = target_train_df.values

    start_train_dt = target_train_df.index[0]
    custom_ds_metadata = {'num_series': num_series, 
                          'num_steps': num_steps,
                          'prediction_length': pred_length,
                          'freq': FREQ,
                          'start': [start_train_dt for _ in range(num_series)] 
                         }

    # Prepare GlounTS Dataset
    related_list = [related_train_df[c].values for c in related_cols]

    train_lst = []
    for i in range(0, num_series):
        target_vec = target[:-pred_length, i]
        related_vecs = [related[:-pred_length, i] for related in related_list]
        item = store_df.loc[i+1]
        dic = {FieldName.TARGET: target_vec, 
               FieldName.START: start_train_dt,
               FieldName.FEAT_DYNAMIC_REAL: related_vecs,
               FieldName.FEAT_STATIC_CAT: [item[0]],
               FieldName.FEAT_STATIC_REAL: [item[1]]
              } 
        train_lst.append(dic)

    test_lst = []
    for i in range(0, num_series):
        target_vec = target[:, i]
        related_vecs = [related[:, i] for related in related_list]
        item = store_df.loc[i+1]    
        dic = {FieldName.TARGET: target_vec, 
               FieldName.START: start_train_dt,
               FieldName.FEAT_DYNAMIC_REAL: related_vecs,
               FieldName.FEAT_STATIC_CAT: [item[0]],
               FieldName.FEAT_STATIC_REAL: [item[1]]
              } 
        test_lst.append(dic)

    train_ds = ListDataset(train_lst, freq=FREQ)
    test_ds = ListDataset(test_lst, freq=FREQ)   

    # Define Estimator    
    trainer = Trainer(
        ctx=device,
        epochs=epochs,
        learning_rate=lr,
        batch_size=batch_size
    )
    
    deepar_estimator = DeepAREstimator(freq=FREQ, 
                                       prediction_length=pred_length,
                                       use_feat_dynamic_real=True,
                                       use_feat_static_cat=True,
                                       use_feat_static_real=True,
                                       cardinality=[3],
                                       num_cells=30,
                                       distr_output=StudentTOutput(),
                                       trainer=trainer)
    # Train the model
    deepar_predictor = deepar_estimator.train(train_ds)
    
    # Evaluate trained model on test data
    forecast_it, ts_it = make_evaluation_predictions(test_ds, deepar_predictor, num_samples=100)
    forecasts = list(forecast_it)
    tss = list(ts_it)
    evaluator = Evaluator(quantiles=[0.1, 0.5, 0.9])
    agg_metrics, item_metrics = evaluator(iter(tss), iter(forecasts), num_series=len(test_ds))

    metrics = ['RMSE', 'MAPE', 'wQuantileLoss[0.1]', 'wQuantileLoss[0.5]', 'wQuantileLoss[0.9]', 'mean_wQuantileLoss']
    metrics_dic = dict((key,value) for key, value in agg_metrics.items() if key in metrics)
    print(json.dumps(metrics_dic, indent=2))

    # Save the model
    deepar_predictor.serialize(pathlib.Path(model_dir))
    return deepar_predictor
Beispiel #18
0
def forecast_dataset(dataset,
                     epochs=100,
                     learning_rate=1e-3,
                     num_samples=100,
                     model="SimpleFeedForward",
                     r_method="ets",
                     alpha=0,
                     distrib="Gaussian"):
    if distrib == "Gaussian":
        distr_output = GaussianOutput()
    elif distrib == "Laplace":
        distr_output = LaplaceOutput()
    elif distrib == "PiecewiseLinear":
        distr_output = PiecewiseLinearOutput(num_pieces=2)
    elif distrib == "Uniform":
        distr_output = UniformOutput()
    elif distrib == "Student":
        distr_output = StudentTOutput()
    else:
        distr_output = None

    if model != "GaussianProcess":
        ctx = mx.Context("gpu")
    else:
        ctx = mx.Context("cpu")

    # Trainer
    trainer = Trainer(epochs=epochs,
                      learning_rate=learning_rate,
                      num_batches_per_epoch=100,
                      ctx=ctx,
                      hybridize=True if model[0] != "c" else False)

    # Estimator (if machine learning model)
    if model == "SimpleFeedForward":  # 10s / epochs for context 60*24
        estimator = SimpleFeedForwardEstimator(
            num_hidden_dimensions=[10],
            prediction_length=dataset.prediction_length,
            context_length=dataset.context_length,
            freq=dataset.freq,
            trainer=trainer,
            distr_output=distr_output)
    elif model == "cSimpleFeedForward":  # 10s / epochs for context 60*24
        estimator = CustomSimpleFeedForwardEstimator(
            prediction_length=dataset.prediction_length,
            context_length=dataset.context_length,
            freq=dataset.freq,
            trainer=trainer,
            num_cells=40,
            alpha=alpha,
            distr_output=distr_output,
            distr_output_type=distrib)
    elif model == "CanonicalRNN":  # 80s /epochs for context 60*24, idem for 60*1
        estimator = canonical.CanonicalRNNEstimator(
            freq=dataset.freq,
            context_length=dataset.context_length,
            prediction_length=dataset.prediction_length,
            trainer=trainer,
            distr_output=distr_output,
        )
    elif model == "DeepAr":
        estimator = deepar.DeepAREstimator(
            freq=dataset.freq,
            context_length=dataset.context_length,
            prediction_length=dataset.prediction_length,
            trainer=trainer,
            distr_output=distr_output,
        )
    elif model == "DeepFactor":  # 120 s/epochs if one big time serie, 1.5s if 183 time series
        estimator = deep_factor.DeepFactorEstimator(
            freq=dataset.freq,
            context_length=dataset.context_length,
            prediction_length=dataset.prediction_length,
            trainer=trainer,
            distr_output=distr_output,
        )
    elif model == "DeepState":  # Very slow on cpu
        estimator = deepstate.DeepStateEstimator(
            freq=dataset.freq,
            prediction_length=dataset.prediction_length,
            trainer=trainer,
            cardinality=list([1]),
            use_feat_static_cat=False)
    elif model == "GaussianProcess":  # CPU / GPU problem
        estimator = gp_forecaster.GaussianProcessEstimator(
            freq=dataset.freq,
            prediction_length=dataset.prediction_length,
            trainer=trainer,
            cardinality=1)
    elif model == "NPTS":
        estimator = npts.NPTSEstimator(
            freq=dataset.freq, prediction_length=dataset.prediction_length)
    elif model == "MQCNN":
        estimator = seq2seq.MQCNNEstimator(
            prediction_length=dataset.prediction_length,
            freq=dataset.freq,
            context_length=dataset.context_length,
            trainer=trainer,
            quantiles=list([0.005, 0.05, 0.25, 0.5, 0.75, 0.95, 0.995]))
    elif model == "MQRNN":
        estimator = seq2seq.MQRNNEstimator(
            prediction_length=dataset.prediction_length,
            freq=dataset.freq,
            context_length=dataset.context_length,
            trainer=trainer,
            quantiles=list([0.005, 0.05, 0.25, 0.5, 0.75, 0.95, 0.995]))
    elif model == "RNN2QR":  # Must be investigated
        estimator = seq2seq.RNN2QRForecaster(
            prediction_length=dataset.prediction_length,
            freq=dataset.freq,
            context_length=dataset.context_length,
            trainer=trainer,
            cardinality=dataset.cardinality,
            embedding_dimension=1,
            encoder_rnn_layer=1,
            encoder_rnn_num_hidden=1,
            decoder_mlp_layer=[1],
            decoder_mlp_static_dim=1)
    elif model == "SeqToSeq":  # Must be investigated
        estimator = seq2seq.Seq2SeqEstimator(
            prediction_length=dataset.prediction_length,
            freq=dataset.freq,
            context_length=dataset.context_length,
            trainer=trainer,
            cardinality=[1],
            embedding_dimension=1,
            decoder_mlp_layer=[1],
            decoder_mlp_static_dim=1,
            encoder=Seq2SeqEncoder())
    elif model == "Transformer":  # Make the computer lag the first time
        estimator = transformer.TransformerEstimator(
            prediction_length=dataset.prediction_length,
            freq=dataset.freq,
            context_length=dataset.context_length,
            trainer=trainer)

    else:
        estimator = None

    # Predictor (directly if non machine learning model and from estimator if machine learning)
    if model == "Prophet":
        predictor = prophet.ProphetPredictor(
            freq=dataset.freq,
            prediction_length=dataset.prediction_length,
        )
    elif model == "R":
        predictor = r_forecast.RForecastPredictor(
            freq=dataset.freq,
            prediction_length=dataset.prediction_length,
            method_name=r_method)
    elif model == "SeasonalNaive":
        predictor = seasonal_naive.SeasonalNaivePredictor(
            freq=dataset.freq,
            prediction_length=dataset.prediction_length,
            season_length=24)
    else:
        predictor = estimator.train(dataset.train_ds)
        if model[0] != "c":
            predictor.serialize(Path("temp"))
            predictor = Predictor.deserialize(
                Path("temp"), ctx=mx.cpu(0))  # fix for deepstate

    # Evaluate
    forecast_it, ts_it = make_evaluation_predictions(
        dataset=dataset.test_ds,  # test dataset
        predictor=predictor,  # predictor
        num_samples=num_samples,  # num of sample paths we want for evaluation
    )

    return list(forecast_it), list(ts_it)