Configurer les statistiques

Les statistiques sont les valeurs au niveau de l'exécution qu'un évaluateur expose à partir de ses scores par enregistrement : une moyenne, un total, un percentile ou une métrique de classification telle que le F1. Ce sont celles que vous voyez dans l'en-tête du tableau d'exécutions, dans les graphiques au fil du temps, et que vous ciblez avec un objectif.

Par défaut, un évaluateur calcule l’ensemble historique (avg, min, max, std, count). Déclarez statistics si vous voulez un autre ensemble : un nombre total d’échecs, des percentiles de latence ou aucune statistique.

Chaque statistique déclarée est une déclaration sérialisable comprise par le SDK, le backend et Studio. Elle peut donc être recalculée après filtrage ou réévaluation, représentée dans un graphique, comparée et contrôlée par un objectif.

Exemple rapide

Exemple rapide

from mistralai.evaluations import Evaluator, Goal, Statistic

Evaluator(
    name="latency_ms",
    description="End-to-end response time in milliseconds.",
    scorer=latency_scorer,
    statistics=[
        Statistic.percentile(95, goal=Goal.lte(500)),
        Statistic.percentile(50),
        Statistic.percentile(75),
    ],
)
Les factories

Les factories

La factory Statistic déclare chaque réduction intégrée :

MéthodeSignificationID
Statistic.avg()Moyenne arithmétique des scores numériquesavg
Statistic.sum()Somme des scores numériques (par exemple, un nombre total d’échecs)sum
Statistic.min()Plus petit score numériquemin
Statistic.max()Plus grand score numériquemax
Statistic.std()Écart type de la populationstd
Statistic.count()Nombre de scores numériques réussis et non nulscount
Statistic.percentile(p)Le percentile p, 0 <= p <= 100p50, p95, p99.9, …

Chaque ID est canonique et stable : avg, sum, min, max, std, count et p{p} pour les percentiles (p50, p95). Les ID servent à référencer une statistique dans le SDK, la payload d’exécution et l’interface. Ils ne changent donc jamais une fois déclarés. Une médiane correspond à Statistic.percentile(50) — il n’existe pas de factory distincte pour elle.

Il n’existe volontairement pas de réduction rate : un taux correspond à avg sur des scores 0/1.

Omission ou liste explicite

Omission ou liste explicite

Le champ statistics a deux modes :

  • Omis (par défaut) — le comportement historique est conservé. Studio détecte le type de score et, pour les scores numériques, expose l’ensemble par défaut avg, min, max, std, count.
  • Une liste explicite — fait autorité. Seules ces statistiques sont calculées et exposées, dans l’ordre indiqué, sans ajout de valeurs par défaut implicites. Une liste vide statistics=[] signifie que l’évaluateur n’expose aucune statistique au niveau de l’exécution.

La première entrée de la liste effective est la statistique principale de l’évaluateur : la valeur unique affichée dans l’en-tête du tableau des exécutions pour une présentation compacte. Il s’agit d’une convention d’affichage, pas d’une option persistée.

Exemples

Exemples

Ensemble par défaut (omission)

Ensemble par défaut (omission)

Omettre statistics conserve l’ensemble par défaut :

Evaluator(name="quality", scorer=quality_scorer)
# exposes avg, min, max, std, count — avg is the headline
Total des échecs

Total des échecs

Un évaluateur dont la fonction de scoring renvoie 0/1 par enregistrement, expose uniquement le nombre total d’échecs et impose un seuil à zéro :

from mistralai.evaluations import Evaluator, Goal, Statistic

Evaluator(
    name="failures",
    description="1 when the record failed, 0 otherwise.",
    scorer=failure_scorer,  # returns numeric 0 or 1
    statistics=[Statistic.sum(goal=Goal.lte(0))],
)

sum additionne les scores 0/1, et son objectif fait échouer l’exécution si un enregistrement a échoué.

Percentiles de latence

Percentiles de latence

from mistralai.evaluations import Evaluator, Goal, Statistic

Evaluator(
    name="latency_ms",
    description="End-to-end response time in milliseconds.",
    scorer=latency_scorer,
    statistics=[
        Statistic.percentile(95, goal=Goal.lte(500)),
        Statistic.percentile(50),
        Statistic.percentile(75),
    ],
)

Cela expose exactement p50, p75 et p95 — pas de avg, min, max, std ni count. Comme p95 est en premier, il devient la statistique principale affichée dans l’en-tête du tableau des exécutions, et son Goal.lte(500) fait échouer l’exécution lorsque la latence au 95e percentile dépasse 500 ms.

Statistiques de classification

Statistiques de classification

precision, recall et f1 proviennent d'une matrice de confusion sur les paires d'étiquettes (expected, predicted), ils nécessitent donc deux étiquettes par enregistrement. L'étiquette prédite est la value du score. L'étiquette attendue est lue dans les metadata du score, sous expected_key (par défaut "expected").

MéthodeSignificationID
Statistic.precision(...)Précision (valeur prédictive positive)precision, precision_macro, …
Statistic.recall(...)Rappel (taux de vrais positifs)recall, recall_micro, …
Statistic.f1(...)F1, la moyenne harmonique de la précision et du rappelf1, f1_weighted, …

Chaque fabrique prend exactement un des arguments suivants :

  • positive_label : une métrique binaire, calculée par rapport à cette seule classe.
  • average : une métrique multi-classes, moyennée avec "macro", "micro" ou "weighted".

Les deux modes acceptent également les arguments optionnels expected_key, labels et goal.

Binaire

Binaire

from mistralai.evaluations import Evaluator, Score, Statistic

def scorer(ctx) -> Score:
    # value: the model's prediction; metadata["expected"]: the ground-truth label
    return Score(value=ctx.output, metadata={"expected": ctx.input_record["expected"]})

Evaluator(
    name="spam_classifier",
    scorer=scorer,
    statistics=[
        Statistic.f1(positive_label="spam"),  # headline
        Statistic.precision(positive_label="spam"),
        Statistic.recall(positive_label="spam"),
    ],
)

Les étiquettes sont des scores catégoriels, donc l'évaluateur obtient aussi les fréquences de prédiction. Studio affiche les métriques à côté de la matrice de confusion à partir de laquelle elles ont été calculées, et additionne les matrices entre les exécutions pour agréger les métriques dans la liste des exécutions.

Multi-classes

Multi-classes

statistics=[
    Statistic.f1(average="macro"),            # id: f1_macro
    Statistic.precision(average="weighted"),  # id: precision_weighted
    Statistic.recall(average="micro"),        # id: recall_micro
]

Les moyennes macro et weighted dépendent des classes présentes. Passez labels pour fixer l'ensemble des classes, par exemple Statistic.f1(average="macro", labels=["fr", "en", "de"]), afin que la valeur reste comparable quand un filtre retire tous les enregistrements d'une classe.

Métriques non définies et étiquettes manquantes

Métriques non définies et étiquettes manquantes

  • Une métrique est null (affichée comme -) quand son dénominateur est nul, par exemple la précision quand le modèle ne prédit jamais la classe positive.
  • Un score sans étiquette attendue dans ses métadonnées ne peut pas entrer dans la matrice de confusion. Il est exclu des métriques et compté dans excluded_count, affiché dans Studio à côté du nombre d'enregistrements scorés.

Pour l'exactitude, vous n'avez pas besoin d'une statistique de classification : attribuez un score de 1 quand la prédiction correspond à l'étiquette attendue et 0 sinon, puis déclarez Statistic.avg().

Objectifs au niveau des statistiques

Objectifs au niveau des statistiques

Un objectif associé à une statistique cible cette statistique — à la fois au niveau de l’enregistrement et de l’agrégation de l’exécution. C’est la méthode recommandée pour contrôler une exécution et remplacer aggregate_goal :

# Recommended
Evaluator(
    name="accuracy",
    scorer=accuracy_scorer,
    statistics=[Statistic.avg(goal=Goal.gte(0.9))],
)

# Deprecated — prefer a statistic-level goal
Evaluator(
    name="accuracy",
    scorer=accuracy_scorer,
    aggregate_goal=Goal.gte(0.9),
)

Un objectif au niveau d’une statistique ne porte jamais son propre metric : la cible est la statistique à laquelle il est associé. (Seul le chemin obsolète aggregate_goal utilise metric pour nommer une statistique.)

Les scores doivent être numériques 0/1, pas booléens

Les scores doivent être numériques 0/1, pas booléens

Les réductions numériques nécessitent des scores numériques. Un évaluateur qui se base sur réussite/échec doit émettre 0 ou 1 numériques, pas True/False. Les booléens sont classés comme valeurs catégorielles, donc un scorer qui renvoie un booléen produit des statistiques catégorielles (fréquences et mode) et aucune des réductions numériques ci-dessus ne s'applique.

def failure_scorer(ctx) -> int:
    return 1 if failed(ctx) else 0   # numeric — correct

def failure_scorer(ctx) -> bool:
    return failed(ctx)               # boolean — categorical, no sum/percentile
L’algorithme de percentile

L’algorithme de percentile

Statistic.percentile(p) utilise l’algorithme Hyndman-Fan type-7 (valeur par défaut de NumPy). Pour des scores triés x de longueur n et un rang h = (n - 1) * p / 100, le résultat interpole linéairement entre x[floor(h)] et x[ceil(h)] ; un score unique renvoie ce score. Le même algorithme s’exécute dans le SDK Python, le SDK TypeScript et le backend. Les mêmes scores produisent donc toujours la même valeur.

Échantillons vides

Échantillons vides

Lorsqu’aucun score numérique réussi n’alimente le calcul, un count déclaré vaut 0 et toutes les autres statistiques déclarées valent null (non évaluables). Un ensemble de données vide ne peut donc jamais satisfaire par accident un objectif comme Statistic.sum(goal=Goal.lte(0)).