Answer

Logit vs probit: what is the difference, and which should you use?

Inspired by a question on Cross Validated ·

regressionlogistic regression

The short answer

Both model a yes/no outcome by pushing a linear predictor through an S-shaped curve: the logistic curve for logit, the normal curve for probit. Their predictions are nearly identical and their coefficients differ mainly by a factor of about 1.6 to 1.8. Use logit when you want odds ratios, which is most of the time; use probit when your theory assumes a normally distributed latent variable or your field expects it.

Two versions of the same idea

Both are generalized linear models for a binary outcome such as pass/fail or bought/did not buy. Each one computes a linear predictor, b0 + b1*x1 + ..., and turns it into a probability between 0 and 1 with a link function. The logit model uses the logistic curve, so the linear predictor is the log of the odds. The probit model uses the cumulative normal curve, so the linear predictor is a z-score on the standard normal scale.

A helpful way to see the difference is a hidden, continuous variable. Imagine each person has an unobserved propensity, and the event happens when that propensity crosses zero. If the random part of the propensity follows a standard normal distribution, you get probit. If it follows a logistic distribution, you get logit. The logistic distribution looks very much like the normal one, with slightly heavier tails and a standard deviation of about 1.81 instead of 1.

Why the coefficients look different

Because the two latent scales have different spreads, logit coefficients are larger. In the middle of the curve, logit estimates are usually about 1.6 to 1.8 times the probit estimates (1.6 matches the slopes of the two curves at their centre, and 1.81 matches their standard deviations). The ratio is a rule of thumb, not a law, but it is why nobody should compare a logit coefficient with a probit coefficient directly.

The fitted probabilities are what really matter, and they rarely differ by more than one or two percentage points except far out in the tails, where the logistic curve approaches 0 and 1 a little more slowly. With ordinary sample sizes, the data can almost never tell the two models apart.

Which one to choose

Do not choose between them by trying both and keeping the one with the smaller p-value. If you want an empirical check, compare the models' AIC values, but expect the difference to be small; a difference of one or two points is no reason to switch. See the page on AIC vs BIC for how to read such differences.

See it in R and Python

This simulation generates pass/fail outcomes for 500 students from a true logistic model with hours of study as the predictor, then fits both a logit and a probit model with base R's glm(). The Python tab fits the same two models by maximum likelihood with NumPy and SciPy.

R

set.seed(2052)
n <- 500
hours <- runif(n, 0, 10)                        # hours studied
pass  <- rbinom(n, 1, plogis(-3 + 0.6 * hours)) # true model is logistic

logit  <- glm(pass ~ hours, family = binomial(link = "logit"))
probit <- glm(pass ~ hours, family = binomial(link = "probit"))

# Coefficients differ in scale, not in story
round(rbind(logit = coef(logit), probit = coef(probit)), 3)
round(coef(logit) / coef(probit), 2)            # roughly 1.6 to 1.8

# Fit and predictions are nearly identical
round(c(AIC_logit = AIC(logit), AIC_probit = AIC(probit)), 2)
round(max(abs(fitted(logit) - fitted(probit))), 3)

# Predicted probability of passing at 2, 5 and 8 hours
new <- data.frame(hours = c(2, 5, 8))
round(rbind(logit  = predict(logit,  new, type = "response"),
            probit = predict(probit, new, type = "response")), 3)

# Logit: odds ratio per extra hour with a Wald 95% CI
b  <- coef(summary(logit))["hours", ]
round(c(b[1:4], OR = exp(b[[1]]),
        lower = exp(b[[1]] - 1.96 * b[[2]]), upper = exp(b[[1]] + 1.96 * b[[2]])), 3)
format.pval(b[[4]], digits = 3)

Python

import numpy as np
from scipy import stats
from scipy.special import expit

rng = np.random.default_rng(2052)
n = 500
hours = rng.uniform(0, 10, n)                          # hours studied
passed = rng.binomial(1, expit(-3 + 0.6 * hours))      # true model is logistic
X = np.column_stack([np.ones(n), hours])

def fit_binary(link):
    # Maximum likelihood by Fisher scoring (what R's glm does); returns estimates, SEs, AIC
    cdf, pdf = (expit, lambda e: expit(e) * (1 - expit(e))) if link == "logit" else (stats.norm.cdf, stats.norm.pdf)
    beta = np.zeros(2)
    for _ in range(50):
        eta = X @ beta
        mu = np.clip(cdf(eta), 1e-10, 1 - 1e-10)
        w = pdf(eta) ** 2 / (mu * (1 - mu))
        info = X.T @ (X * w[:, None])
        beta = beta + np.linalg.solve(info, X.T @ ((passed - mu) * pdf(eta) / (mu * (1 - mu))))
    mu = cdf(X @ beta)
    loglik = np.sum(passed * np.log(mu) + (1 - passed) * np.log(1 - mu))
    return beta, np.sqrt(np.diag(np.linalg.inv(info))), -2 * loglik + 2 * len(beta), mu

(b_l, se_l, aic_l, mu_l), (b_p, se_p, aic_p, mu_p) = fit_binary("logit"), fit_binary("probit")

# Coefficients differ in scale, not in story
print("logit ", np.round(b_l, 3), " probit", np.round(b_p, 3))
print("ratio ", np.round(b_l / b_p, 2))                 # roughly 1.6 to 1.8

# Fit and predictions are nearly identical
print("AIC logit", round(aic_l, 2), " AIC probit", round(aic_p, 2))
print("max difference in fitted probabilities", round(np.max(np.abs(mu_l - mu_p)), 3))

# Predicted probability of passing at 2, 5 and 8 hours
new = np.column_stack([np.ones(3), [2, 5, 8]])
print("logit ", np.round(expit(new @ b_l), 3), " probit", np.round(stats.norm.cdf(new @ b_p), 3))

# Logit: odds ratio per extra hour with a Wald 95% CI
z = b_l[1] / se_l[1]
print("b", round(b_l[1], 3), "SE", round(se_l[1], 3), "z", round(z, 3), "p", 2 * stats.norm.sf(abs(z)))
print("OR", round(np.exp(b_l[1]), 3), "CI", np.round(np.exp(b_l[1] + np.array([-1.96, 1.96]) * se_l[1]), 3))

The figures below come from one seeded run of the R code. Python uses a different random number generator, so its figures differ slightly, but the pattern is the same.

Common mistakes

How to report logistic regression results in APA style (7th edition)

Say in the method section which model you fitted (for example, "a binary logistic regression" or "a probit regression"), what the outcome was coded as, and how the confidence intervals were computed. Using the logit model above as an example:

"A logistic regression showed that hours of study predicted passing, b = 0.71, SE = 0.06, z = 12.01, p < .001. Each additional hour was associated with roughly double the odds of passing, OR = 2.03, 95% CI [1.81, 2.28]."

For a probit model, report b, SE, z and p the same way, and add predicted probabilities or average marginal effects so readers can see the size of the effect. In a table, give each predictor's b, SE, p and, for logit, the odds ratio with its 95% CI, plus the sample size and a fit statistic such as AIC in a note.

Related tools and guides

More answered questions

Working with your own data?

General answers only go so far. Send us your situation and we'll reply by email within two business days.

Ask your question

Written by AskStats with AI assistance. This is general information, not advice for your specific data or study. When the results matter, check your approach with a qualified statistician.