aromidvar1355 commited on
Commit
fa4e17e
·
verified ·
1 Parent(s): e1026f9

Update core/train_eval.py

Browse files
Files changed (1) hide show
  1. core/train_eval.py +53 -19
core/train_eval.py CHANGED
@@ -9,11 +9,11 @@ import matplotlib.pyplot as plt
9
  import os
10
 
11
 
12
- def create_sequences(data, window_size):
13
  X, y = [], []
14
- for i in range(len(data) - window_size):
15
  X.append(data[i:i + window_size])
16
- y.append(data[i + window_size])
17
  return np.array(X), np.array(y)
18
 
19
 
@@ -38,30 +38,41 @@ def train_and_evaluate(
38
  # Step 2: Normalize data
39
  scaler = StandardScaler()
40
  scaled_data = scaler.fit_transform(original_values.reshape(-1, 1))
41
- X, y = create_sequences(scaled_data, window)
42
 
43
- # Step 3: Split
44
  split = int(len(X) * (1 - test_split))
45
- X_train, X_test = X[:split], X[split:]
46
- y_train, y_test = y[:split], y[split:]
 
47
 
48
  X_train_tensor = torch.tensor(X_train, dtype=torch.float32)
49
  y_train_tensor = torch.tensor(y_train, dtype=torch.float32)
 
 
50
  X_test_tensor = torch.tensor(X_test, dtype=torch.float32)
51
  y_test_tensor = torch.tensor(y_test, dtype=torch.float32)
52
 
53
  train_loader = DataLoader(TensorDataset(X_train_tensor, y_train_tensor), batch_size=32, shuffle=True)
 
54
  test_loader = DataLoader(TensorDataset(X_test_tensor, y_test_tensor), batch_size=32, shuffle=False)
55
 
56
  # Step 4: Model
57
  input_dim = X_train.shape[2] if X_train.ndim == 3 else 1
58
  model = model_cls(input_size=input_dim, hidden_size=hidden, num_layers=layers, output_size=horizon).to(device)
59
- optimizer = torch.optim.AdamW(model.parameters(), lr=0.001, betas=(0.9, 0.999), weight_decay=0.01)
60
  loss_fn = nn.MSELoss()
61
 
62
  train_losses = []
 
 
 
 
 
 
63
  model.train()
64
  for epoch in range(epochs):
 
65
  epoch_loss = 0.0
66
  for xb, yb in train_loader:
67
  xb, yb = xb.to(device), yb.to(device)
@@ -72,10 +83,38 @@ def train_and_evaluate(
72
  optimizer.step()
73
  epoch_loss += loss.item()
74
  train_losses.append(epoch_loss / len(train_loader))
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  if verbose and (epoch + 1) % 10 == 0:
76
- print(f"Epoch {epoch+1}/{epochs} - Loss: {train_losses[-1]:.4f}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
 
78
  result["train_loss"] = train_losses
 
79
 
80
  # Step 5: Evaluate
81
  model.eval()
@@ -90,16 +129,14 @@ def train_and_evaluate(
90
  preds = np.concatenate(preds, axis=0)
91
  targets = np.concatenate(targets, axis=0)
92
 
93
- preds_inv = scaler.inverse_transform(preds.reshape(-1, 1)).reshape(preds.shape)
94
- targets_inv = scaler.inverse_transform(targets.reshape(-1, 1)).reshape(targets.shape)
95
 
96
  mse = mean_squared_error(targets_inv, preds_inv)
97
  rmse = np.sqrt(mse)
98
  mae = mean_absolute_error(targets_inv, preds_inv)
99
- # Calculate R2 score
100
  r2 = r2_score(targets_inv, preds_inv)
101
 
102
-
103
  result["metrics"] = {
104
  #"R2": round(r2, 4),
105
  "RMSE": round(rmse, 4),
@@ -110,17 +147,14 @@ def train_and_evaluate(
110
  result["actual"] = targets_inv
111
  result["predicted"] = result["forecast"]
112
 
113
- # Step 6: Predict the next value (for UI)
114
  latest_window = scaled_data[-window:].reshape(1, window, 1)
115
  latest_input = torch.tensor(latest_window, dtype=torch.float32).to(device)
116
 
117
  with torch.no_grad():
118
  future_pred = model(latest_input).cpu().numpy()
119
- future_pred_inv = scaler.inverse_transform(future_pred.reshape(-1, 1)).reshape(future_pred.shape)
120
 
121
- result["latest_prediction"] = {
122
- "input_index": len(original_values),
123
- "value": float(future_pred_inv[0][0])
124
- }
125
 
126
  return result
 
9
  import os
10
 
11
 
12
+ def create_sequences(data, window_size, horizon=1):
13
  X, y = [], []
14
+ for i in range(len(data) - window_size - horizon + 1):
15
  X.append(data[i:i + window_size])
16
+ y.append(data[i + window_size:i + window_size + horizon].flatten())
17
  return np.array(X), np.array(y)
18
 
19
 
 
38
  # Step 2: Normalize data
39
  scaler = StandardScaler()
40
  scaled_data = scaler.fit_transform(original_values.reshape(-1, 1))
41
+ X, y = create_sequences(scaled_data, window, horizon)
42
 
43
+ # Step 3: Split into train, validation, and test
44
  split = int(len(X) * (1 - test_split))
45
+ val_split = int(split * 0.9) # 90% of training data for training, 10% for validation
46
+ X_train, X_val, X_test = X[:val_split], X[val_split:split], X[split:]
47
+ y_train, y_val, y_test = y[:val_split], y[val_split:split], y[split:]
48
 
49
  X_train_tensor = torch.tensor(X_train, dtype=torch.float32)
50
  y_train_tensor = torch.tensor(y_train, dtype=torch.float32)
51
+ X_val_tensor = torch.tensor(X_val, dtype=torch.float32)
52
+ y_val_tensor = torch.tensor(y_val, dtype=torch.float32)
53
  X_test_tensor = torch.tensor(X_test, dtype=torch.float32)
54
  y_test_tensor = torch.tensor(y_test, dtype=torch.float32)
55
 
56
  train_loader = DataLoader(TensorDataset(X_train_tensor, y_train_tensor), batch_size=32, shuffle=True)
57
+ val_loader = DataLoader(TensorDataset(X_val_tensor, y_val_tensor), batch_size=32, shuffle=False)
58
  test_loader = DataLoader(TensorDataset(X_test_tensor, y_test_tensor), batch_size=32, shuffle=False)
59
 
60
  # Step 4: Model
61
  input_dim = X_train.shape[2] if X_train.ndim == 3 else 1
62
  model = model_cls(input_size=input_dim, hidden_size=hidden, num_layers=layers, output_size=horizon).to(device)
63
+ optimizer = torch.optim.AdamW(model.parameters(), lr=lr, betas=(0.9, 0.999), weight_decay=0.01)
64
  loss_fn = nn.MSELoss()
65
 
66
  train_losses = []
67
+ val_losses = []
68
+ best_val_loss = float('inf')
69
+ patience = 5
70
+ counter = 0
71
+ best_model_state = None
72
+
73
  model.train()
74
  for epoch in range(epochs):
75
+ # Training
76
  epoch_loss = 0.0
77
  for xb, yb in train_loader:
78
  xb, yb = xb.to(device), yb.to(device)
 
83
  optimizer.step()
84
  epoch_loss += loss.item()
85
  train_losses.append(epoch_loss / len(train_loader))
86
+
87
+ # Validation
88
+ model.eval()
89
+ val_loss = 0.0
90
+ with torch.no_grad():
91
+ for xb, yb in val_loader:
92
+ xb, yb = xb.to(device), yb.to(device)
93
+ out = model(xb)
94
+ loss = loss_fn(out, yb)
95
+ val_loss += loss.item()
96
+ val_loss /= len(val_loader)
97
+ val_losses.append(val_loss)
98
+
99
  if verbose and (epoch + 1) % 10 == 0:
100
+ print(f"Epoch {epoch+1}/{epochs} - Train Loss: {train_losses[-1]:.4f}, Val Loss: {val_losses[-1]:.4f}")
101
+
102
+ # Early stopping
103
+ if val_loss < best_val_loss:
104
+ best_val_loss = val_loss
105
+ counter = 0
106
+ best_model_state = model.state_dict()
107
+ else:
108
+ counter += 1
109
+ if counter >= patience:
110
+ print(f"Early stopping at epoch {epoch+1}")
111
+ break
112
+
113
+ if best_model_state:
114
+ model.load_state_dict(best_model_state)
115
 
116
  result["train_loss"] = train_losses
117
+ result["val_loss"] = val_losses
118
 
119
  # Step 5: Evaluate
120
  model.eval()
 
129
  preds = np.concatenate(preds, axis=0)
130
  targets = np.concatenate(targets, axis=0)
131
 
132
+ preds_inv = scaler.inverse_transform(preds.reshape(-1, horizon)).reshape(preds.shape)
133
+ targets_inv = scaler.inverse_transform(targets.reshape(-1, horizon)).reshape(targets.shape)
134
 
135
  mse = mean_squared_error(targets_inv, preds_inv)
136
  rmse = np.sqrt(mse)
137
  mae = mean_absolute_error(targets_inv, preds_inv)
 
138
  r2 = r2_score(targets_inv, preds_inv)
139
 
 
140
  result["metrics"] = {
141
  #"R2": round(r2, 4),
142
  "RMSE": round(rmse, 4),
 
147
  result["actual"] = targets_inv
148
  result["predicted"] = result["forecast"]
149
 
150
+ # Step 6: Predict the next value(s) (for UI)
151
  latest_window = scaled_data[-window:].reshape(1, window, 1)
152
  latest_input = torch.tensor(latest_window, dtype=torch.float32).to(device)
153
 
154
  with torch.no_grad():
155
  future_pred = model(latest_input).cpu().numpy()
156
+ future_pred_inv = scaler.inverse_transform(future_pred.reshape(-1, horizon)).reshape(future_pred.shape)
157
 
158
+ result["latest_prediction"] = future_pred_inv[0].tolist() # List of horizon predictions
 
 
 
159
 
160
  return result