SPACE / src /training /losses.py
e-cagan's picture
Deploy AUGUR
c679d56
Raw
History Blame Contribute Delete
3.01 kB
"""
Module for custom loss functions.
"""
import torch
import torch.nn as nn
import torch.nn.functional as F
class MemAELoss(nn.Module):
"""MSE reconstruction + entropy regularization on attention weights."""
def __init__(self, entropy_weight: float = 0.0002):
super().__init__()
self.entropy_weight = entropy_weight # alpha
self.mse = nn.MSELoss()
def forward(self, recon, target, attn):
"""
Args:
recon: (B, T, C, H, W) reconstruction
target: (B, T, C, H, W) input
attn: (B, n_queries, N) attention weights
Returns:
total_loss, (recon_loss, entropy_loss) # ayrı logla
"""
eps = 1e-12
# Reconstruction
recon_loss = self.mse(recon, target)
# Entropy: per-query entropy, then mean
# E = mean( -sum_i ( w_i * log(w_i + eps) ) )
entropy = (-(attn * torch.log(attn + eps)).sum(dim=-1)).mean()
# Sum
total = recon_loss + self.entropy_weight * entropy
return total, (recon_loss, entropy)
class PredictionLoss(nn.Module):
"""Intensity (L2) + gradient loss for future frame prediction."""
def __init__(self, grad_weight: float = 1.0):
super().__init__()
self.grad_weight = grad_weight # lambda_grad
def forward(self, pred, target):
"""
Args:
pred: (B, 1, H, W) predicted frame
target: (B, 1, H, W) ground truth frame
Returns:
total, (intensity, gradient)
"""
# Intensity (L2)
intensity = F.mse_loss(pred, target)
# Gradient loss
## Horizontal (x) gradient (last axis = W)
pred_dx = torch.abs(pred[:, :, :, 1:] - pred[:, :, :, :-1])
target_dx = torch.abs(target[:, :, :, 1:] - target[:, :, :, :-1])
## Vertical (y) gradient (the axis before last = H)
pred_dy = torch.abs(pred[:, :, 1:, :] - pred[:, :, :-1, :])
target_dy = torch.abs(target[:, :, 1:, :] - target[:, :, :-1, :])
## loss: gradient differences
gradient = F.l1_loss(pred_dx, target_dx) + F.l1_loss(pred_dy, target_dy)
# Total
total = intensity + self.grad_weight * gradient
return total, (intensity, gradient)
if __name__ == "__main__":
# Smoke test
# loss_fn = MemAELoss()
# recon = torch.randn(2, 16, 1, 128, 128)
# target = torch.randn(2, 16, 1, 128, 128)
# attn = torch.softmax(torch.randn(2, 1024, 2000), dim=-1) # valid distribution
# total, (rl, ent) = loss_fn(recon, target, attn)
# print(f"total: {total.item():.4f}, recon: {rl.item():.4f}, entropy: {ent.item():.4f}")
# Prediction loss smoke test
loss_pred = PredictionLoss()
pred = torch.randn(2, 1, 128, 128)
target = torch.randn(2, 1, 128, 128)
total, (inten, grad) = loss_pred(pred, target)
print(f"total: {total.item():.4f}, intensity: {inten.item():.4f}, gradient: {grad.item():.4f}")