"""Confidence calculation and visualization utilities. Provides normalized softmax confidence and color-coded badges""" from typing import Tuple, List import numpy as np import torch import torch.nn.functional as F def calculate_softmax_confidence(logits: torch.Tensor) -> Tuple[np.ndarray, float, str, str]: """Calculate normalized confidence using softmax Args: logits: Raw model logits tensor Returns: Tuple of (probabilities, max_confidence, confidence_level, confidence_emoji) """ # ===Apply softmax to get probabilities=== probs_np = F.softmax(logits, dim=1).cpu().numpy().flatten() # ===Get maximum probability as confidence=== max_confidence = float(np.max(probs_np)) # ===Determine confidence level and emoji=== if max_confidence >= 0.80: confidence_level = "HIGH" confidence_emoji = "🟢" elif max_confidence >= 0.60: confidence_level = "MEDIUM" confidence_emoji = "🟡" else: confidence_level = "LOW" confidence_emoji = "🔴" return probs_np, max_confidence, confidence_level, confidence_emoji def get_confidence_badge(confidence: float) -> Tuple[str, str]: """Get confidence badge emoji and level description Args: confidence: Confidence value (0-1) Returns: Tuple of (emoji, level) """ if confidence >= 0.80: return "🟢", "HIGH" elif confidence >= 0.60: return "🟡", "MEDIUM" else: return "🔴", "LOW" def format_confidence_display(confidence: float, level: str, emoji: str) -> str: """ Format confidence for display in UI Args: confidence: Confidence value (0-1) level: Confidence level (HIGH/MEDIUM/LOW) emoji: Confidence emoji Returns: Formatted confidence string """ return f"{emoji} **{level}** ({confidence:.1%})" def create_confidence_progress_html( probabilities: np.ndarray, labels: List[str], highlight_idx: int ) -> str: """ Create HTML for confidence progress bars Args: probabilities: Array of class probabilities labels: List of class labels highlight_idx: Index of predicted class to highlight Returns: HTML string for progress bars """ if len(probabilities) == 0 or len(labels) == 0: return "
No confidence data available
" html_parts = [] for i, (prob, label) in enumerate(zip(probabilities, labels)): # ===Color based on whether this is the predicted class=== if i == highlight_idx: if prob >= 0.80: color = "#22c55e" # green-500 text_color = "#ffffff" elif prob >= 0.60: color = "#eab308" # yellow-500 text_color = "#000000" else: color = "#ef4444" # red-500 text_color = "#ffffff" else: color = "#e5e7eb" # gray-200 text_color = "#6b7280" # gray-500 percentage = prob * 100 html_parts.append(f"""