diff --git a/README.md b/README.md index 5ded097..25b0014 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,27 @@ suppress unnecessary components, enabling high performance in a wide range of scenarios. On a variety of real-world datasets, we demonstrate significant performance improvements over existing * [PyTorch Tutorial - Temporal Fusion Transformers](https://pytorch-forecasting.readthedocs.io/en/latest/tutorials/stallion.html) +* [PyTorch Forecasting Announcement](https://towardsdatascience.com/introducing-pytorch-forecasting-64de99b9ef46#:~:text=What%20is%20PyTorch%20Forecasting%3F,easily%20trained%20with%20pandas%20dataframes.) * [PyTorch Tutorial - TimeSeriesDataSet](https://pytorch-forecasting.readthedocs.io/en/latest/api/pytorch_forecasting.data.timeseries.TimeSeriesDataSet.html#timeseriesdataset) * [Paper - Temporal Fusion Transformers -for Interpretable Multi-horizon Time Series Forecasting](https://arxiv.org/pdf/1912.09363.pdf) \ No newline at end of file +for Interpretable Multi-horizon Time Series Forecasting](https://arxiv.org/pdf/1912.09363.pdf) +* [Flight Demand Forecasting with +Transformers](https://arxiv.org/pdf/2111.04471v1.pdf) + + +* Check: + * UBER: + * [UBER BLOG](https://eng.uber.com/neural-networks/) + * [UBER PAPER](http://roseyu.com/time-series-workshop/submissions/TSW2017_paper_3.pdf) + * [UBER EXAMPLE](https://forecasters.org/wp-content/uploads/gravity_forms/7-c6dd08fee7f0065037affb5b74fec20a/2017/07/Laptev_Nikolay_ISF2017.pdf) + * [UBER EXAMPLE](https://conferences.oreilly.com/strata/strata-ca-2018/cdn.oreillystatic.com/en/assets/1/event/269/Detecting%20time%20series%20anomalies%20at%20Uber%20scale%20with%20recurrent%20neural%20networks%20Presentation.pdf) + * [UBER M4](https://eng.uber.com/m4-forecasting-competition/) + * [time-series-workshop](http://roseyu.com/time-series-workshop/) + * [Large-Scale Unusual Time Series Detection](https://robjhyndman.com/papers/icdm2015.pdf) + * [Mcompetitions code](https://github.com/Mcompetitions/M5-methods/tree/master/Code%20of%20Winning%20Methods) + * [Ocado Demand Forecasting](https://www.ocadogroup.com/technology/blog/how-we-improve-forecasting-and-availability-neural-networks-and-deep-learning) + * [Unit8](https://unit8.com/casestudies/) + * [TimeSeries_CNN_Classification_Using_Grid_Representation](https://github.com/junyoung-jamong/TimeSeries_CNN_Classification_Using_Grid_Representation) + + + \ No newline at end of file diff --git a/model/tft_regressor-1.pt b/model/tft_regressor-1.pt new file mode 100644 index 0000000..142dd5c Binary files /dev/null and b/model/tft_regressor-1.pt differ diff --git a/predict_regressors.py b/predict_regressors.py index e1c3db3..afefb72 100644 --- a/predict_regressors.py +++ b/predict_regressors.py @@ -17,12 +17,15 @@ DROPOUT = spec["model"]["dropout"] HIDDEN_CONTINUOUS_SIZE = spec["model"]["hidden_continuous_size"] -data = pd.read_csv("data/MERCHANT_NUMBER_OF_TRX.csv") +data = pd.read_csv("data/poc.csv") data = data[[ "MERCHANT_1_NUMBER_OF_TRX", "MERCHANT_2_NUMBER_OF_TRX", - "date" + # "USER_1_NUMBER_OF_TRX", + # "USER_2_NUMBER_OF_TRX", + "TIME" ]] +data = data.rename(columns={'TIME': 'date'}) data = data.set_index("date").stack().reset_index() data = data.rename( columns={ @@ -49,7 +52,8 @@ .astype("category") # cut atypical values at the end of the sample -train_data = data[:3200*2] +cutoff = data["id"].nunique() +train_data = data[:3200*cutoff] max_prediction_length = 24 max_encoder_length = 72 training_cutoff = data["time_idx"].max() - max_prediction_length @@ -92,7 +96,12 @@ model.load_state_dict(torch.load("model/tft_regressor.pt")) -for target in ["MERCHANT_1_NUMBER_OF_TRX", "MERCHANT_2_NUMBER_OF_TRX"]: +for target in [ + "MERCHANT_1_NUMBER_OF_TRX", + "MERCHANT_2_NUMBER_OF_TRX", + # "USER_1_NUMBER_OF_TRX", + # "USER_2_NUMBER_OF_TRX", +]: df = data[data["id"] == target].reset_index(drop=True) diff --git a/train_regressors.py b/train_regressors.py index 30c3434..fe0cbbd 100644 --- a/train_regressors.py +++ b/train_regressors.py @@ -61,7 +61,8 @@ .astype("category") # cut atypical values at the end of the sample -train_data = data[:3200*2] +cutoff = data["id"].nunique() +train_data = data[:3200*cutoff] max_prediction_length = 24 max_encoder_length = 72 training_cutoff = data["time_idx"].max() - max_prediction_length diff --git a/train_regressors_benchmark.py b/train_regressors_benchmark.py new file mode 100644 index 0000000..983c083 --- /dev/null +++ b/train_regressors_benchmark.py @@ -0,0 +1,69 @@ +import warnings + +import pandas as pd +import numpy as np +import matplotlib.pyplot as plt + +import statsmodels.api as sm +# from statsmodels.tsa.arima_model import ARIMA + +warnings.filterwarnings("ignore") + +data = pd.read_csv("data/poc.csv") + +target = "MERCHANT_2_NUMBER_OF_TRX" +data = data[[ + target, + "TIME" +]] +data = data.rename(columns={'TIME': 'date'}) +# data["MERCHANT_1_NUMBER_OF_TRX"] = np.log(data["MERCHANT_1_NUMBER_OF_TRX"] + 1e-8) + +# add datetime variables +data["month"] = pd.to_datetime(data.date).dt.month +data["day_of_week"] = pd.to_datetime(data.date).dt.dayofweek +data["hour"] = pd.to_datetime(data.date).dt.hour +data["date"] = pd.to_datetime(data["date"]) +data = data.set_index("date") + +# cut atypical values at the end of the sample +start = 3000 - 6*24 +train_data = data[:start] +test_data = data[start + 1:3600] +max_prediction_length = 24*15 + +AR, I, MA = 5, 1, 5 +order = (AR, I, MA) + +SAR, SI, SMA, seas = 1, 0, 1, 24 +Sorder = (SAR, SI, SMA, seas) + +endog = train_data[target] + +exog = train_data.iloc[:, 1:] + +model = sm.tsa.statespace.SARIMAX(endog=endog, + exog=exog, + order=order, + seasonal_order=Sorder, + enforce_stationarity=False, + enforce_invertibility=False, + trend='c') + +res = model.fit(disp=True) + +exog_graph = None if exog is None else test_data[:max_prediction_length] + +fig, ax = plt.subplots(figsize=(7, 3)) + +train_data[target][-200:].plot(ax=ax) +test_data[target][:100].plot(ax=ax) + +# Construct the forecasts +fcast = res.get_forecast( + steps=max_prediction_length, + exog=exog_graph.iloc[:, 1:] +).summary_frame() +fcast['mean'].plot(ax=ax, style='k--') +# ax.fill_between(fcast.index, fcast['mean_ci_lower'], fcast['mean_ci_upper'], color='k', alpha=0.1) +plt.show() diff --git a/train_regressors_colab.py b/train_regressors_colab.py index 789df5c..4022502 100644 --- a/train_regressors_colab.py +++ b/train_regressors_colab.py @@ -28,12 +28,15 @@ HIDDEN_CONTINUOUS_SIZE = spec["model"]["hidden_continuous_size"] GRADIENT_CLIP_VAL = spec["model"]["gradient_clip_val"] -data = pd.read_csv("/content/temporal-fusion-transformer/data/MERCHANT_NUMBER_OF_TRX.csv") +data = pd.read_csv("/content/temporal-fusion-transformer/data/poc.csv") data = data[[ "MERCHANT_1_NUMBER_OF_TRX", "MERCHANT_2_NUMBER_OF_TRX", - "date" + "USER_1_NUMBER_OF_TRX", + "USER_2_NUMBER_OF_TRX", + "TIME" ]] +data = data.rename(columns={'TIME': 'date'}) data = data.set_index("date").stack().reset_index() data = data.rename( columns={ @@ -60,7 +63,8 @@ .astype("category") # cut atypical values at the end of the sample -train_data = data[:3200*2] +cutoff = data["id"].nunique() +train_data = data[:3200*cutoff] max_prediction_length = 24 max_encoder_length = 72 training_cutoff = data["time_idx"].max() - max_prediction_length