Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
| """Far-Field ASR Score (FFAS): harmonic mean of smooth per-condition accuracies.""" | |
| from __future__ import annotations | |
| from typing import Optional, Sequence | |
| def ffas_harmonic(values: Sequence[float], weights: Optional[Sequence[float]] = None) -> float: | |
| """ | |
| Weighted harmonic mean of positive smooth scores in (0, 1]; higher is better. | |
| Used for per-scenario accuracies and optional speed/RTF terms. | |
| """ | |
| if not values: | |
| raise ValueError("values must contain at least one entry") | |
| if any(v <= 0 for v in values): | |
| raise ValueError("values must be positive") | |
| if weights is None: | |
| weights = [1.0] * len(values) | |
| elif len(weights) != len(values): | |
| raise ValueError("weights and values must have the same length") | |
| weighted_recip_sum = sum(w / v for w, v in zip(weights, values)) | |
| return sum(weights) / weighted_recip_sum | |
| def smooth_speed_from_rtf(rtf: float) -> float: | |
| """Map RTF (audio sec / infer sec, higher = faster) to a smooth score in (0, 1].""" | |
| if rtf < 0 or rtf != rtf: # NaN | |
| raise ValueError("RTF must be a non-negative finite number") | |
| r = float(rtf) | |
| return r / (1.0 + r) | |
| def ffas(wers: Sequence[float], weights: Optional[Sequence[float]] = None) -> float: | |
| """ | |
| Far-Field ASR Score (FFAS): harmonic mean of smooth accuracies. | |
| Each WER is mapped to accuracy via A = 1 / (1 + WER), bounded in (0, 1]. | |
| Handles WER > 1 gracefully (never collapses to 0). The final score is | |
| the (weighted) harmonic mean of accuracies across all conditions. | |
| Args: | |
| wers: WER values for each condition (non-negative). | |
| weights: Optional weights, same length as wers. Defaults to equal. | |
| Returns: | |
| FFAS score in (0, 1]. Higher is better. | |
| """ | |
| if not wers: | |
| raise ValueError("wers must contain at least one value") | |
| if any(w < 0 for w in wers): | |
| raise ValueError("WER values must be non-negative") | |
| accs = [1.0 / (1.0 + wer) for wer in wers] | |
| return ffas_harmonic(accs, weights) | |
| def robustness(wer_anechoic: float, wer_degraded: float) -> float: | |
| """ | |
| Companion metric: how gracefully the model degrades. | |
| Returns A_degraded / A_anechoic. Closer to 1.0 = more robust. | |
| """ | |
| a_an = 1.0 / (1.0 + wer_anechoic) | |
| a_deg = 1.0 / (1.0 + wer_degraded) | |
| return a_deg / a_an | |