Skip to main content
The ROCCurve class template computes Receiver Operating Characteristic (ROC) curves and Area Under the Curve (AUC) for binary classifiers. It operates on raw classifier scores rather than hard predictions, making it threshold-agnostic. Multi-class problems are supported via one-vs-rest.

Template parameters

Score
typename
default:"double"
Floating-point type of classifier output (e.g., float, double). Higher scores indicate higher confidence in the positive class.
Label
typename
default:"int"
Integer-like binary label type. Positive class = 1, negative class = 0 (or any other value).

Nested types

Point

struct Point {
    double fpr;  // False positive rate = FP / (FP + TN)
    double tpr;  // True positive rate = TP / (TP + FN)
};
Represents a single point on the ROC curve.

Constructor

explicit ROCCurve(const std::vector<Score>& scores,
                  const std::vector<Label>& labels,
                  Label                     pos_label = Label(1));
Computes the ROC curve for a binary classification problem.
scores
const std::vector<Score>&
Raw classifier outputs, length n_samples. Higher values indicate higher confidence in the positive class.
labels
const std::vector<Label>&
Ground-truth binary labels, length n_samples.
pos_label
Label
default:"Label(1)"
Value in labels that denotes the positive class.

Methods

curve

[[nodiscard]] const std::vector<Point>& curve() const noexcept;
Returns the computed ROC curve points.
return
const std::vector<Point>&
Ordered curve points from (0,0) to (1,1)
The curve is built by sorting samples in descending score order and sweeping the decision threshold from +∞ to -∞. Samples with tied scores are processed as a batch before emitting a curve point.

auc

[[nodiscard]] double auc() const noexcept;
Returns the Area Under the ROC Curve.
return
double
AUC score in range [0.0, 1.0]
Computed via the trapezoidal rule over curve points. AUC represents the probability that the classifier ranks a random positive sample higher than a random negative sample (Wilcoxon-Mann-Whitney statistic).

n_pos

[[nodiscard]] std::size_t n_pos() const noexcept;
return
std::size_t
Number of positive samples in the dataset

n_neg

[[nodiscard]] std::size_t n_neg() const noexcept;
return
std::size_t
Number of negative samples in the dataset

optimal_threshold

[[nodiscard]] Score optimal_threshold() const noexcept;
Returns the score threshold that maximizes the Youden J statistic.
return
Score
Optimal threshold value
This is the point on the curve closest to (FPR=0, TPR=1) by Euclidean distance, computed as argmax_t (TPR(t) - FPR(t)).

Static methods for multi-class

roc_ovr

[[nodiscard]] static std::vector<ROCCurve>
roc_ovr(const std::vector<std::vector<Score>>& scores,
        const std::vector<Label>&              labels,
        std::size_t                            n_classes);
Computes one-vs-rest ROC curves for a multi-class problem.
scores
const std::vector<std::vector<Score>>&
Score matrix, shape (n_samples, n_classes). scores[i][k] is the model’s confidence that sample i belongs to class k.
labels
const std::vector<Label>&
Integer class labels, length n_samples.
n_classes
std::size_t
Number of classes K.
return
std::vector<ROCCurve>
Vector of K ROCCurve objects, one per class
For each class k, constructs a binary problem treating class k as positive and all other classes as negative.

macro_auc

[[nodiscard]] static double
macro_auc(const std::vector<std::vector<Score>>& scores,
          const std::vector<Label>&              labels,
          std::size_t                            n_classes);
Computes the macro-average AUC across all classes.
scores
const std::vector<std::vector<Score>>&
Score matrix, shape (n_samples, n_classes).
labels
const std::vector<Label>&
Integer class labels, length n_samples.
n_classes
std::size_t
Number of classes K.
return
double
Unweighted mean of per-class AUC scores

Example usage

Binary classification

#include <mlpp/model_validation/roc_curve.hpp>

using namespace mlpp::model_validation;

// Classifier scores and true labels
std::vector<double> scores = {0.9, 0.8, 0.7, 0.6, 0.55, 0.4, 0.3, 0.2};
std::vector<int>    labels = {1,   1,   0,   1,   0,    0,   1,   0};

// Compute ROC curve
ROCCurve<double, int> roc(scores, labels, 1);

std::cout << "AUC: " << roc.auc() << std::endl;
std::cout << "Optimal threshold: " << roc.optimal_threshold() << std::endl;
std::cout << "Positive samples: " << roc.n_pos() << std::endl;
std::cout << "Negative samples: " << roc.n_neg() << std::endl;

// Print curve points
for (const auto& pt : roc.curve()) {
    std::cout << "FPR: " << pt.fpr << ", TPR: " << pt.tpr << std::endl;
}

Multi-class classification (one-vs-rest)

#include <mlpp/model_validation/roc_curve.hpp>

using namespace mlpp::model_validation;

// Score matrix: each row is a sample, each column is a class
std::vector<std::vector<double>> scores = {
    {0.7, 0.2, 0.1},  // sample 0: class 0 most confident
    {0.1, 0.8, 0.1},  // sample 1: class 1 most confident
    {0.2, 0.1, 0.7},  // sample 2: class 2 most confident
    {0.6, 0.3, 0.1},
    {0.1, 0.7, 0.2}
};

std::vector<int> labels = {0, 1, 2, 0, 1};

// Compute per-class ROC curves
auto roc_curves = ROCCurve<double, int>::roc_ovr(scores, labels, 3);

for (size_t k = 0; k < roc_curves.size(); ++k) {
    std::cout << "Class " << k << " AUC: " << roc_curves[k].auc() << std::endl;
}

// Compute macro-average AUC
double macro = ROCCurve<double, int>::macro_auc(scores, labels, 3);
std::cout << "Macro-average AUC: " << macro << std::endl;

Implementation notes

Tie handling: All samples with the same score are processed as a batch before emitting a curve point. This matches scikit-learn’s convention and prevents artificially jagged curves. AUC computation: Uses the trapezoidal rule. For continuous scores with no ties, this is exact. For discrete scores, it provides linear interpolation between breakpoints. The AUC is equivalent to the Wilcoxon-Mann-Whitney statistic: AUC = P(score(positive) > score(negative)). This interpretation is independent of class balance.

Build docs developers (and LLMs) love