Classification Applications › Evaluation and Metrics

Michael BrenndoerferFebruary 22, 20266 min read
Language AI HandbookAll chapters
Part 63 of 67LLM Applications
Chapter 482Classification Applications › Evaluation and Metrics
Reading section 7 of 10 · Evaluation and Metrics · 6 minSection 7 of 10 · 6 min

Book contents

Section 7 of 10 · 6 min read

Classification Applications › Evaluation and MetricsOne section · Sections in this chapter7 / 10 ↓
Reading tools Definitions & inline links

Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.

Article links

Make inline references clickable

Classification evaluation requires care about which metrics you report and what they mean.

Accuracy and Its Limitations

Accuracy, the fraction of correct predictions, is the most natural metric but fails in two important ways.

First, it treats all errors equally. Misclassifying a fraud report as an account inquiry has far higher cost than misclassifying an account inquiry as a fraud report. Applications with asymmetric error costs need weighted or asymmetric metrics.

Second, accuracy is misleading for imbalanced datasets. A classifier that always predicts the majority class in a 95/5 imbalance achieves 95% accuracy. That number is meaningless as an evaluation of the classifier's utility.

The combination of these two failures makes accuracy a particularly poor guide for systems where the economically important class is the rare one. In fraud detection, spam filtering, medical diagnosis, and content moderation, the class that matters is almost always the minority class. Reporting accuracy in these settings creates a false sense of security: a model with 98% accuracy can still be missing 40% of fraud cases.

Precision, Recall, and F1

The standard alternative to accuracy is the precision-recall family of metrics, evaluated per class and then aggregated.

For a class cc:

Precisionc=TPcTPc+FPc\text{Precision}_c = \frac{\text{TP}_c}{\text{TP}_c + \text{FP}_c} Recallc=TPcTPc+FNc\text{Recall}_c = \frac{\text{TP}_c}{\text{TP}_c + \text{FN}_c} F1c=2⋅Precisionc⋅RecallcPrecisionc+RecallcF_1^c = \frac{2 \cdot \text{Precision}_c \cdot \text{Recall}_c}{\text{Precision}_c + \text{Recall}_c}

where:

  • TPc\text{TP}_c (True Positives): examples correctly predicted as class cc
  • FPc\text{FP}_c (False Positives): examples of other classes incorrectly predicted as class cc
  • FNc\text{FN}_c (False Negatives): examples of class cc incorrectly predicted as another class

Precision measures how often the model is right when it fires on class cc. Recall measures what fraction of the true class cc examples the model retrieves. F1 is their harmonic mean, penalizing models that sacrifice one to maximize the other. Note that Precision and Recall trade off: raising the decision threshold increases Precision but decreases Recall, and vice versa.

The harmonic mean matters here. If a model achieves 100% precision by predicting the positive class on only one example and getting it right, its F1 will be near zero because recall is near zero. If it achieves 100% recall by predicting positive for every example, its F1 will be low because precision will be near the base rate. F1 rewards balanced performance, which is usually what you want.

The macro-average F1 averages the per-class F1 scores with equal weight:

Macro-F1=1C∑c=1CF1c\text{Macro-F1} = \frac{1}{C} \sum_{c=1}^{C} F_1^c

The weighted-average F1 weights each class by its support (number of examples):

Weighted-F1=∑c=1Cnc⋅F1c∑c=1Cnc\text{Weighted-F1} = \frac{\sum_{c=1}^{C} n_c \cdot F_1^c}{\sum_{c=1}^{C} n_c}

where ncn_c is the number of examples in class cc. Macro-F1 is more informative for imbalanced datasets because it gives equal importance to rare classes. Weighted-F1 reflects overall system performance weighted by class frequency.

The choice between macro and weighted F1 is a business decision disguised as a technical one. Weighted-F1 tells you how the system performs on average traffic. Macro-F1 tells you how the system performs on each category equally. If the rare categories (fraud, critical safety issues) are the ones that matter most, macro-F1 is the right headline metric, even though it is sensitive to performance on categories with very few examples.

In[22]:
Code
import numpy as np

# Simulate classifier predictions on a 4-class problem with imbalance
np.random.seed(42)

# True labels: imbalanced distribution
true_labels = (
    ["check_balance"] * 80
    + ["transfer_funds"] * 50
    + ["pay_bill"] * 40
    + ["report_fraud"] * 15
)

# Simulate predictions with class-specific error rates
# Fraud detection is harder (fewer examples, higher confusion)
predicted_labels = []
error_rates = {
    "check_balance": 0.05,
    "transfer_funds": 0.10,
    "pay_bill": 0.12,
    "report_fraud": 0.25,
}

confusion_pairs = {
    "check_balance": "transfer_funds",
    "transfer_funds": "check_balance",
    "pay_bill": "check_balance",
    "report_fraud": "transfer_funds",
}

for label in true_labels:
    if np.random.random() < error_rates[label]:
        predicted_labels.append(confusion_pairs[label])
    else:
        predicted_labels.append(label)
Out[23]:
Console
Classification Report:
                precision    recall  f1-score   support

 check_balance       0.88      0.94      0.91        80
      pay_bill       1.00      0.88      0.93        40
  report_fraud       1.00      0.67      0.80        15
transfer_funds       0.82      0.90      0.86        50

      accuracy                           0.89       185
     macro avg       0.93      0.84      0.87       185
  weighted avg       0.90      0.89      0.89       185

Overall accuracy: 0.892

The classification report reveals what overall accuracy hides: the fraud detection class (report_fraud) has significantly lower recall than the other classes because it has fewer training examples and higher confusion with other intents. The overall accuracy of approximately 90% looks reasonable, but the fraud recall of approximately 75% means one in four fraud reports is miscategorized. Whether that is acceptable depends on the application's risk tolerance, but reporting accuracy alone would have obscured this critical gap entirely.

The FβF_\beta Generalization

When recall and precision are not equally important, you can generalize F1 to weight one more heavily than the other using the FβF_\beta metric:

Fβ=(1+β2)⋅Precision⋅Recall(β2⋅Precision)+RecallF_\beta = (1 + \beta^2) \cdot \frac{\text{Precision} \cdot \text{Recall}}{(\beta^2 \cdot \text{Precision}) + \text{Recall}}

where:

  • β>1\beta > 1: weights recall more heavily than precision (useful when missing positives is costly, as in fraud or medical screening)
  • β<1\beta < 1: weights precision more heavily than recall (useful when false positives are costly, as in content recommendation or legal document review)
  • β=1\beta = 1: the standard F1 metric, treating precision and recall equally

In fraud detection, you might use F2F_2 to ensure the metric penalizes misses more than false alarms. In spam filtering, where users strongly object to legitimate email being marked as spam, you might use F0.5F_{0.5} to penalize false positives more. The β\beta parameter makes the business tradeoff explicit and encodes it directly into the metric.

Key Parameters

The key modeling parameters for text classification systems are:

  • model: The pre-trained backbone to fine-tune. distilbert-base-uncased-finetuned-sst-2-english is fast and suitable for binary sentiment. For zero-shot classification, cross-encoder/nli-deberta-v3-small is compact and efficient; facebook/bart-large-mnli is larger and often more accurate but requires a 1.6GB download. For fine-tuning, bert-base-uncased or roberta-base are standard starting points.
  • device: The compute backend for inference. -1 forces CPU; use 0 for GPU when available. GPU inference is typically 10-30x faster for transformer models.
  • OOS_THRESHOLD: The confidence floor for out-of-scope rejection in intent detection. Values between 0.4 and 0.6 are typical; tune on a held-out OOS development set.
  • ngram_range: For TF-IDF classifiers, (1, 2) includes unigrams and bigrams, capturing local negation patterns. Extending to (1, 3) rarely helps and increases feature space substantially.
  • C (logistic regression): The inverse regularization strength. Smaller values produce stronger regularization. C=1.0 is a reasonable default; reduce to 0.1 for small datasets to prevent overfitting.
  • class_weight: Set to 'balanced' in LogisticRegression or LinearSVC to automatically upweight rare classes proportional to their inverse frequency.