def test_gaussian_likelihood(mu: float, sigma: float, hybridize: bool): ''' Test to check that maximizing the likelihood recovers the parameters ''' # generate samples mus = mx.nd.zeros((NUM_SAMPLES, )) + mu sigmas = mx.nd.zeros((NUM_SAMPLES, )) + sigma distr = Gaussian(mus, sigmas) samples = distr.sample() init_biases = [ mu - START_TOL_MULTIPLE * TOL * mu, inv_softplus(sigma - START_TOL_MULTIPLE * TOL * sigma), ] mu_hat, sigma_hat = maximum_likelihood_estimate_sgd( GaussianOutput(), samples, init_biases=init_biases, hybridize=hybridize, learning_rate=PositiveFloat(0.001), num_epochs=PositiveInt(5), ) 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"alpha did not match: sigma = {sigma}, sigma_hat = {sigma_hat}"
def test_box_cox_tranform( lambdas: Tuple[float, float], mu_sigma: Tuple[float, float], hybridize: bool, ): ''' Test to check that maximizing the likelihood recovers the parameters ''' # test instance lam_1, lam_2 = lambdas mu, sigma = mu_sigma # generate samples lamdas_1 = mx.nd.zeros((NUM_SAMPLES, )) + lam_1 lamdas_2 = mx.nd.zeros((NUM_SAMPLES, )) + lam_2 transform = InverseBoxCoxTransform(lamdas_1, lamdas_2) mus = mx.nd.zeros((NUM_SAMPLES, )) + mu sigmas = mx.nd.zeros((NUM_SAMPLES, )) + sigma gausian_distr = Gaussian(mus, sigmas) # Here the base distribution is Guassian which is transformed to # non-Gaussian via the inverse Box-Cox transform. # Sampling from `trans_distr` gives non-Gaussian samples trans_distr = TransformedDistribution(gausian_distr, transform) # Given the non-Gaussian samples find the true parameters # of the Box-Cox transformation as well as the underlying Gaussian distribution. samples = trans_distr.sample() init_biases = [ mu - START_TOL_MULTIPLE * TOL * mu, inv_softplus(sigma - START_TOL_MULTIPLE * TOL * sigma), lam_1 - START_TOL_MULTIPLE * TOL * lam_1, inv_softplus(lam_2 - START_TOL_MULTIPLE * TOL * lam_2), ] mu_hat, sigma_hat, lam_1_hat, lam_2_hat = maximum_likelihood_estimate_sgd( TransformedDistributionOutput( GaussianOutput(), InverseBoxCoxTransformOutput(lb_obs=lam_2, fix_lambda_2=True), ), samples, init_biases=init_biases, hybridize=hybridize, learning_rate=PositiveFloat(0.01), num_epochs=PositiveInt(18), ) assert (np.abs(lam_1_hat - lam_1) < TOL * lam_1 ), f"lam_1 did not match: lam_1 = {lam_1}, lam_1_hat = {lam_1_hat}" # assert ( # np.abs(lam_2_hat - lam_2) < TOL * lam_2 # ), f"lam_2 did not match: lam_2 = {lam_2}, lam_2_hat = {lam_2_hat}" assert np.abs(mu_hat - mu) < TOL * np.abs( 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}"
def test_mixture_inference() -> None: mdo = MixtureDistributionOutput([GaussianOutput(), GaussianOutput()]) args_proj = mdo.get_args_proj() args_proj.initialize() args_proj.hybridize() input = mx.nd.ones((BATCH_SIZE, 1)) distr_args = args_proj(input) d = mdo.distribution(distr_args) # plot_samples(d.sample()) trainer = mx.gluon.Trainer( args_proj.collect_params(), "sgd", {"learning_rate": 0.02} ) mixture_samples = mx.nd.array(np_samples) N = 1000 t = tqdm(list(range(N))) for i in t: with mx.autograd.record(): distr_args = args_proj(input) d = mdo.distribution(distr_args) loss = d.loss(mixture_samples) loss.backward() loss_value = loss.mean().asnumpy() t.set_postfix({"loss": loss_value}) trainer.step(BATCH_SIZE) distr_args = args_proj(input) d = mdo.distribution(distr_args) obtained_hist = histogram(d.sample().asnumpy()) # uncomment to see histograms # pl.plot(obtained_hist) # pl.plot(EXPECTED_HIST) # pl.show() assert diff(obtained_hist, EXPECTED_HIST) < 0.5
MultivariateGaussianOutput, LowrankMultivariateGaussianOutput, NegativeBinomialOutput, PiecewiseLinearOutput, StudentTOutput, UniformOutput, DirichletOutput, 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)),
histogram(samples_mix.asnumpy()), histogram(samples_ref.asnumpy()) ) < 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)
GaussianOutput, LaplaceOutput, MixtureDistributionOutput, MultivariateGaussianOutput, NegativeBinomialOutput, PiecewiseLinearOutput, StudentTOutput, 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)),
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)