Logistic Regression
scikit-learn
predict_proba
machine learning
Python

scikit-learn return value of LogisticRegression.predict_proba

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

Introduction

LogisticRegression.predict_proba(...) returns class probabilities for each input sample. The most important detail is that the columns are ordered according to model.classes_, so you should never guess which column corresponds to which class label.

What the Return Value Looks Like

For n_samples input rows and n_classes classes, predict_proba returns an array of shape (n_samples, n_classes).

python
1from sklearn.datasets import make_classification
2from sklearn.linear_model import LogisticRegression
3
4X, y = make_classification(
5    n_samples=20,
6    n_features=4,
7    n_classes=2,
8    random_state=7
9)
10
11model = LogisticRegression()
12model.fit(X, y)
13
14probs = model.predict_proba(X[:3])
15print(probs)
16print(probs.shape)
17print(model.classes_)

Each row is the probability distribution for one sample, and each row sums to 1.0.

Binary Classification Example

In a binary problem, the output usually has two columns. If model.classes_ is [0, 1], then:

  • column 0 is the probability of class 0
  • column 1 is the probability of class 1

For example:

python
print(model.classes_)      # [0 1]
print(model.predict_proba(X[:2]))

An output like:

text
[[0.72 0.28]
 [0.10 0.90]]

means:

  • sample 0: 72% class 0, 28% class 1
  • sample 1: 10% class 0, 90% class 1

That second column is often used as the "positive class" probability, but only when classes_ actually orders the labels that way.

Do Not Guess the Positive Class Column

This is the most common mistake. If your labels are strings or non-standard numeric values, the class order might not be what you assumed.

python
1from sklearn.linear_model import LogisticRegression
2
3X = [[0], [1], [2], [3]]
4y = ["ham", "spam", "ham", "spam"]
5
6model = LogisticRegression()
7model.fit(X, y)
8
9print(model.classes_)
10print(model.predict_proba([[1.5]]))

Always inspect model.classes_ before interpreting the columns.

Multi-Class Output

For multi-class classification, predict_proba still returns one row per sample and one column per class.

python
1from sklearn.datasets import make_classification
2from sklearn.linear_model import LogisticRegression
3
4X, y = make_classification(
5    n_samples=50,
6    n_features=6,
7    n_informative=4,
8    n_redundant=0,
9    n_classes=3,
10    n_clusters_per_class=1,
11    random_state=7
12)
13
14model = LogisticRegression(max_iter=500)
15model.fit(X, y)
16
17probs = model.predict_proba(X[:2])
18print(model.classes_)
19print(probs)
20print(probs.sum(axis=1))

Now each row has three probabilities, one for each class, and they still sum to 1.

predict Versus predict_proba

predict(...) returns the final chosen class label. predict_proba(...) returns the model's probability distribution across classes.

You can often think of:

python
predicted_labels = model.predict(X)

as roughly equivalent to taking the highest-probability column in:

python
probabilities = model.predict_proba(X)

but the probability output gives much more information for thresholding, ranking, calibration, and downstream decision-making.

Thresholding Is Your Responsibility

In binary classification, many workflows use the probability for one class and then apply a custom threshold such as 0.7 instead of the default highest-probability decision. That is another reason to interpret predict_proba(...) with classes_ in hand rather than assuming a hardcoded column meaning.

Common Pitfalls

The biggest mistake is assuming column 1 always means "positive class." The correct mapping always comes from model.classes_.

Another issue is forgetting that each row corresponds to one sample and each column corresponds to one class. Misreading the axes leads to incorrect downstream logic.

Developers also treat the probabilities as calibrated truth by default. Logistic regression probabilities are often useful, but calibration quality still depends on data and model fit.

Finally, if you only need the predicted label, predict(...) is simpler. Use predict_proba(...) when the probability itself matters.

Summary

  • 'predict_proba(...) returns an array of shape (n_samples, n_classes).'
  • Each row is a probability distribution over classes for one sample.
  • The column order is defined by model.classes_.
  • In binary classification, do not assume the second column is the positive class without checking classes_.
  • Use predict_proba(...) when probabilities or thresholds matter, not just class labels.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

All Rights Reserved.