Data Science AUC-ROC Curve
The ROC curve plots a classifier's true positive rate against its false positive rate across every possible decision threshold, and the AUC score summarizes that curve as a single number describing how well the model separates the two classes.
Beyond a Single Accuracy Number
A classifier like logistic regression outputs a probability, and a threshold (commonly 0.5) turns that probability into a class label. But 0.5 is just one choice. Lowering the threshold catches more true positives at the cost of more false positives; raising it does the opposite. The ROC (Receiver Operating Characteristic) curve shows this entire trade-off at once, by plotting performance across every possible threshold rather than committing to just one.
True Positive Rate and False Positive Rate
The ROC curve has two axes. The y-axis is the true positive rate (TPR), also called recall or sensitivity: of all the actual positive cases, what fraction did the model correctly catch? The x-axis is the false positive rate (FPR): of all the actual negative cases, what fraction did the model incorrectly flag as positive? As you sweep the decision threshold from high to low, both TPR and FPR change, tracing out the curve from the bottom-left corner (0,0) to the top-right corner (1,1).
- TPR = True Positives / (True Positives + False Negatives) — how many real positives were caught.
- FPR = False Positives / (False Positives + True Negatives) — how many real negatives were wrongly flagged.
- A high threshold makes the model cautious: low FPR, but also lower TPR.
- A low threshold makes the model liberal: high TPR, but also higher FPR.
Example: Plotting an ROC curve
from sklearn.datasets import load_breast_cancer
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_curve, roc_auc_score
X, y = load_breast_cancer(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, random_state=1)
model = LogisticRegression(max_iter=5000)
model.fit(X_train, y_train)
# Probability of the positive class, needed for the curve
y_scores = model.predict_proba(X_test)[:, 1]
fpr, tpr, thresholds = roc_curve(y_test, y_scores)
auc = roc_auc_score(y_test, y_scores)
print('AUC:', round(auc, 3))
# fpr and tpr are arrays you can plot: plt.plot(fpr, tpr)Interpreting the AUC Score
An AUC of 1.0 means perfect separation: for every possible threshold, the model correctly ranks all positives above all negatives, with no overlap at all. An AUC of 0.5 means the model performs no better than random guessing, equivalent to the diagonal line from (0,0) to (1,1) on the ROC plot. In practice, most useful models land somewhere between these extremes, and higher AUC always means better ranking ability regardless of which threshold you eventually choose to deploy.