Train for one epoch.
(
feature_model: nn.Module,
linear_classifiers: AllClassifiers,
optimizer: torch.optim.Optimizer,
scheduler: torch.optim.lr_scheduler._LRScheduler,
criterion: nn.Module,
train_loader,
epoch: int,
epoch_length: int,
device: torch.device,
)
| 255 | |
| 256 | |
| 257 | def train_one_epoch( |
| 258 | feature_model: nn.Module, |
| 259 | linear_classifiers: AllClassifiers, |
| 260 | optimizer: torch.optim.Optimizer, |
| 261 | scheduler: torch.optim.lr_scheduler._LRScheduler, |
| 262 | criterion: nn.Module, |
| 263 | train_loader, |
| 264 | epoch: int, |
| 265 | epoch_length: int, |
| 266 | device: torch.device, |
| 267 | ) -> float: |
| 268 | """Train for one epoch.""" |
| 269 | linear_classifiers.train() |
| 270 | total_loss = 0.0 |
| 271 | num_batches = 0 |
| 272 | |
| 273 | progress_bar = tqdm(train_loader, total=epoch_length, desc=f"Epoch {epoch}") if is_main_process() else train_loader |
| 274 | |
| 275 | for batch_idx, (images, labels) in enumerate(progress_bar): |
| 276 | if batch_idx >= epoch_length: |
| 277 | break |
| 278 | |
| 279 | images = images.to(device, non_blocking=True) |
| 280 | labels = labels.to(device, non_blocking=True) |
| 281 | |
| 282 | features = feature_model(images) |
| 283 | outputs = linear_classifiers(features) |
| 284 | |
| 285 | losses = {f"loss_{k}": criterion(v, labels) for k, v in outputs.items()} |
| 286 | loss = sum(losses.values()) |
| 287 | |
| 288 | optimizer.zero_grad() |
| 289 | loss.backward() |
| 290 | optimizer.step() |
| 291 | scheduler.step() |
| 292 | |
| 293 | total_loss += loss.item() |
| 294 | num_batches += 1 |
| 295 | |
| 296 | if is_main_process() and batch_idx % 50 == 0: |
| 297 | progress_bar.set_postfix(loss=loss.item(), lr=optimizer.param_groups[0]["lr"]) |
| 298 | |
| 299 | return total_loss / max(num_batches, 1) |
| 300 | |
| 301 | |
| 302 | @torch.no_grad() |
no test coverage detected