Rewrote dataset to be able to include new features
This commit is contained in:
@@ -1,10 +1,11 @@
|
|||||||
# Result Report November
|
# Result Report November (1)
|
||||||
## 1. TODOs
|
## 1. TODOs
|
||||||
|
|
||||||
- [x] Compare autoregressive vs non-autoregressive
|
- [x] Compare autoregressive vs non-autoregressive
|
||||||
- [ ] Add more input parameters (load forecast)
|
- [ ] Add more input parameters (load forecast)
|
||||||
- [x] Quantile Regression sampling fix
|
- [x] Quantile Regression sampling fix
|
||||||
- [x] Quantile Regression exploration
|
- [x] Quantile Regression exploration
|
||||||
|
- [ ] Plots with good scaling (y-axis)
|
||||||
|
|
||||||
## 2. Autoregressive vs Non-Autoregressive
|
## 2. Autoregressive vs Non-Autoregressive
|
||||||
|
|
||||||
@@ -85,3 +86,9 @@ Hidden Units: 1024
|
|||||||
| --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- |
|
||||||
| 0.1, 0.2, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.8, 0.9 | 65.6542529596313 | 7392.5142575554955 | 77.55779692831604 | 10769.161724849037 |
|
| 0.1, 0.2, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.8, 0.9 | 65.6542529596313 | 7392.5142575554955 | 77.55779692831604 | 10769.161724849037 |
|
||||||
| 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9 | 65.68495924348356 | 7326.2239225611975 | 77.62433888969542 | 10789.003223366473 |
|
| 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9 | 65.68495924348356 | 7326.2239225611975 | 77.62433888969542 | 10789.003223366473 |
|
||||||
|
|
||||||
|
Also tried one with dropout of 0.3, results are better. This needs to be tested more (hyperparameter tuning is not the focus here):
|
||||||
|
|
||||||
|
| Quantiles | Train-MAE | Train-MSE | Test-MAE | Test-MSE |
|
||||||
|
| --- | --- | --- | --- | --- |
|
||||||
|
| 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9 | 63.710736942371994 | 6988.6436956508105 | 77.29499496466444 | 10706.484005597813 |
|
||||||
310945
data/load_forecast.csv
Normal file
310945
data/load_forecast.csv
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,2 +1,2 @@
|
|||||||
from .dataset import NrvDataset
|
from .dataset import NrvDataset
|
||||||
from .preprocessing import DataProcessor
|
from .preprocessing import DataProcessor, DataConfig
|
||||||
@@ -3,13 +3,61 @@ from torch.utils.data import Dataset, DataLoader
|
|||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
|
||||||
class NrvDataset(Dataset):
|
class NrvDataset(Dataset):
|
||||||
def __init__(self, dataframe, sequence_length=96, predict_sequence_length=96):
|
def __init__(self, dataframe, data_config, sequence_length=96, predict_sequence_length=96):
|
||||||
self.data = torch.tensor(dataframe['nrv'].to_numpy(), dtype=torch.float32)
|
self.data_config = data_config
|
||||||
|
|
||||||
|
self.nrv = torch.tensor(dataframe['nrv'].to_numpy(), dtype=torch.float32)
|
||||||
|
self.load_forecast = torch.tensor(dataframe['load_forecast'].to_numpy(), dtype=torch.float32)
|
||||||
|
|
||||||
self.sequence_length = sequence_length
|
self.sequence_length = sequence_length
|
||||||
self.predict_sequence_length = predict_sequence_length
|
self.predict_sequence_length = predict_sequence_length
|
||||||
|
|
||||||
def __len__(self):
|
def __len__(self):
|
||||||
return len(self.data) - self.sequence_length - self.predict_sequence_length
|
return len(self.nrv) - self.sequence_length - self.predict_sequence_length
|
||||||
|
|
||||||
def __getitem__(self, idx):
|
def __getitem__(self, idx):
|
||||||
return self.data[idx:idx+self.sequence_length], self.data[idx+self.sequence_length:idx+self.sequence_length+self.predict_sequence_length]
|
features = []
|
||||||
|
|
||||||
|
if self.data_config.NRV_HISTORY:
|
||||||
|
nrv = self.nrv[idx:idx+self.sequence_length]
|
||||||
|
features.append(nrv.view(-1))
|
||||||
|
|
||||||
|
if self.data_config.LOAD_HISTORY:
|
||||||
|
load_history = self.load_forecast[idx:idx+self.sequence_length]
|
||||||
|
features.append(load_history.view(-1))
|
||||||
|
|
||||||
|
if self.data_config.LOAD_FORECAST:
|
||||||
|
load_forecast = self.load_forecast[idx+self.sequence_length:idx+self.sequence_length+self.predict_sequence_length]
|
||||||
|
features.append(load_forecast.view(-1))
|
||||||
|
|
||||||
|
if not features:
|
||||||
|
raise ValueError("No features are configured to be included in the dataset.")
|
||||||
|
|
||||||
|
# Concatenate along dimension 0 to create a one-dimensional feature vector
|
||||||
|
all_features = torch.cat(features, dim=0)
|
||||||
|
|
||||||
|
# Target sequence, flattened if necessary
|
||||||
|
nrv_target = self.nrv[idx+self.sequence_length:idx+self.sequence_length+self.predict_sequence_length].view(-1)
|
||||||
|
|
||||||
|
return all_features, nrv_target
|
||||||
|
|
||||||
|
def random_day_autoregressive(self, idx: int):
|
||||||
|
features = []
|
||||||
|
|
||||||
|
# we already have the NRV history with the newly predicted values, so we don't need to include the last 96 values
|
||||||
|
|
||||||
|
if self.data_config.LOAD_HISTORY:
|
||||||
|
load_history = self.load_forecast[idx:idx+self.sequence_length]
|
||||||
|
features.append(load_history.view(-1))
|
||||||
|
|
||||||
|
if self.data_config.LOAD_FORECAST:
|
||||||
|
load_forecast = self.load_forecast[idx+self.sequence_length:idx+self.sequence_length+self.predict_sequence_length]
|
||||||
|
features.append(load_forecast.view(-1))
|
||||||
|
|
||||||
|
target = self.nrv[idx+self.sequence_length:idx+self.sequence_length+self.predict_sequence_length]
|
||||||
|
|
||||||
|
if len(features) == 0:
|
||||||
|
return None, target
|
||||||
|
|
||||||
|
all_features = torch.cat(features, dim=0)
|
||||||
|
return all_features, target
|
||||||
@@ -8,9 +8,15 @@ import pytz
|
|||||||
|
|
||||||
|
|
||||||
history_data_path = "../../data/history-quarter-hour-data.csv"
|
history_data_path = "../../data/history-quarter-hour-data.csv"
|
||||||
|
forecast_data_path = "../../data/load_forecast.csv"
|
||||||
|
|
||||||
|
class DataConfig:
|
||||||
|
NRV_HISTORY: bool = True
|
||||||
|
LOAD_FORECAST: bool = True
|
||||||
|
LOAD_HISTORY: bool = False
|
||||||
|
|
||||||
class DataProcessor:
|
class DataProcessor:
|
||||||
def __init__(self):
|
def __init__(self, data_config: DataConfig):
|
||||||
self.batch_size = 2048
|
self.batch_size = 2048
|
||||||
|
|
||||||
self.train_range = (-np.inf, datetime(year=2022, month=11, day=30, tzinfo=pytz.UTC))
|
self.train_range = (-np.inf, datetime(year=2022, month=11, day=30, tzinfo=pytz.UTC))
|
||||||
@@ -18,10 +24,15 @@ class DataProcessor:
|
|||||||
|
|
||||||
self.update_range_str()
|
self.update_range_str()
|
||||||
|
|
||||||
self.features = ['nrv']
|
self.history_features = self.get_nrv_history()
|
||||||
|
self.future_features = self.get_load_forecast()
|
||||||
|
|
||||||
|
self.all_features = self.history_features.merge(self.future_features, on='datetime', how='left')
|
||||||
|
|
||||||
|
self.data_config = data_config
|
||||||
|
|
||||||
self.nrv_df = self.get_nrv_history()
|
|
||||||
self.nrv_scaler = MinMaxScaler(feature_range=(-1, 1))
|
self.nrv_scaler = MinMaxScaler(feature_range=(-1, 1))
|
||||||
|
self.load_forecast_scaler = MinMaxScaler(feature_range=(-1, 1))
|
||||||
|
|
||||||
|
|
||||||
def set_train_range(self, train_range: tuple):
|
def set_train_range(self, train_range: tuple):
|
||||||
@@ -49,6 +60,22 @@ class DataProcessor:
|
|||||||
df.sort_values(by="datetime", inplace=True)
|
df.sort_values(by="datetime", inplace=True)
|
||||||
return df
|
return df
|
||||||
|
|
||||||
|
def get_load_forecast(self):
|
||||||
|
df = pd.read_csv(forecast_data_path, delimiter=';')
|
||||||
|
df = df.rename(columns={'Day-ahead 6PM forecast': 'load_forecast', 'Datetime': 'datetime'})
|
||||||
|
df = df[['datetime', 'load_forecast']]
|
||||||
|
|
||||||
|
df['datetime'] = pd.to_datetime(df['datetime'], utc=True)
|
||||||
|
|
||||||
|
# check if there are nan values
|
||||||
|
# if df.isnull().values.any():
|
||||||
|
# # print the rows with nan values
|
||||||
|
# print(df[df.isnull().any(axis=1)])
|
||||||
|
# raise ValueError("There are nan values in the load forecast data.")
|
||||||
|
|
||||||
|
df.sort_values(by="datetime", inplace=True)
|
||||||
|
return df
|
||||||
|
|
||||||
def set_batch_size(self, batch_size: int):
|
def set_batch_size(self, batch_size: int):
|
||||||
self.batch_size = batch_size
|
self.batch_size = batch_size
|
||||||
|
|
||||||
@@ -56,7 +83,7 @@ class DataProcessor:
|
|||||||
return torch.utils.data.DataLoader(dataset, batch_size=self.batch_size, shuffle=shuffle, num_workers=4)
|
return torch.utils.data.DataLoader(dataset, batch_size=self.batch_size, shuffle=shuffle, num_workers=4)
|
||||||
|
|
||||||
def get_train_dataloader(self, transform: bool = True, predict_sequence_length: int = 96):
|
def get_train_dataloader(self, transform: bool = True, predict_sequence_length: int = 96):
|
||||||
train_df = self.nrv_df.copy()
|
train_df = self.all_features.copy()
|
||||||
|
|
||||||
if self.train_range[0] != -np.inf:
|
if self.train_range[0] != -np.inf:
|
||||||
train_df = train_df[(train_df['datetime'] >= self.train_range[0])]
|
train_df = train_df[(train_df['datetime'] >= self.train_range[0])]
|
||||||
@@ -66,13 +93,14 @@ class DataProcessor:
|
|||||||
|
|
||||||
if transform:
|
if transform:
|
||||||
train_df['nrv'] = self.nrv_scaler.fit_transform(train_df['nrv'].values.reshape(-1, 1)).reshape(-1)
|
train_df['nrv'] = self.nrv_scaler.fit_transform(train_df['nrv'].values.reshape(-1, 1)).reshape(-1)
|
||||||
|
train_df['load_forecast'] = self.load_forecast_scaler.fit_transform(train_df['load_forecast'].values.reshape(-1, 1)).reshape(-1)
|
||||||
|
|
||||||
train_dataset = NrvDataset(train_df, predict_sequence_length=predict_sequence_length)
|
train_dataset = NrvDataset(train_df, data_config=self.data_config, predict_sequence_length=predict_sequence_length)
|
||||||
return self.get_dataloader(train_dataset)
|
return self.get_dataloader(train_dataset)
|
||||||
|
|
||||||
def get_test_dataloader(self, transform: bool = True, predict_sequence_length: int = 96):
|
def get_test_dataloader(self, transform: bool = True, predict_sequence_length: int = 96):
|
||||||
|
|
||||||
test_df = self.nrv_df.copy()
|
test_df = self.all_features.copy()
|
||||||
|
|
||||||
if self.test_range[0] != -np.inf:
|
if self.test_range[0] != -np.inf:
|
||||||
test_df = test_df[(test_df['datetime'] >= self.test_range[0])]
|
test_df = test_df[(test_df['datetime'] >= self.test_range[0])]
|
||||||
@@ -82,35 +110,14 @@ class DataProcessor:
|
|||||||
|
|
||||||
if transform:
|
if transform:
|
||||||
test_df['nrv'] = self.nrv_scaler.transform(test_df['nrv'].values.reshape(-1, 1)).reshape(-1)
|
test_df['nrv'] = self.nrv_scaler.transform(test_df['nrv'].values.reshape(-1, 1)).reshape(-1)
|
||||||
test_dataset = NrvDataset(test_df, predict_sequence_length=predict_sequence_length)
|
test_df['load_forecast'] = self.load_forecast_scaler.transform(test_df['load_forecast'].values.reshape(-1, 1)).reshape(-1)
|
||||||
|
|
||||||
|
test_dataset = NrvDataset(test_df, data_config=self.data_config, predict_sequence_length=predict_sequence_length)
|
||||||
return self.get_dataloader(test_dataset, shuffle=False)
|
return self.get_dataloader(test_dataset, shuffle=False)
|
||||||
|
|
||||||
|
|
||||||
def get_dataloaders(self, transform: bool = True, predict_sequence_length: int = 96):
|
def get_dataloaders(self, transform: bool = True, predict_sequence_length: int = 96):
|
||||||
return self.get_train_dataloader(transform=transform, predict_sequence_length=predict_sequence_length), self.get_test_dataloader(transform=transform, predict_sequence_length=predict_sequence_length)
|
return self.get_train_dataloader(transform=transform, predict_sequence_length=predict_sequence_length), self.get_test_dataloader(transform=transform, predict_sequence_length=predict_sequence_length)
|
||||||
|
|
||||||
def get_random_day(self, train: bool = True, transform: bool = True):
|
|
||||||
df = self.nrv_df.copy()
|
|
||||||
|
|
||||||
range = self.train_range if train else self.test_range
|
|
||||||
|
|
||||||
if range[0] != -np.inf:
|
|
||||||
df = df[(df['datetime'] >= range[0])]
|
|
||||||
|
|
||||||
if range[1] != np.inf:
|
|
||||||
df = df[(df['datetime'] <= range[1])]
|
|
||||||
|
|
||||||
if transform:
|
|
||||||
df['nrv'] = self.nrv_scaler.transform(df['nrv'].values.reshape(-1, 1)).reshape(-1)
|
|
||||||
|
|
||||||
data_tensor = torch.tensor(df[self.features].values, dtype=torch.float32)
|
|
||||||
|
|
||||||
random_start_idx = np.random.randint(0, len(df) - 191)
|
|
||||||
|
|
||||||
current_day_features = data_tensor[random_start_idx:random_start_idx+96]
|
|
||||||
next_day_features = data_tensor[random_start_idx+96:random_start_idx+192]
|
|
||||||
|
|
||||||
return (current_day_features, next_day_features)
|
|
||||||
|
|
||||||
def inverse_transform(self, tensor: torch.Tensor):
|
def inverse_transform(self, tensor: torch.Tensor):
|
||||||
return self.nrv_scaler.inverse_transform(tensor.cpu().numpy()).reshape(-1)
|
return self.nrv_scaler.inverse_transform(tensor.cpu().numpy()).reshape(-1)
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import torch
|
import torch
|
||||||
|
|
||||||
class NonLinearRegression(torch.nn.Module):
|
class NonLinearRegression(torch.nn.Module):
|
||||||
def __init__(self, inputSize, output_size, hiddenSize=128, numLayers=2):
|
def __init__(self, inputSize, output_size, hiddenSize=128, numLayers=2, dropout=0.0):
|
||||||
super(NonLinearRegression, self).__init__()
|
super(NonLinearRegression, self).__init__()
|
||||||
self.inputSize = inputSize
|
self.inputSize = inputSize
|
||||||
self.output_size = output_size
|
self.output_size = output_size
|
||||||
@@ -9,11 +9,15 @@ class NonLinearRegression(torch.nn.Module):
|
|||||||
self.hiddenSize = hiddenSize
|
self.hiddenSize = hiddenSize
|
||||||
self.numLayers = numLayers
|
self.numLayers = numLayers
|
||||||
|
|
||||||
|
self.dropout = dropout
|
||||||
|
|
||||||
# add linear layers with relu
|
# add linear layers with relu
|
||||||
self.layers = torch.nn.ModuleList()
|
self.layers = torch.nn.ModuleList()
|
||||||
self.layers.append(torch.nn.Linear(inputSize, hiddenSize))
|
self.layers.append(torch.nn.Linear(inputSize, hiddenSize))
|
||||||
|
self.layers.append(torch.nn.Dropout(dropout))
|
||||||
for _ in range(numLayers - 2):
|
for _ in range(numLayers - 2):
|
||||||
self.layers.append(torch.nn.Linear(hiddenSize, hiddenSize))
|
self.layers.append(torch.nn.Linear(hiddenSize, hiddenSize))
|
||||||
|
self.layers.append(torch.nn.Dropout(dropout))
|
||||||
self.layers.append(torch.nn.Linear(hiddenSize, output_size))
|
self.layers.append(torch.nn.Linear(hiddenSize, output_size))
|
||||||
|
|
||||||
self.relu = torch.nn.ReLU()
|
self.relu = torch.nn.ReLU()
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
"source": [
|
"source": [
|
||||||
"import sys\n",
|
"import sys\n",
|
||||||
"sys.path.append('..')\n",
|
"sys.path.append('..')\n",
|
||||||
"from data import DataProcessor\n",
|
"from data import DataProcessor, DataConfig\n",
|
||||||
"from trainers.quantile_trainer import QuantileTrainer\n",
|
"from trainers.quantile_trainer import QuantileTrainer\n",
|
||||||
"from trainers.autoregressive_trainer import AutoRegressiveTrainer\n",
|
"from trainers.autoregressive_trainer import AutoRegressiveTrainer\n",
|
||||||
"from trainers.trainer import Trainer\n",
|
"from trainers.trainer import Trainer\n",
|
||||||
@@ -50,35 +50,40 @@
|
|||||||
"name": "stdout",
|
"name": "stdout",
|
||||||
"output_type": "stream",
|
"output_type": "stream",
|
||||||
"text": [
|
"text": [
|
||||||
"ClearML Task: created new task id=909da25a8d214f75ab3858506ae615e8\n",
|
"ClearML Task: created new task id=ae9d93e6bf3f4d228832378707574777\n",
|
||||||
"2023-11-07 16:29:35,665 - clearml.Task - INFO - Storing jupyter notebook directly as code\n",
|
"ClearML results page: http://192.168.1.182:8080/projects/2e46d4af6f1e4c399cf9f5aa30bc8795/experiments/ae9d93e6bf3f4d228832378707574777/output/log\n",
|
||||||
"ClearML results page: http://192.168.1.182:8080/projects/2e46d4af6f1e4c399cf9f5aa30bc8795/experiments/909da25a8d214f75ab3858506ae615e8/output/log\n",
|
"2023-11-08 21:46:32,338 - clearml.Task - INFO - Storing jupyter notebook directly as code\n",
|
||||||
"2023-11-07 16:30:08,121 - clearml.model - WARNING - 500 model found when searching for `file:///workspaces/Thesis/src/notebooks/checkpoint.pt`\n",
|
"2023-11-08 21:46:32,342 - clearml.Repository Detection - WARNING - Can't get url information for git repo in /workspaces/Thesis/src/notebooks\n",
|
||||||
"2023-11-07 16:30:08,123 - clearml.model - WARNING - Selected model `Quantile Regression - Linear` (id=bc0cb0d7fc614e2e8b0edf5b85348646)\n",
|
"2023-11-08 21:46:35,244 - clearml.model - WARNING - 500 model found when searching for `file:///workspaces/Thesis/src/notebooks/checkpoint.pt`\n",
|
||||||
"2023-11-07 16:30:08,130 - clearml.frameworks - INFO - Found existing registered model id=bc0cb0d7fc614e2e8b0edf5b85348646 [/workspaces/Thesis/src/notebooks/checkpoint.pt] reusing it.\n",
|
"2023-11-08 21:46:35,245 - clearml.model - WARNING - Selected model `Untitled Task` (id=bc0cb0d7fc614e2e8b0edf5b85348646)\n",
|
||||||
"2023-11-07 16:30:08,677 - clearml.Task - INFO - Completed model upload to http://192.168.1.182:8081/Thesis/NrvForecast/Non-AutoRegressive%20-%20Non%20Linear%20%283%20hidden%20layers%20-%201024%20units%29.909da25a8d214f75ab3858506ae615e8/models/checkpoint.pt\n",
|
"2023-11-08 21:46:35,254 - clearml.frameworks - INFO - Found existing registered model id=bc0cb0d7fc614e2e8b0edf5b85348646 [/workspaces/Thesis/src/notebooks/checkpoint.pt] reusing it.\n",
|
||||||
"2023-11-07 16:30:10,302 - clearml.Task - INFO - Completed model upload to http://192.168.1.182:8081/Thesis/NrvForecast/Non-AutoRegressive%20-%20Non%20Linear%20%283%20hidden%20layers%20-%201024%20units%29.909da25a8d214f75ab3858506ae615e8/models/checkpoint.pt\n",
|
"2023-11-08 21:46:35,748 - clearml.Task - INFO - Completed model upload to http://192.168.1.182:8081/Thesis/NrvForecast/Untitled%20Task.ae9d93e6bf3f4d228832378707574777/models/checkpoint.pt\n",
|
||||||
|
"2023-11-08 21:46:37,673 - clearml.Task - INFO - Completed model upload to http://192.168.1.182:8081/Thesis/NrvForecast/Untitled%20Task.ae9d93e6bf3f4d228832378707574777/models/checkpoint.pt\n",
|
||||||
|
"2023-11-08 21:46:41,215 - clearml.Task - INFO - Completed model upload to http://192.168.1.182:8081/Thesis/NrvForecast/Untitled%20Task.ae9d93e6bf3f4d228832378707574777/models/checkpoint.pt\n",
|
||||||
|
"2023-11-08 21:46:43,004 - clearml.Task - INFO - Completed model upload to http://192.168.1.182:8081/Thesis/NrvForecast/Untitled%20Task.ae9d93e6bf3f4d228832378707574777/models/checkpoint.pt\n",
|
||||||
|
"2023-11-08 21:46:44,745 - clearml.Task - INFO - Completed model upload to http://192.168.1.182:8081/Thesis/NrvForecast/Untitled%20Task.ae9d93e6bf3f4d228832378707574777/models/checkpoint.pt\n",
|
||||||
"Early stopping triggered\n"
|
"Early stopping triggered\n"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"source": [
|
"source": [
|
||||||
"#### Hyperparameters ####\n",
|
"#### Hyperparameters ####\n",
|
||||||
"inputDim = 96\n",
|
"inputDim = 96 + 96\n",
|
||||||
"learningRate = 0.0003\n",
|
"learningRate = 0.0003\n",
|
||||||
"epochs = 50\n",
|
"epochs = 150\n",
|
||||||
"\n",
|
"\n",
|
||||||
"# model = LinearRegression(inputDim, 96)\n",
|
"# model = LinearRegression(inputDim, 96)\n",
|
||||||
"model = NonLinearRegression(inputDim, 96, hiddenSize=1024, numLayers=5)\n",
|
"model = NonLinearRegression(inputDim, 96, hiddenSize=1024, numLayers=5)\n",
|
||||||
"optimizer = torch.optim.Adam(model.parameters(), lr=learningRate)\n",
|
"optimizer = torch.optim.Adam(model.parameters(), lr=learningRate)\n",
|
||||||
"\n",
|
"\n",
|
||||||
"#### Data Processor ####\n",
|
"#### Data Processor ####\n",
|
||||||
"data_processor = DataProcessor()\n",
|
"data_config = DataConfig()\n",
|
||||||
|
"data_processor = DataProcessor(data_config)\n",
|
||||||
"data_processor.set_batch_size(1024)\n",
|
"data_processor.set_batch_size(1024)\n",
|
||||||
"\n",
|
"\n",
|
||||||
"\n",
|
"\n",
|
||||||
"data_processor.set_train_range((datetime(year=2015, month=1, day=1, tzinfo=pytz.UTC), datetime(year=2022, month=11, day=30, tzinfo=pytz.UTC)))\n",
|
"data_processor.set_train_range((datetime(year=2015, month=1, day=1, tzinfo=pytz.UTC), datetime(year=2022, month=11, day=30, tzinfo=pytz.UTC)))\n",
|
||||||
"data_processor.set_test_range((datetime(year=2023, month=1, day=1, tzinfo=pytz.UTC), np.inf))\n",
|
"data_processor.set_test_range((datetime(year=2023, month=1, day=1, tzinfo=pytz.UTC), datetime(year=2023, month=6, day=20, tzinfo=pytz.UTC)))\n",
|
||||||
"\n",
|
"\n",
|
||||||
"#### ClearML ####\n",
|
"#### ClearML ####\n",
|
||||||
"clearml_helper = ClearMLHelper(project_name=\"Thesis/NrvForecast\")\n",
|
"clearml_helper = ClearMLHelper(project_name=\"Thesis/NrvForecast\")\n",
|
||||||
@@ -87,7 +92,7 @@
|
|||||||
"trainer = Trainer(model, optimizer, nn.MSELoss(), data_processor, \"cuda\", debug=False, clearml_helper=clearml_helper)\n",
|
"trainer = Trainer(model, optimizer, nn.MSELoss(), data_processor, \"cuda\", debug=False, clearml_helper=clearml_helper)\n",
|
||||||
"trainer.add_metrics_to_track([MSELoss(), L1Loss()])\n",
|
"trainer.add_metrics_to_track([MSELoss(), L1Loss()])\n",
|
||||||
"trainer.plot_every(10)\n",
|
"trainer.plot_every(10)\n",
|
||||||
"trainer.early_stopping(patience=10)\n",
|
"trainer.early_stopping(patience=40)\n",
|
||||||
"trainer.train(epochs=epochs)"
|
"trainer.train(epochs=epochs)"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -100,15 +105,30 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 3,
|
"execution_count": 2,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stderr",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"InsecureRequestWarning: Certificate verification is disabled! Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "stdout",
|
"name": "stdout",
|
||||||
"output_type": "stream",
|
"output_type": "stream",
|
||||||
"text": [
|
"text": [
|
||||||
"ClearML Task: created new task id=6467cef37fdc408d95b89f0dca0e26dd\n",
|
"ClearML Task: created new task id=e4983af7aad748e8ae71e5fa46767d60\n",
|
||||||
"ClearML results page: http://192.168.1.182:8080/projects/2e46d4af6f1e4c399cf9f5aa30bc8795/experiments/6467cef37fdc408d95b89f0dca0e26dd/output/log\n",
|
"ClearML results page: http://192.168.1.182:8080/projects/2e46d4af6f1e4c399cf9f5aa30bc8795/experiments/e4983af7aad748e8ae71e5fa46767d60/output/log\n",
|
||||||
|
"2023-11-08 22:51:38,769 - clearml.Task - INFO - Storing jupyter notebook directly as code\n",
|
||||||
|
"2023-11-08 22:51:38,773 - clearml.Repository Detection - WARNING - Can't get url information for git repo in /workspaces/Thesis/src/notebooks\n",
|
||||||
|
"2023-11-08 22:51:41,704 - clearml.model - WARNING - 500 model found when searching for `file:///workspaces/Thesis/src/notebooks/checkpoint.pt`\n",
|
||||||
|
"2023-11-08 22:51:41,705 - clearml.model - WARNING - Selected model `Untitled Task` (id=bc0cb0d7fc614e2e8b0edf5b85348646)\n",
|
||||||
|
"2023-11-08 22:51:41,713 - clearml.frameworks - INFO - Found existing registered model id=bc0cb0d7fc614e2e8b0edf5b85348646 [/workspaces/Thesis/src/notebooks/checkpoint.pt] reusing it.\n",
|
||||||
|
"2023-11-08 22:51:42,239 - clearml.Task - INFO - Completed model upload to http://192.168.1.182:8081/Thesis/NrvForecast/Untitled%20Task.e4983af7aad748e8ae71e5fa46767d60/models/checkpoint.pt\n",
|
||||||
|
"2023-11-08 22:51:43,980 - clearml.Task - INFO - Completed model upload to http://192.168.1.182:8081/Thesis/NrvForecast/Untitled%20Task.e4983af7aad748e8ae71e5fa46767d60/models/checkpoint.pt\n",
|
||||||
|
"2023-11-08 22:51:45,684 - clearml.Task - INFO - Completed model upload to http://192.168.1.182:8081/Thesis/NrvForecast/Untitled%20Task.e4983af7aad748e8ae71e5fa46767d60/models/checkpoint.pt\n",
|
||||||
"Early stopping triggered\n"
|
"Early stopping triggered\n"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -124,7 +144,9 @@
|
|||||||
"optimizer = torch.optim.Adam(model.parameters(), lr=learningRate)\n",
|
"optimizer = torch.optim.Adam(model.parameters(), lr=learningRate)\n",
|
||||||
"\n",
|
"\n",
|
||||||
"#### Data Processor ####\n",
|
"#### Data Processor ####\n",
|
||||||
"data_processor = DataProcessor()\n",
|
"data_config = DataConfig()\n",
|
||||||
|
"data_config.LOAD_FORECAST = False\n",
|
||||||
|
"data_processor = DataProcessor(data_config)\n",
|
||||||
"data_processor.set_batch_size(1024)\n",
|
"data_processor.set_batch_size(1024)\n",
|
||||||
"\n",
|
"\n",
|
||||||
"\n",
|
"\n",
|
||||||
@@ -151,26 +173,18 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 4,
|
"execution_count": 2,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"name": "stderr",
|
"ename": "TypeError",
|
||||||
"output_type": "stream",
|
"evalue": "DataProcessor.__init__() missing 1 required positional argument: 'data_config'",
|
||||||
"text": [
|
"output_type": "error",
|
||||||
"/workspaces/Thesis/src/notebooks/../trainers/quantile_trainer.py:16: UserWarning:\n",
|
"traceback": [
|
||||||
"\n",
|
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
|
||||||
"To copy construct from a tensor, it is recommended to use sourceTensor.clone().detach() or sourceTensor.clone().detach().requires_grad_(True), rather than torch.tensor(sourceTensor).\n",
|
"\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)",
|
||||||
"\n"
|
"\u001b[1;32m/workspaces/Thesis/src/notebooks/training.ipynb Cell 7\u001b[0m line \u001b[0;36m1\n\u001b[1;32m <a href='vscode-notebook-cell://dev-container%2B7b22686f737450617468223a222f686f6d652f766963746f726d796c6c652f53656144726976652f4d79204c69627261726965732f4750552d7365727665722f546865736973222c226c6f63616c446f636b6572223a66616c73652c22636f6e66696746696c65223a7b22246d6964223a312c2270617468223a222f686f6d652f766963746f726d796c6c652f53656144726976652f4d79204c69627261726965732f4750552d7365727665722f5468657369732f2e646576636f6e7461696e65722f646576636f6e7461696e65722e6a736f6e222c22736368656d65223a227673636f64652d66696c65486f7374227d7d@ssh-remote%2Bvictormylle.be/workspaces/Thesis/src/notebooks/training.ipynb#X10sdnNjb2RlLXJlbW90ZQ%3D%3D?line=13'>14</a>\u001b[0m data_config \u001b[39m=\u001b[39m DataConfig()\n\u001b[1;32m <a href='vscode-notebook-cell://dev-container%2B7b22686f737450617468223a222f686f6d652f766963746f726d796c6c652f53656144726976652f4d79204c69627261726965732f4750552d7365727665722f546865736973222c226c6f63616c446f636b6572223a66616c73652c22636f6e66696746696c65223a7b22246d6964223a312c2270617468223a222f686f6d652f766963746f726d796c6c652f53656144726976652f4d79204c69627261726965732f4750552d7365727665722f5468657369732f2e646576636f6e7461696e65722f646576636f6e7461696e65722e6a736f6e222c22736368656d65223a227673636f64652d66696c65486f7374227d7d@ssh-remote%2Bvictormylle.be/workspaces/Thesis/src/notebooks/training.ipynb#X10sdnNjb2RlLXJlbW90ZQ%3D%3D?line=14'>15</a>\u001b[0m data_config\u001b[39m.\u001b[39mLOAD_FORECAST \u001b[39m=\u001b[39m \u001b[39mFalse\u001b[39;00m\n\u001b[0;32m---> <a href='vscode-notebook-cell://dev-container%2B7b22686f737450617468223a222f686f6d652f766963746f726d796c6c652f53656144726976652f4d79204c69627261726965732f4750552d7365727665722f546865736973222c226c6f63616c446f636b6572223a66616c73652c22636f6e66696746696c65223a7b22246d6964223a312c2270617468223a222f686f6d652f766963746f726d796c6c652f53656144726976652f4d79204c69627261726965732f4750552d7365727665722f5468657369732f2e646576636f6e7461696e65722f646576636f6e7461696e65722e6a736f6e222c22736368656d65223a227673636f64652d66696c65486f7374227d7d@ssh-remote%2Bvictormylle.be/workspaces/Thesis/src/notebooks/training.ipynb#X10sdnNjb2RlLXJlbW90ZQ%3D%3D?line=15'>16</a>\u001b[0m data_processor \u001b[39m=\u001b[39m DataProcessor()\n\u001b[1;32m <a href='vscode-notebook-cell://dev-container%2B7b22686f737450617468223a222f686f6d652f766963746f726d796c6c652f53656144726976652f4d79204c69627261726965732f4750552d7365727665722f546865736973222c226c6f63616c446f636b6572223a66616c73652c22636f6e66696746696c65223a7b22246d6964223a312c2270617468223a222f686f6d652f766963746f726d796c6c652f53656144726976652f4d79204c69627261726965732f4750552d7365727665722f5468657369732f2e646576636f6e7461696e65722f646576636f6e7461696e65722e6a736f6e222c22736368656d65223a227673636f64652d66696c65486f7374227d7d@ssh-remote%2Bvictormylle.be/workspaces/Thesis/src/notebooks/training.ipynb#X10sdnNjb2RlLXJlbW90ZQ%3D%3D?line=16'>17</a>\u001b[0m data_processor\u001b[39m.\u001b[39mset_batch_size(\u001b[39m1024\u001b[39m)\n\u001b[1;32m <a href='vscode-notebook-cell://dev-container%2B7b22686f737450617468223a222f686f6d652f766963746f726d796c6c652f53656144726976652f4d79204c69627261726965732f4750552d7365727665722f546865736973222c226c6f63616c446f636b6572223a66616c73652c22636f6e66696746696c65223a7b22246d6964223a312c2270617468223a222f686f6d652f766963746f726d796c6c652f53656144726976652f4d79204c69627261726965732f4750552d7365727665722f5468657369732f2e646576636f6e7461696e65722f646576636f6e7461696e65722e6a736f6e222c22736368656d65223a227673636f64652d66696c65486f7374227d7d@ssh-remote%2Bvictormylle.be/workspaces/Thesis/src/notebooks/training.ipynb#X10sdnNjb2RlLXJlbW90ZQ%3D%3D?line=18'>19</a>\u001b[0m data_processor\u001b[39m.\u001b[39mset_train_range((\u001b[39m-\u001b[39mnp\u001b[39m.\u001b[39minf, datetime(year\u001b[39m=\u001b[39m\u001b[39m2022\u001b[39m, month\u001b[39m=\u001b[39m\u001b[39m11\u001b[39m, day\u001b[39m=\u001b[39m\u001b[39m30\u001b[39m, tzinfo\u001b[39m=\u001b[39mpytz\u001b[39m.\u001b[39mUTC)))\n",
|
||||||
]
|
"\u001b[0;31mTypeError\u001b[0m: DataProcessor.__init__() missing 1 required positional argument: 'data_config'"
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "stdout",
|
|
||||||
"output_type": "stream",
|
|
||||||
"text": [
|
|
||||||
"ClearML Task: created new task id=07a2dc72793446d8a8101eafce0d80db\n",
|
|
||||||
"ClearML results page: http://192.168.1.182:8080/projects/2e46d4af6f1e4c399cf9f5aa30bc8795/experiments/07a2dc72793446d8a8101eafce0d80db/output/log\n",
|
|
||||||
"Early stopping triggered\n"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -178,17 +192,19 @@
|
|||||||
"#### Hyperparameters ####\n",
|
"#### Hyperparameters ####\n",
|
||||||
"inputDim = 96\n",
|
"inputDim = 96\n",
|
||||||
"learningRate = 0.0003\n",
|
"learningRate = 0.0003\n",
|
||||||
"epochs = 50\n",
|
"epochs = 100\n",
|
||||||
"\n",
|
"\n",
|
||||||
"quantiles = torch.tensor([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]).to(\"cuda\")\n",
|
"quantiles = torch.tensor([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]).to(\"cuda\")\n",
|
||||||
"\n",
|
"\n",
|
||||||
"# model = LinearRegression(inputDim, len(quantiles))\n",
|
"# model = LinearRegression(inputDim, len(quantiles))\n",
|
||||||
"model = NonLinearRegression(inputDim, len(quantiles), hiddenSize=1024, numLayers=5)\n",
|
"model = NonLinearRegression(inputDim, len(quantiles), hiddenSize=1024, numLayers=5, dropout=0.2)\n",
|
||||||
"model.output_size = 1\n",
|
"model.output_size = 1\n",
|
||||||
"optimizer = torch.optim.Adam(model.parameters(), lr=learningRate)\n",
|
"optimizer = torch.optim.Adam(model.parameters(), lr=learningRate)\n",
|
||||||
"\n",
|
"\n",
|
||||||
"#### Data Processor ####\n",
|
"#### Data Processor ####\n",
|
||||||
"data_processor = DataProcessor()\n",
|
"data_config = DataConfig()\n",
|
||||||
|
"data_config.LOAD_FORECAST = False\n",
|
||||||
|
"data_processor = DataProcessor(data_config)\n",
|
||||||
"data_processor.set_batch_size(1024)\n",
|
"data_processor.set_batch_size(1024)\n",
|
||||||
"\n",
|
"\n",
|
||||||
"data_processor.set_train_range((-np.inf, datetime(year=2022, month=11, day=30, tzinfo=pytz.UTC)))\n",
|
"data_processor.set_train_range((-np.inf, datetime(year=2022, month=11, day=30, tzinfo=pytz.UTC)))\n",
|
||||||
@@ -204,6 +220,13 @@
|
|||||||
"trainer.plot_every(10)\n",
|
"trainer.plot_every(10)\n",
|
||||||
"trainer.train(epochs=epochs)"
|
"trainer.train(epochs=epochs)"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"metadata": {
|
"metadata": {
|
||||||
|
|||||||
@@ -10,19 +10,16 @@ from plotly.subplots import make_subplots
|
|||||||
from trainers.trainer import Trainer
|
from trainers.trainer import Trainer
|
||||||
|
|
||||||
class AutoRegressiveTrainer(Trainer):
|
class AutoRegressiveTrainer(Trainer):
|
||||||
def debug_plots(self, task, train: bool, samples, epoch):
|
def debug_plots(self, task, train: bool, data_loader, sample_indices, epoch):
|
||||||
X, y = samples
|
num_samples = len(sample_indices)
|
||||||
X = X.to(self.device)
|
|
||||||
|
|
||||||
num_samples = len(X)
|
|
||||||
rows = num_samples # One row per sample since we only want one column
|
rows = num_samples # One row per sample since we only want one column
|
||||||
cols = 1
|
cols = 1
|
||||||
|
|
||||||
fig = make_subplots(rows=rows, cols=cols, subplot_titles=[f'Sample {i+1}' for i in range(num_samples)])
|
fig = make_subplots(rows=rows, cols=cols, subplot_titles=[f'Sample {i+1}' for i in range(num_samples)])
|
||||||
|
|
||||||
for i, (current_day, next_day) in enumerate(zip(X, y)):
|
for i, idx in enumerate(sample_indices):
|
||||||
predictions = self.predict_auto_regressive(current_day)
|
initial, predictions, target = self.auto_regressive(data_loader, idx)
|
||||||
sub_fig = self.get_plot(current_day, next_day, predictions, show_legend=(i == 0))
|
sub_fig = self.get_plot(initial, target, predictions, show_legend=(i == 0))
|
||||||
|
|
||||||
row = i + 1
|
row = i + 1
|
||||||
col = 1
|
col = 1
|
||||||
@@ -30,7 +27,7 @@ class AutoRegressiveTrainer(Trainer):
|
|||||||
for trace in sub_fig.data:
|
for trace in sub_fig.data:
|
||||||
fig.add_trace(trace, row=row, col=col)
|
fig.add_trace(trace, row=row, col=col)
|
||||||
|
|
||||||
loss = self.criterion(predictions.to(self.device), next_day.to(self.device)).item()
|
loss = self.criterion(predictions.to(self.device), target.to(self.device)).item()
|
||||||
|
|
||||||
fig['layout']['annotations'][i].update(text=f"{loss.__class__.__name__}: {loss:.6f}")
|
fig['layout']['annotations'][i].update(text=f"{loss.__class__.__name__}: {loss:.6f}")
|
||||||
|
|
||||||
@@ -46,14 +43,38 @@ class AutoRegressiveTrainer(Trainer):
|
|||||||
figure=fig
|
figure=fig
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def auto_regressive(self, data_loader, idx, sequence_length: int = 96):
|
||||||
|
self.model.eval()
|
||||||
|
target_full = []
|
||||||
|
predictions_full = []
|
||||||
|
|
||||||
def predict_auto_regressive(self, initial_sequence: torch.Tensor, sequence_length: int = 96):
|
prev_features, target = data_loader.dataset[idx]
|
||||||
initial_sequence = initial_sequence.to(self.device)
|
prev_features = prev_features.to(self.device)
|
||||||
|
|
||||||
return predict_auto_regressive(self.model, initial_sequence, sequence_length)
|
initial_sequence = prev_features[:96]
|
||||||
|
|
||||||
def random_day_prediction(self):
|
target_full.append(target)
|
||||||
current_day_features, next_day_features = self.data_processor.get_random_test_day()
|
with torch.no_grad():
|
||||||
|
prediction = self.model(prev_features.unsqueeze(0))
|
||||||
|
predictions_full.append(prediction.squeeze(-1))
|
||||||
|
|
||||||
predictions = self.predict_auto_regressive(current_day_features)
|
for i in range(sequence_length - 1):
|
||||||
return current_day_features, next_day_features, predictions
|
new_features = torch.cat((prev_features[1:97].cpu(), prediction.squeeze(-1).cpu()), dim=0)
|
||||||
|
|
||||||
|
# get the other needed features
|
||||||
|
other_features, new_target = data_loader.dataset.random_day_autoregressive(idx + i + 1)
|
||||||
|
|
||||||
|
if other_features is not None:
|
||||||
|
prev_features = torch.cat((new_features, other_features), dim=0)
|
||||||
|
else:
|
||||||
|
prev_features = new_features
|
||||||
|
|
||||||
|
# add target to target_full
|
||||||
|
target_full.append(new_target)
|
||||||
|
|
||||||
|
# predict
|
||||||
|
with torch.no_grad():
|
||||||
|
prediction = self.model(new_features.unsqueeze(0).to(self.device))
|
||||||
|
predictions_full.append(prediction.squeeze(-1))
|
||||||
|
|
||||||
|
return initial_sequence.cpu(), torch.stack(predictions_full).cpu(), torch.stack(target_full).cpu()
|
||||||
@@ -20,10 +20,6 @@ class QuantileTrainer(AutoRegressiveTrainer):
|
|||||||
criterion = PinballLoss(quantiles=quantiles_tensor)
|
criterion = PinballLoss(quantiles=quantiles_tensor)
|
||||||
super().__init__(model=model, optimizer=optimizer, criterion=criterion, data_processor=data_processor, device=device, clearml_helper=clearml_helper, debug=debug)
|
super().__init__(model=model, optimizer=optimizer, criterion=criterion, data_processor=data_processor, device=device, clearml_helper=clearml_helper, debug=debug)
|
||||||
|
|
||||||
def predict_auto_regressive(self, initial_sequence: torch.Tensor, sequence_length: int = 96):
|
|
||||||
initial_sequence = initial_sequence.to(self.device)
|
|
||||||
|
|
||||||
return predict_auto_regressive_quantile(self.model, self.sample_from_dist, initial_sequence, self.quantiles, sequence_length)
|
|
||||||
|
|
||||||
def log_final_metrics(self, task, dataloader, train: bool = True):
|
def log_final_metrics(self, task, dataloader, train: bool = True):
|
||||||
metrics = { metric.__class__.__name__: 0.0 for metric in self.metrics_to_track }
|
metrics = { metric.__class__.__name__: 0.0 for metric in self.metrics_to_track }
|
||||||
@@ -85,6 +81,52 @@ class QuantileTrainer(AutoRegressiveTrainer):
|
|||||||
|
|
||||||
return fig
|
return fig
|
||||||
|
|
||||||
|
def auto_regressive(self, data_loader, idx, sequence_length: int = 96):
|
||||||
|
self.model.eval()
|
||||||
|
target_full = []
|
||||||
|
predictions_sampled = []
|
||||||
|
predictions_full = []
|
||||||
|
|
||||||
|
prev_features, target = data_loader.dataset[idx]
|
||||||
|
prev_features = prev_features.to(self.device)
|
||||||
|
|
||||||
|
initial_sequence = prev_features[:96]
|
||||||
|
|
||||||
|
target_full.append(target)
|
||||||
|
with torch.no_grad():
|
||||||
|
prediction = self.model(prev_features.unsqueeze(0))
|
||||||
|
predictions_full.append(prediction.squeeze(0))
|
||||||
|
|
||||||
|
# sample from the distribution
|
||||||
|
sample = self.sample_from_dist(self.quantiles.cpu(), prediction.squeeze(-1).cpu().numpy())
|
||||||
|
predictions_sampled.append(sample)
|
||||||
|
|
||||||
|
for i in range(sequence_length - 1):
|
||||||
|
new_features = torch.cat((prev_features[1:97].cpu(), torch.tensor([predictions_sampled[-1]])), dim=0)
|
||||||
|
new_features = new_features.float()
|
||||||
|
|
||||||
|
# get the other needed features
|
||||||
|
other_features, new_target = data_loader.dataset.random_day_autoregressive(idx + i + 1)
|
||||||
|
|
||||||
|
if other_features is not None:
|
||||||
|
prev_features = torch.cat((new_features, other_features), dim=0)
|
||||||
|
else:
|
||||||
|
prev_features = new_features
|
||||||
|
|
||||||
|
# add target to target_full
|
||||||
|
target_full.append(new_target)
|
||||||
|
|
||||||
|
# predict
|
||||||
|
with torch.no_grad():
|
||||||
|
prediction = self.model(new_features.unsqueeze(0).to(self.device))
|
||||||
|
predictions_full.append(prediction.squeeze(0))
|
||||||
|
|
||||||
|
# sample from the distribution
|
||||||
|
sample = self.sample_from_dist(self.quantiles.cpu(), prediction.squeeze(-1).cpu().numpy())
|
||||||
|
predictions_sampled.append(sample)
|
||||||
|
|
||||||
|
return initial_sequence.cpu(), torch.stack(predictions_full).cpu(), torch.stack(target_full).cpu()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def sample_from_dist(quantiles, output_values):
|
def sample_from_dist(quantiles, output_values):
|
||||||
# Interpolate the inverse CDF
|
# Interpolate the inverse CDF
|
||||||
|
|||||||
@@ -70,23 +70,22 @@ class Trainer:
|
|||||||
return task
|
return task
|
||||||
|
|
||||||
def random_samples(self, train: bool = True, num_samples: int = 10):
|
def random_samples(self, train: bool = True, num_samples: int = 10):
|
||||||
random_X = []
|
train_loader, test_loader = self.data_processor.get_dataloaders(predict_sequence_length=self.model.output_size)
|
||||||
random_Y = []
|
|
||||||
|
|
||||||
for _ in range(num_samples):
|
if train:
|
||||||
X, y = self.data_processor.get_random_day(train=train)
|
loader = train_loader
|
||||||
random_X.append(X)
|
else:
|
||||||
random_Y.append(y)
|
loader = test_loader
|
||||||
|
|
||||||
|
indices = np.random.randint(0, len(loader.dataset) - 1, size=num_samples)
|
||||||
|
return indices
|
||||||
|
|
||||||
random_X = torch.stack(random_X)
|
|
||||||
random_Y = torch.stack(random_Y)
|
|
||||||
return random_X, random_Y
|
|
||||||
|
|
||||||
def train(self, epochs: int):
|
def train(self, epochs: int):
|
||||||
train_loader, test_loader = self.data_processor.get_dataloaders(predict_sequence_length=self.model.output_size)
|
train_loader, test_loader = self.data_processor.get_dataloaders(predict_sequence_length=self.model.output_size)
|
||||||
|
|
||||||
train_random_X, train_random_y = self.random_samples(train=True)
|
train_samples = self.random_samples(train=True)
|
||||||
test_random_X, test_random_y = self.random_samples(train=False)
|
test_samples = self.random_samples(train=False)
|
||||||
|
|
||||||
task = self.init_clearml_task()
|
task = self.init_clearml_task()
|
||||||
|
|
||||||
@@ -129,8 +128,8 @@ class Trainer:
|
|||||||
|
|
||||||
|
|
||||||
if epoch % self.plot_every_n_epochs == 0:
|
if epoch % self.plot_every_n_epochs == 0:
|
||||||
self.debug_plots(task, True, (train_random_X, train_random_y), epoch)
|
self.debug_plots(task, True, train_loader, train_samples, epoch)
|
||||||
self.debug_plots(task, False, (test_random_X, test_random_y), epoch)
|
self.debug_plots(task, False, test_loader, test_samples, epoch)
|
||||||
|
|
||||||
if task:
|
if task:
|
||||||
self.finish_training(task=task)
|
self.finish_training(task=task)
|
||||||
@@ -144,6 +143,7 @@ class Trainer:
|
|||||||
with torch.no_grad():
|
with torch.no_grad():
|
||||||
for inputs, targets in dataloader:
|
for inputs, targets in dataloader:
|
||||||
inputs, targets = inputs.to(self.device), targets
|
inputs, targets = inputs.to(self.device), targets
|
||||||
|
|
||||||
outputs = self.model(inputs)
|
outputs = self.model(inputs)
|
||||||
|
|
||||||
inversed_outputs = torch.tensor(self.data_processor.inverse_transform(outputs))
|
inversed_outputs = torch.tensor(self.data_processor.inverse_transform(outputs))
|
||||||
@@ -215,22 +215,25 @@ class Trainer:
|
|||||||
return fig
|
return fig
|
||||||
|
|
||||||
|
|
||||||
def debug_plots(self, task, train: bool, samples, epoch):
|
def debug_plots(self, task, train: bool, data_loader, sample_indices, epoch):
|
||||||
X, y = samples
|
num_samples = len(sample_indices)
|
||||||
X = X.to(self.device)
|
|
||||||
|
|
||||||
num_samples = len(X)
|
|
||||||
rows = num_samples # One row per sample since we only want one column
|
rows = num_samples # One row per sample since we only want one column
|
||||||
cols = 1
|
cols = 1
|
||||||
|
|
||||||
fig = make_subplots(rows=rows, cols=cols, subplot_titles=[f'Sample {i+1}' for i in range(num_samples)])
|
fig = make_subplots(rows=rows, cols=cols, subplot_titles=[f'Sample {i+1}' for i in range(num_samples)])
|
||||||
|
|
||||||
for i, (current_day, next_day) in enumerate(zip(X, y)):
|
for i, idx in enumerate(sample_indices):
|
||||||
|
|
||||||
|
features, target = data_loader.dataset[idx]
|
||||||
|
|
||||||
|
features = features.to(self.device)
|
||||||
|
target = target.to(self.device)
|
||||||
|
|
||||||
self.model.eval()
|
self.model.eval()
|
||||||
with torch.no_grad():
|
with torch.no_grad():
|
||||||
predictions = self.model(current_day).cpu()
|
predictions = self.model(features).cpu()
|
||||||
|
|
||||||
sub_fig = self.get_plot(current_day, next_day, predictions, show_legend=(i == 0))
|
sub_fig = self.get_plot(features[:96], target, predictions, show_legend=(i == 0))
|
||||||
|
|
||||||
row = i + 1
|
row = i + 1
|
||||||
col = 1
|
col = 1
|
||||||
@@ -239,7 +242,7 @@ class Trainer:
|
|||||||
fig.add_trace(trace, row=row, col=col)
|
fig.add_trace(trace, row=row, col=col)
|
||||||
|
|
||||||
|
|
||||||
loss = self.criterion(predictions.to(self.device), next_day.squeeze(-1).to(self.device)).item()
|
loss = self.criterion(predictions.to(self.device), target.squeeze(-1).to(self.device)).item()
|
||||||
|
|
||||||
fig['layout']['annotations'][i].update(text=f"{loss.__class__.__name__}: {loss:.6f}")
|
fig['layout']['annotations'][i].update(text=f"{loss.__class__.__name__}: {loss:.6f}")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user