glaucoma-api-idsc / uncertainty.py
muhammadhabibna's picture
Deploy: Full IDSC_D4 Pipeline, 1000 MC Dropout & Quality-Weighted Patient Aggregation
7d11de9
Raw
History Blame Contribute Delete
2.32 kB
"""
uncertainty.py
Monte Carlo Dropout uncertainty estimation.
Exact implementation from [IDSC]_D4.ipynb Cell 11.
"""
import torch
import torch.nn as nn
import numpy as np
from typing import Tuple
UNCERTAINTY_THRESHOLD = 0.05 # From notebook: UNCERTAINTY_THRESHOLD = 0.05
MC_SAMPLES = 1000 # Updated to 1000 samples for prediction
def enable_dropout(model: nn.Module):
"""
Enable dropout layers during inference for MC Dropout.
(Sets all Dropout modules to training mode.)
"""
for m in model.modules():
if isinstance(m, nn.Dropout):
m.train()
def mc_dropout_predict(model: nn.Module,
x_tensor: torch.Tensor,
n_samples: int = MC_SAMPLES,
device: str = 'cpu') -> Tuple[float, float, np.ndarray]:
"""
Run model n_samples forward passes with dropout active.
Args:
model: MLPClassifier with dropout layers
x_tensor: input feature tensor shape (1, input_dim)
n_samples: number of MC passes (default 1000)
device: 'cpu' or 'cuda'
Returns:
mean_prob: float, mean prediction probability
variance: float, prediction variance (= uncertainty)
all_preds: np.ndarray shape (n_samples,)
"""
x_tensor = x_tensor.to(device)
model.eval()
enable_dropout(model) # activate dropout
with torch.no_grad():
# Duplicate the input n_samples times to run as a single batch
x_batch = x_tensor.repeat(n_samples, 1)
# Forward pass for all samples at once
preds = model(x_batch).cpu().numpy().flatten()
mean_prob = float(preds.mean())
variance = float(preds.var())
return mean_prob, variance, preds
def interpret_uncertainty(variance: float) -> dict:
"""
Interpret the uncertainty level for display.
"""
is_ambiguous = variance > UNCERTAINTY_THRESHOLD
level = 'HIGH' if variance > 0.10 else ('MEDIUM' if variance > 0.05 else 'LOW')
return {
'variance': round(variance, 6),
'threshold': UNCERTAINTY_THRESHOLD,
'is_ambiguous': is_ambiguous,
'uncertainty_level': level,
'uncertainty_pct': round(min(variance / 0.15, 1.0) * 100, 1), # 0–100% for UI
'refer_to_specialist': is_ambiguous,
}