-
Notifications
You must be signed in to change notification settings - Fork 33
/
Copy pathNeptune_hpo_single_run.py
121 lines (99 loc) · 3.35 KB
/
Neptune_hpo_single_run.py
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
from functools import reduce
import neptune
import torch
import torch.nn as nn
import torch.optim as optim
from neptune.utils import stringify_unsupported
from torchvision import datasets, transforms
from tqdm.auto import trange
# Create a Neptune run
run = neptune.init_run(
project="common/hpo", # your project name
api_token=neptune.ANONYMOUS_API_TOKEN, # your api token
tags=["script"],
)
# Hyperparameters
parameters = {
"batch_size": 64,
"epochs": 2,
"input_size": (3, 32, 32),
"n_classes": 10,
"dataset_size": 1000,
"model_filename": "basemodel",
"device": torch.device("cuda:0" if torch.cuda.is_available() else "cpu"),
}
input_size = reduce(lambda x, y: x * y, parameters["input_size"])
## Hyperparameter search space
learning_rates = [0.005, 0.01, 0.05] # learning rate choices
# Model
class BaseModel(nn.Module):
def __init__(self, input_size, hidden_dim, n_classes):
super(BaseModel, self).__init__()
self.main = nn.Sequential(
nn.Linear(input_size, hidden_dim * 2),
nn.ReLU(),
nn.Linear(hidden_dim * 2, hidden_dim),
nn.ReLU(),
nn.Linear(hidden_dim, hidden_dim // 2),
nn.ReLU(),
nn.Linear(hidden_dim // 2, n_classes),
)
self.input_size = input_size
def forward(self, input):
x = input.view(-1, self.input_size)
return self.main(x)
model = BaseModel(
input_size,
input_size,
parameters["n_classes"],
).to(parameters["device"])
criterion = nn.CrossEntropyLoss()
# Dataset
data_tfms = {
"train": transforms.Compose(
[
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]),
]
)
}
trainset = datasets.FakeData(
size=parameters["dataset_size"],
image_size=parameters["input_size"],
num_classes=parameters["n_classes"],
transform=data_tfms["train"],
)
trainloader = torch.utils.data.DataLoader(
trainset, batch_size=parameters["batch_size"], shuffle=True, num_workers=0
)
# Training loop
for i, lr in enumerate(learning_rates):
# Log hyperparameters
run[f"trials/{i}/params"] = stringify_unsupported(parameters)
run[f"trials/{i}/params/lr"] = lr
optimizer = optim.SGD(model.parameters(), lr=lr)
# Initialize fields for best values across all trials
best_loss = None
for _ in trange(parameters["epochs"]):
for x, y in trainloader:
x, y = x.to(parameters["device"]), y.to(parameters["device"])
optimizer.zero_grad()
outputs = model.forward(x)
loss = criterion(outputs, y)
_, preds = torch.max(outputs, 1)
acc = (torch.sum(preds == y.data)) / len(x)
# Log trial metrics
run[f"trials/{i}/metrics/batch/loss"].append(loss)
run[f"trials/{i}/metrics/batch/acc"].append(acc)
# Log best values across all trials
if best_loss is None or loss < best_loss:
run["best/trial"] = i
run["best/metrics/loss"] = best_loss = loss
run["best/metrics/acc"] = acc
run["best/params"] = stringify_unsupported(parameters)
run["best/params/lr"] = lr
loss.backward()
optimizer.step()
# Stop logging
run.stop()