| import torch |
| import torch.nn as nn |
| import torch.optim as optim |
| import torch.nn.functional as F |
| from tqdm import tqdm |
| import numpy as np |
|
|
| |
| def train_model(model, train_loader, epochs=10, device=None): |
| |
| if device is None: |
| device = torch.device("cuda" if torch.cuda.is_available() else "cpu") |
| |
| model.to(device) |
| optimizer = optim.AdamW(model.parameters(), lr=1e-4) |
| criterion = nn.MSELoss() |
|
|
| for epoch in range(epochs): |
| model.train() |
| total_loss = 0 |
| for images, _ in tqdm(train_loader, desc=f"Epoch {epoch+1}"): |
| images = images.to(device) |
| optimizer.zero_grad() |
| |
| reconstructed = model(images) |
| loss = criterion(reconstructed, images) |
| |
| loss.backward() |
| optimizer.step() |
| total_loss += loss.item() |
| |
| print(f"Epoch {epoch+1} complete. Avg Loss: {total_loss/len(train_loader):.6f}") |
|
|
| |
| def evaluate_anomaly(model, test_loader, device=None): |
| if device is None: |
| device = torch.device("cuda" if torch.cuda.is_available() else "cpu") |
| |
| model.eval() |
| errors = [] |
| labels = [] |
| |
| print("Computing anomaly scores (Peak Score Method)...") |
| with torch.no_grad(): |
| for images, label in tqdm(test_loader): |
| images = images.to(device) |
| reconstructed = model(images) |
| |
| |
| diff = (images - reconstructed)**2 |
| |
| |
| diff_map = torch.mean(diff, dim=1, keepdim=True) |
| |
| |
| |
| smoothed_diff = F.avg_pool2d(diff_map, kernel_size=15, stride=1, padding=7) |
| |
| |
| batch_error, _ = torch.max(smoothed_diff.view(images.size(0), -1), dim=1) |
| |
| errors.extend(batch_error.cpu().numpy()) |
| labels.extend(label.numpy()) |
| |
| return errors, labels |