90 lines
4.1 KiB
Python
90 lines
4.1 KiB
Python
import torch
|
|
from aiRNN import dataloader, models, losses
|
|
import pathlib
|
|
import pandas as pd
|
|
|
|
file_list = pathlib.Path("../../cpp/known_routes_and_aircraft.csv")
|
|
base_path = file_list.parent
|
|
file_list = file_list.read_text().splitlines()
|
|
file_list = [(base_path / f).resolve() for f in file_list if (base_path / f).exists()]
|
|
|
|
if not pathlib.Path("dataset.pt").exists():
|
|
dataset = dataloader.EvenlySpacedDataset(
|
|
filepaths=file_list,
|
|
n_input=30*15, # 15 minutes input
|
|
n_output=30*5, # 5 minutes output
|
|
n_windows_per_file=7,
|
|
step=1,
|
|
feature_columns=("lat", "lon", "alt", "ias"),
|
|
context_columns=("last_lat", "last_lon", "last_alt", "last_ias", "last_timestamp"),
|
|
time_columns=("timestamp", "dt"),
|
|
target_columns=("lat", "lon", "alt"),
|
|
device="cuda",
|
|
)
|
|
dataset.save_entire_dataset("dataset.pt")
|
|
|
|
results = []
|
|
for step in [1, 5, 10, 30]:
|
|
dataset = dataloader.SaveDataset(torch.load("dataset.pt"), device="cuda", step=step)
|
|
dataset_length = len(dataset)
|
|
dataset, val_dataset = torch.utils.data.random_split(
|
|
dataset,
|
|
[int(0.8 * dataset_length), dataset_length - int(0.8 * dataset_length)],
|
|
generator=torch.Generator().manual_seed(42)
|
|
)
|
|
print(f"Starting hyperparameter scan for step={step}")
|
|
for base_name, base_model in [
|
|
("RNN", models.ThreeInputRNN),
|
|
("LSTM", models.ThreeInputLSTM),
|
|
("GRU", models.ThreeInputGRU),
|
|
]:
|
|
for hidden_size in [16, 32, 64]:
|
|
for rnn_size in [32, 64, 128]:
|
|
model = base_model(
|
|
time_in=2,
|
|
feat_in=4,
|
|
context_in=5,
|
|
hidden_size=hidden_size,
|
|
rnn_size=rnn_size,
|
|
out_size=3,
|
|
device="cuda",
|
|
)
|
|
print(f"Training {base_name} with hidden_size={hidden_size}, rnn_size={rnn_size}")
|
|
optimizer = torch.optim.Adam(model.parameters(), lr=1e-2)
|
|
scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, patience=5, factor=0.5)
|
|
criterion = losses.HaversineAltitudeLoss(alt_const=1e-3)
|
|
loss = -1.0
|
|
for epoch in range(100):
|
|
loss_history = []
|
|
for X_f, X_t, y, X_c in torch.utils.data.DataLoader(dataset, batch_size=256, shuffle=True):
|
|
optimizer.zero_grad()
|
|
warm_up_steps = 450 // step
|
|
pred_steps = 150 // step
|
|
y_pred, _ = model(X_t, X_f, X_c, warm_up_steps, pred_steps)
|
|
loss = criterion(y_pred, y)
|
|
loss.backward()
|
|
torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)
|
|
optimizer.step()
|
|
loss_history.append(loss.item())
|
|
loss = sum(loss_history) / len(loss_history)
|
|
scheduler.step(loss)
|
|
print(f"Epoch {epoch}: loss={loss}, lr={optimizer.param_groups[0]['lr']}")
|
|
with torch.no_grad():
|
|
val_loss_history = []
|
|
for X_f, X_t, y, X_c in torch.utils.data.DataLoader(val_dataset, batch_size=256):
|
|
warm_up_steps = 450 // step
|
|
pred_steps = 150 // step
|
|
y_pred, _ = model(X_t, X_f, X_c, warm_up_steps, pred_steps)
|
|
v_loss = criterion(y_pred, y)
|
|
val_loss_history.append(v_loss.item())
|
|
loss = sum(val_loss_history) / len(val_loss_history)
|
|
print(f"Validation loss: {loss}")
|
|
torch.save(model.state_dict(), f"{base_name}_hs{hidden_size}_rs{rnn_size}_step{step}.pt")
|
|
results.append((base_name, hidden_size, rnn_size, step, loss))
|
|
|
|
for r in results:
|
|
print(f"Model: {r[0]}, hidden_size={r[1]}, rnn_size={r[2]}, step={r[3]} => final loss={r[4]}")
|
|
|
|
# Save results to CSV
|
|
df = pd.DataFrame(results, columns=["Model", "Hidden Size", "RNN Size", "Step", "Final Loss"])
|
|
df.to_csv("hyperparameter_scan_results.csv", index=False) |