How to Mock ROC AUC in Python

Compute ROC AUC from scratch in Python using pairwise comparisons between positive and negative score distributions, ideal for testing ML models without sklearn.

Medium Python 3.8+ Aug 9, 2026 ML engineering pipelines 12 views 0 copies

Python code

33 lines
Python 3.8+
import random
from math import comb


def mock_roc_auc(scores, labels):
    """Compute mock ROC AUC by simulating a classifier's score distribution."""
    random.seed(42)
    n = len(labels)
    pos_scores = [scores[i] for i in range(n) if labels[i] == 1]
    neg_scores = [scores[i] for i in range(n) if labels[i] == 0]

    auc = sum(
        1 if p > n_score else 0.5 if p == n_score else 0
        for p in pos_scores
        for n_score in neg_scores
    ) / (len(pos_scores) * len(neg_scores))
    return auc


scores = [random.uniform(0, 1) for _ in range(10)]
labels = [1, 0, 1, 0, 1, 0, 1, 0, 1, 0]
auc = mock_roc_auc(scores, labels)
print(f"Mock ROC AUC: {auc:.4f} (scores={[round(s, 2) for s in scores]})")

# Also compute with rank-based method (Mann-Whitney U statistic equivalent)
scores2 = [0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1, 0.0]
labels2 = [1, 1, 0, 1, 0, 0, 1, 0, 0, 0]  # 4 positives, 6 negatives
auc2 = sum(
    1 if scores2[i] > scores2[j] else 0.5 if scores2[i] == scores2[j] else 0
    for i in range(len(labels2)) if labels2[i] == 1
    for j in range(len(labels2)) if labels2[j] == 0
) / (sum(labels2) * (len(labels2) - sum(labels2)))
print(f"Rank-based AUC: {auc2:.4f}")

Output

stdout
Mock ROC AUC: 0.6250 (scores=[0.6394, 0.0250, 0.2750, 0.2230, 0.7365, 0.6767, 0.8922, 0.0869, 0.4219, 0.0298])
Rank-based AUC: 0.6667

How it works

The function computes AUC by comparing every positive-class score against every negative-class score. A positive score higher than a negative one contributes 1, ties contribute 0.5, and losses contribute 0 — the average of all comparisons is the AUC. The rank-based method uses the same pairwise logic but with a fixed, sorted score list to verify correctness. This 'from-scratch' approach avoids heavy dependencies and gives you full control over tie-handling in your ML evaluation pipeline.

Common mistakes

  • Forgetting to handle ties (equal scores) — the 0.5 contribution is essential for correct AUC
  • Using random scores without a fixed seed makes output non-reproducible in tests
  • Dividing by zero when either class is empty in the dataset
  • Confusing positive/negative label order — AUC depends on which class is treated as positive

Variations

  1. Use sklearn.metrics.roc_auc_score for a production-ready implementations when numpy/scikit-learn are available
  2. Implement using rank-based Mann-Whitney U statistic with sorted scores for O(n log n) complexity

Real-world use cases

  • Unit testing model scoring logic without a full ML framework installed in CI environments
  • Validating a custom scoring function's discrimination power during feature engineering iterations
  • Quickly benchmarking a classic ML experiment in a lightweight serverless function where heavy dependencies are avoided.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from ML engineering pipelines

Related tutorials and quizzes for this topic.