-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathengine.py
More file actions
160 lines (140 loc) · 5.09 KB
/
Copy pathengine.py
File metadata and controls
160 lines (140 loc) · 5.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
from typing import List, Dict, Tuple
import torch
from tqdm.auto import tqdm
def train_step(
model: torch.nn.Module,
dataloader: torch.utils.data.DataLoader,
loss_fn: torch.nn.Module,
optimizer:torch.optim.Optimizer,
device:torch.device
)->Tuple[float, float]:
"""
Trains a PyTorch model for a single epoch.
Turns a target Pytorch model to training mode and then runs through all of
the training steps.
Args:
model: A PyTorch model to be trained.
dataloader: A DataLoader instance for the model to be trained on
loss_fn: A PyTorch loss function to minimize
optimizer: a PyTorch optimizer to help minimize the loss function
device: A target device to compute on
Returns:
A tuple of training loss and training accuracy metrics, in the form of
(train_loss, train_accuracy). For example: (0.1112, 0.8743)
"""
model.train()
train_loss, train_acc = 0, 0
for X, y in dataloader:
X, y = X.to(device), y.to(device)
y_pred = model(X)
loss = loss_fn(y_pred, y)
train_loss += loss.item()
optimizer.zero_grad()
loss.backward()
optimizer.step()
y_pred_class = torch.argmax(torch.softmax(y_pred, dim=1), dim=1)
train_acc += (y_pred_class == y).sum().item()/len(y_pred)
train_loss = train_loss / len(dataloader)
train_acc = train_acc / len(dataloader)
return train_loss, train_acc
def val_step(
model: torch.nn.Module,
dataloader: torch.utils.data.DataLoader,
loss_fn: torch.nn.Module,
device: torch.device
)-> Tuple[float, float]:
"""
Validates a PyTorch model for a single epoch.
Turns a target PyTorch model to 'eval' model and then performs
a forward pass on a testing dataset.
Args:
model: A PyTorch model to be tested
dataloader: A DataLoader instance for the model to be tested on
loss_fn: A Pytorch loss function to calculate loss on the test data
device: A target device to compute on
Returns:
a tuple of testing loss and testing accuracy metrics in the form
(test_loss, test_accuracy). For example:
(0.0223, 0.8985)
"""
model.eval()
val_loss, val_acc = 0, 0
with torch.inference_mode():
for X, y in dataloader:
X, y = X.to(device), y.to(device)
val_pred = model(X)
loss = loss_fn(val_pred, y)
val_loss += loss.item()
val_pred_class = val_pred.argmax(dim=1)
val_acc += (val_pred_class == y).sum().item()/len(val_pred_class)
val_loss /= len(dataloader)
val_acc /= len(dataloader)
return val_loss, val_acc
def train(
model: torch.nn.Module,
train_dataloader: torch.utils.data.DataLoader,
val_dataloader: torch.utils.data.DataLoader,
optimizer: torch.optim.Optimizer,
loss_fn: torch.nn.Module,
epochs: int,
device: torch.device
)-> Dict[str, List[float]]:
"""
Trains and validates a Pytorch model.
Passes a target PyTorch model through a train_step() and a test_step()
function for a number of epochs, training and testing the model in the
same epoch loop.
Calculates, prints and stores evaluation metrics throughout.
Args:
model: A PyTorch model to be trained and tested.
train_dataloader: A DataLoader instance for the model to be trained on.
test_dataloader: A DataLoader instance for the model to be tested on.
optimizer: A PyTorch optimizer to help minimize the loss function.
loss_fn: A PyTorch loss function to calculate loss on both datasets.
epochs: An integer indicating how many epochs to train for.
device: A target device to compute on
Returns:
A dictionary of training and testing loss as well as training and testing accuracy
metrics. Each metric has a value ina list for each epoch.
In the form: {
train_loss: [...],
train_acc: [...],
test_loss: [...],
test_acc: [...]
}
For example if training for epochs=2:
{
train_loss: [2.0616, 1.0537],
train_acc: [0,3934, 0.4125],
test_loss: [1,2537, 1.5706],
test_acc: [0.3400, 0.2973]
}
"""
results = {
"train_loss": [],
"train_acc": [],
"val_loss": [],
"val_acc": []
}
for epoch in tqdm(range(epochs)):
train_loss, train_acc = train_step(
model=model,
dataloader=train_dataloader,
loss_fn=loss_fn,
optimizer=optimizer,
device=device
)
val_loss, val_acc = val_step(
model=model,
dataloader=val_dataloader,
loss_fn=loss_fn,
device=device
)
print(f"Epoch: {epoch+1}")
print(f"Train loss: {train_loss:.4f} | Train acc: {train_acc:.4f}")
print(f"Val loss: {val_loss:.4f} | Val acc: {val_acc:.4f}\n")
results["train_loss"].append(train_loss)
results["train_acc"].append(train_acc)
results["val_loss"].append(val_loss)
results["val_acc"].append(val_acc)
return results