| 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() |
|
|