arcisvlm / evaluation /adaptation_eval.py
Hardik Sanghvi
feat: integrate Gemma 4 E2B backbone for production-quality VLM inference
7a564e3
Raw
History Blame Contribute Delete
3.34 kB
"""
Adaptation Evaluation — measures per-camera LoRA quality vs static routing.
Metrics:
- Per-camera decode loss (adapted vs base)
- Adaptation improvement percentage
- Confidence calibration quality
- Adapter diversity (how different are adapters for different cameras?)
Used by scripts/eval_adaptation.py — this module provides the core evaluation
functions without the CLI/checkpoint-loading boilerplate.
"""
from __future__ import annotations
from typing import Optional
import torch
import torch.nn.functional as F
def compute_adaptation_improvement(
base_loss: float,
adapted_loss: float,
) -> float:
"""Compute improvement percentage: positive means adapted is better."""
if base_loss == 0:
return 0.0
return (base_loss - adapted_loss) / base_loss * 100
def compute_adapter_diversity(
adapter_params: list[torch.Tensor],
) -> dict[str, float]:
"""
Measure how diverse the generated adapters are across cameras.
Low diversity suggests the hypernetwork is ignoring conditioning.
Args:
adapter_params: List of flat LoRA param tensors (one per camera)
Returns:
Dict with mean_cosine_sim (lower = more diverse), std, min, max
"""
if len(adapter_params) < 2:
return {"mean_cosine_sim": 0.0, "std": 0.0, "min": 0.0, "max": 0.0}
# Stack and compute pairwise cosine similarity
stacked = torch.stack(adapter_params) # [N, params]
stacked_norm = F.normalize(stacked, dim=-1)
sim_matrix = stacked_norm @ stacked_norm.T # [N, N]
# Get upper triangle (exclude diagonal)
mask = torch.triu(torch.ones_like(sim_matrix, dtype=torch.bool), diagonal=1)
pairwise_sims = sim_matrix[mask]
return {
"mean_cosine_sim": pairwise_sims.mean().item(),
"std": pairwise_sims.std().item(),
"min": pairwise_sims.min().item(),
"max": pairwise_sims.max().item(),
}
def compute_calibration_quality(
confidences: list[float],
errors: list[float],
n_bins: int = 10,
) -> dict[str, float]:
"""
Measure calibration quality: does confidence predict actual accuracy?
Uses Expected Calibration Error (ECE) — lower is better.
Args:
confidences: List of confidence scores [0, 1]
errors: List of actual error values (lower = better prediction)
Returns:
Dict with ece, mean_confidence, mean_error
"""
if not confidences:
return {"ece": 0.0, "mean_confidence": 0.0, "mean_error": 0.0}
conf_t = torch.tensor(confidences)
err_t = torch.tensor(errors)
# Convert errors to accuracy (1 - normalized_error)
max_err = err_t.max()
if max_err > 0:
accuracy = 1.0 - err_t / max_err
else:
accuracy = torch.ones_like(err_t)
# Bin by confidence
bin_boundaries = torch.linspace(0, 1, n_bins + 1)
ece = 0.0
for i in range(n_bins):
mask = (conf_t >= bin_boundaries[i]) & (conf_t < bin_boundaries[i + 1])
if mask.sum() > 0:
bin_conf = conf_t[mask].mean()
bin_acc = accuracy[mask].mean()
ece += mask.float().mean() * abs(bin_conf - bin_acc)
return {
"ece": ece.item(),
"mean_confidence": conf_t.mean().item(),
"mean_error": err_t.mean().item(),
"mean_accuracy": accuracy.mean().item(),
}