import os import gradio as gr import pandas as pd from gluonts.dataset.pandas import PandasDataset from gluonts.dataset.split import split from gluonts.torch.model.deepar import DeepAREstimator from gluonts.torch.distributions import ( NegativeBinomialOutput, StudentTOutput, NormalOutput, ) from gluonts.evaluation import Evaluator, make_evaluation_predictions from make_plot import plot_forecast, plot_train_test def offset_calculation(prediction_length, rolling_windows, length): row_offset = -1 * prediction_length * rolling_windows if abs(row_offset) > 0.95 * length: raise gr.Error("Reduce prediction_length * rolling_windows") return row_offset def preprocess( input_data, prediction_length, rolling_windows, progress=gr.Progress(track_tqdm=True), ): df = pd.read_csv(input_data.name, index_col=0, parse_dates=True) df.sort_index(inplace=True) row_offset = offset_calculation(prediction_length, rolling_windows, len(df)) return plot_train_test(df.iloc[:row_offset], df.iloc[row_offset:]) def train_and_forecast( input_data, file_data, prediction_length, rolling_windows, epochs, distribution, progress=gr.Progress(track_tqdm=True), ): if not input_data and not file_data: raise gr.Error("Upload a file with the Upload button") try: if input_data: df = pd.read_csv(input_data.name, index_col=0, parse_dates=True) else: df = pd.read_csv(file_data.name, index_col=0, parse_dates=True) df.sort_index(inplace=True) except AttributeError: raise gr.Error("Upload a file with the Upload button") row_offset = offset_calculation(prediction_length, rolling_windows, len(df)) try: gluon_df = PandasDataset(df, target=df.columns[0]) except TypeError: freq = pd.infer_freq(df.index[:3]) date_range = pd.date_range(df.index[0], df.index[-1], freq=freq) new_df = df.reindex(date_range) gluon_df = PandasDataset(new_df, target=new_df.columns[0], freq=freq) training_data, test_gen = split(gluon_df, offset=row_offset) if distribution == "StudentT": distr_output = StudentTOutput() elif distribution == "Normal": distr_output = NormalOutput() else: distr_output = NegativeBinomialOutput() estimator = DeepAREstimator( distr_output=distr_output, prediction_length=prediction_length, freq=gluon_df.freq, trainer_kwargs=dict(max_epochs=epochs), ) predictor = estimator.train( training_data=training_data, ) test_data = test_gen.generate_instances( prediction_length=prediction_length, windows=rolling_windows ) evaluator = Evaluator(num_workers=0) forecast_it, ts_it = make_evaluation_predictions( dataset=test_data.input, predictor=predictor ) agg_metrics, _ = evaluator(ts_it, forecast_it) forecasts = list(predictor.predict(test_data.input)) return plot_forecast(df, forecasts), agg_metrics with gr.Blocks() as demo: gr.Markdown( """ # Probabilistic Time Series Forecasting ## How to use Upload a *univariate* csv where the first column contains date-times and the second column is your data for example: | ds | y | |------------|---------------| | 2007-12-10 | 9.590761 | | 2007-12-11 | 8.519590 | | 2007-12-12 | 8.183677 | | 2007-12-13 | 8.072467 | | 2007-12-14 | 7.893572 | ## Steps 1. Click **Upload** to upload your data and visualize it **or** select one of the example CSV files. 2. Click **Run** - This app will then train an estimator and show its predictions as well as evaluation metrics. """ ) with gr.Accordion(label="Hyperparameters"): with gr.Row(): prediction_length = gr.Number( value=12, label="Prediction Length", precision=0 ) windows = gr.Number(value=3, label="Number of Windows", precision=0) epochs = gr.Number(value=10, label="Number of Epochs", precision=0) distribution = gr.Radio( choices=["StudentT", "Negative Binomial", "Normal"], value="StudentT", label="Distribution", ) with gr.Row(label="Dataset"): upload_btn = gr.UploadButton(label="Upload") train_btn = gr.Button(label="Train and Forecast") plot = gr.Plot() json = gr.JSON(label="Evaluation Metrics") file_output = gr.File() upload_btn.upload( fn=preprocess, inputs=[upload_btn, prediction_length, windows], outputs=[plot], ) train_btn.click( fn=train_and_forecast, inputs=[ upload_btn, file_output, prediction_length, windows, epochs, distribution, ], outputs=[plot, json], ) with gr.Row(label="Example Data"): examples = gr.Examples( examples=[ [ os.path.join( os.path.dirname(__file__), "examples", "example_air_passengers.csv", ), 12, 3, ], [ os.path.join( os.path.dirname(__file__), "examples", "example_retail_sales.csv", ), 12, 3, ], [ os.path.join( os.path.dirname(__file__), "examples", "example_pedestrians_covid.csv", ), 12, 3, ], ], fn=preprocess, inputs=[file_output, prediction_length, windows], outputs=[plot], run_on_click=True, ) if __name__ == "__main__": demo.queue().launch()