import numpy as np import torch from PIL.Image import Image import DataLoader from DataLoader import get_image_loader from Net import ImageNN # 01.05.22 -- 0.5h from netio import save_model, load_model, eval_evalset def get_train_device(): device = 'cuda' if torch.cuda.is_available() else 'cpu' print(f'Device to train net: {device}') return torch.device(device) def train_model(): # Set a known random seed for reproducibility np.random.seed(0) torch.manual_seed(0) device = get_train_device() # Load datasets train_loader, test_loader = get_image_loader("training/", precision=np.float32) nn = ImageNN(n_in_channels=3, precision=np.float32) # todo net params nn.train() # init with train mode nn.to(device) # send net to device available optimizer = torch.optim.AdamW(nn.parameters(), lr=0.1, weight_decay=1e-5) # todo adjust parameters and lr loss_function = torch.nn.MSELoss() loss_function.to(device) n_epochs = 7 # todo epcchs here train_sample_size = len(train_loader) losses = [] best_eval_loss = np.inf for epoch in range(n_epochs): print(f"Epoch {epoch}/{n_epochs}\n") i = 0 for input_tensor, target_tensor in train_loader: output = nn(input_tensor.to(device)) # get model output (forward pass) loss = loss_function(output.to(device), target_tensor.to(device)) # compute loss given model output and true target loss.backward() # compute gradients (backward pass) optimizer.step() # perform gradient descent update step optimizer.zero_grad() # reset gradients losses.append(loss.item()) i += train_loader.batch_size print( f'\rTraining epoch {epoch} [{i}/{train_sample_size * train_loader.batch_size}] (curr loss: {loss.item():.3})', end='') # eval model every 3000th sample if i % 3000 == 0: print(f"\nEvaluating model") eval_loss = eval_model(nn, test_loader, loss_function, device) print(f"Evalution loss={eval_loss}") if eval_loss < best_eval_loss: best_eval_loss = eval_loss save_model(nn) nn.train() # evaluate model with submission pkl file eval_evalset() # func to evaluate our trained model def eval_model(model: torch.nn.Module, dataloader: torch.utils.data.DataLoader, loss_fn, device: torch.device): # switch to eval mode model.eval() loss = .0 # disable gradient calculations with torch.no_grad(): i = 0 for input, target in dataloader: input = input.to(device) target = target.to(device) out = model(input) loss += loss_fn(out, target).item() print(f'\rEval prog[{i}/{len(dataloader) * dataloader.batch_size}]', end='') i += dataloader.batch_size print() loss /= len(dataloader) return loss if __name__ == '__main__': train_model()