added README.md
Browse files
README.md
CHANGED
@@ -2,8 +2,122 @@
|
|
2 |
tags:
|
3 |
- pytorch_model_hub_mixin
|
4 |
- model_hub_mixin
|
|
|
|
|
|
|
|
|
5 |
---
|
6 |
|
7 |
-
|
8 |
-
|
9 |
-
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
tags:
|
3 |
- pytorch_model_hub_mixin
|
4 |
- model_hub_mixin
|
5 |
+
metrics:
|
6 |
+
- mae
|
7 |
+
library_name: pytorch
|
8 |
+
pipeline_tag: time-series-forecasting
|
9 |
---
|
10 |
|
11 |
+
# mlp-geron-time-series
|
12 |
+
|
13 |
+
A multi-layer perceptron (MLP) trained on Aurelien Geron's synthetic time series dataset - from Lesson 8 of the Udacity course "Intro to TensorFlow for Deep Learning". It is a PyTorch adaptation of the TensorFlow model trained in the lesson.
|
14 |
+
|
15 |
+
The time series contains a linear trend, a yearly seasonality and some white noise.
|
16 |
+
|
17 |
+
The MLP takes windows of 30 time steps of the series as input, and predicts the next time step of the series as output.
|
18 |
+
|
19 |
+
Code: https://github.com/sambitmukherjee/handson-ml3-pytorch/blob/main/bonus/udacity/Intro_to_TF_for_DL/Lesson_8_A.ipynb
|
20 |
+
|
21 |
+
Experiment tracking: https://wandb.ai/sadhaklal/mlp-geron-time-series
|
22 |
+
|
23 |
+
## Usage
|
24 |
+
|
25 |
+
```
|
26 |
+
import numpy as np
|
27 |
+
|
28 |
+
# Create synthetic time series:
|
29 |
+
def trend(time, slope=0):
|
30 |
+
return slope * time
|
31 |
+
|
32 |
+
def seasonal_pattern(season_time):
|
33 |
+
"""Just an arbitrary pattern; you can change it if you wish."""
|
34 |
+
return np.where(season_time < 0.4, np.cos(season_time * 2 * np.pi), 1 / np.exp(3 * season_time))
|
35 |
+
|
36 |
+
def seasonality(time, period, amplitude=1, phase=0):
|
37 |
+
"""Repeats the same pattern in each period."""
|
38 |
+
season_time = ((time + phase) % period) / period
|
39 |
+
return amplitude * seasonal_pattern(season_time)
|
40 |
+
|
41 |
+
def white_noise(time, noise_level=1, seed=None):
|
42 |
+
return np.random.RandomState(seed).randn(len(time)) * noise_level
|
43 |
+
|
44 |
+
time = np.arange(4 * 365 + 1) # 1 is added since every four years there is a leap year.
|
45 |
+
baseline = 10
|
46 |
+
slope = 0.05
|
47 |
+
amplitude = 50
|
48 |
+
series = baseline + trend(time, slope) + seasonality(time, period=365, amplitude=amplitude)
|
49 |
+
noise_level = 5
|
50 |
+
noise = white_noise(time, noise_level, seed=42)
|
51 |
+
series += noise
|
52 |
+
|
53 |
+
# Define training & validation periods:
|
54 |
+
split_time = 1000
|
55 |
+
x_train = series[:split_time]
|
56 |
+
x_valid = series[split_time:]
|
57 |
+
|
58 |
+
# Create custom `Dataset` class; it'll be used by the `model_forecast` function below:
|
59 |
+
import torch
|
60 |
+
from torch.utils.data import Dataset, DataLoader
|
61 |
+
|
62 |
+
class WindowDataset(Dataset):
|
63 |
+
def __init__(self, series, window_size):
|
64 |
+
window_size += 1
|
65 |
+
self.windows = []
|
66 |
+
for i in range(0, len(series) - window_size + 1, 1):
|
67 |
+
self.windows.append(series[i:i + window_size])
|
68 |
+
|
69 |
+
def __len__(self):
|
70 |
+
return len(self.windows)
|
71 |
+
|
72 |
+
def __getitem__(self, idx):
|
73 |
+
window = self.windows[idx]
|
74 |
+
return window[:-1], window[-1]
|
75 |
+
|
76 |
+
# Re-create model & load weights:
|
77 |
+
import torch.nn as nn
|
78 |
+
from huggingface_hub import PyTorchModelHubMixin
|
79 |
+
|
80 |
+
device = torch.device("cpu")
|
81 |
+
|
82 |
+
class DenseModel(nn.Module, PyTorchModelHubMixin):
|
83 |
+
def __init__(self, window_size):
|
84 |
+
super().__init__()
|
85 |
+
self.dense = nn.Sequential(
|
86 |
+
nn.Linear(window_size, 10),
|
87 |
+
nn.ReLU(),
|
88 |
+
nn.Linear(10, 10),
|
89 |
+
nn.ReLU(),
|
90 |
+
nn.Linear(10, 1)
|
91 |
+
)
|
92 |
+
|
93 |
+
def forward(self, x):
|
94 |
+
return self.dense(x)
|
95 |
+
|
96 |
+
window_size = 30
|
97 |
+
model = DenseModel.from_pretrained("sadhaklal/mlp-geron-time-series", window_size=window_size)
|
98 |
+
model.to(device)
|
99 |
+
|
100 |
+
# Forecast on validation period:
|
101 |
+
def model_forecast(model, series):
|
102 |
+
series = torch.tensor(series, dtype=torch.float32)
|
103 |
+
ds = WindowDataset(series, window_size)
|
104 |
+
dl = DataLoader(ds, batch_size=32, shuffle=False)
|
105 |
+
forecast = []
|
106 |
+
for x_batch, y_batch in dl:
|
107 |
+
x_batch, y_batch = x_batch.to(device), y_batch.to(device)
|
108 |
+
with torch.no_grad():
|
109 |
+
preds = model(x_batch)
|
110 |
+
forecast.append(preds.squeeze())
|
111 |
+
forecast = torch.cat(forecast)
|
112 |
+
return forecast.cpu().numpy()
|
113 |
+
|
114 |
+
dense_forecast = model_forecast(model, series[split_time - window_size:])
|
115 |
+
```
|
116 |
+
|
117 |
+
## Metric
|
118 |
+
|
119 |
+
MAE on the validation period: 5.01
|
120 |
+
|
121 |
+
---
|
122 |
+
|
123 |
+
This model has been pushed to the Hub using the [PyTorchModelHubMixin](https://huggingface.co/docs/huggingface_hub/package_reference/mixins#huggingface_hub.PyTorchModelHubMixin) integration.
|