The training loop is logically split into two sections: model.train() and model.eval(). Note the placement of the following lines of code:
from tqdm import tqdmfor epoch in range(1, epochs + 1): running_loss = 0.0 running_corrects = 0 model.train() # turn on training mode for x, y in tqdm(train_dl): # thanks to our wrapper, we can intuitively iterate over our data! opt.zero_grad() preds = model(x) loss = loss_func(preds, y) loss.backward() opt.step() running_loss += loss.item() * x.size(0) epoch_loss = running_loss / len(trn) # calculate the validation loss for this epoch val_loss = 0.0 model.eval() # turn on evaluation mode for x, y in valid_dl: preds = model(x) loss = loss_func(preds, y) val_loss += loss.item() * x.size(0) ...