Linear Discriminant Analysis

Suppose a bank must decide whether a loan applicant will default. This decision is based on the applicant's income and debt ratio. It has years of labeled records — defaulters and non-defaulters. It wants a decision rule that separates the two groups. This rule should have a simple boundary it can audit and explain. Linear Discriminant Analysis (LDA) answers this by modeling each class as a Gaussian cloud of points. It then asks Bayes' rule which cloud a new point more plausibly came from. LDA sits at a crossroad of ideas already familiar from Naive Bayes Classifiers and Logistic Regression and the Sigmoid. Like Naive Bayes, it is a generative classifier. It models how data are produced within each class. Then it inverts that model with Bayes' theorem to classify. Like logistic regression, it ultimately produces a linear decision boundary. But it arrives there through a completely different route. It assumes Gaussian class-conditional densities with a shared covariance matrix. This differs from directly modeling the log-odds. This generative view matters in practice. When classes are well-separated, when the training set is small, or when the Gaussian assumption is roughly true, LDA can be more statistically efficient than logistic regression. This is because it exploits more structure in the data. It also naturally extends to more than two classes. No one-vs-rest bookkeeping is needed. It also yields the quadratic discriminant analysis (QDA) variant when the shared-covariance assumption is dropped. This trades bias for variance in exchange for curved decision boundaries. This article builds LDA from first principles. It covers the Gaussian generative model and the Bayes-optimal decision rule. It covers the algebraic simplification that produces a linear boundary. It covers the closed-form parameter estimates from data. It also covers the geometric picture of projecting data onto a discriminant direction. It closes with worked numerical traces and common failure modes. It ends with the historical origin of the method in Fisher's 1936 work on taxonomic classification — decades before "machine learning" was a phrase.

Key takeaways
  • LDA models each class's inputs as Gaussian and applies Bayes' rule to classify — a generative, not discriminative, approach.
  • Assuming all classes share one covariance matrix makes the quadratic Bayes boundary collapse into a linear boundary.
  • Class means, the shared covariance, and priors are all estimated by simple closed-form formulas — no iterative optimization needed.
  • Dropping the shared-covariance assumption yields Quadratic Discriminant Analysis (QDA), with curved boundaries but more parameters to estimate.
  • LDA is also a dimensionality-reduction tool: it finds the projection direction that best separates class means relative to within-class scatter.
  • It is efficient and stable with small samples but degrades if the Gaussian or equal-covariance assumptions are badly violated.
The core insight

LDA classifies by assuming each class is Gaussian with the same covariance matrix, which makes the Bayes-optimal boundary between any two classes exactly linear.

The idea

A classifier needs a rule that maps a feature vector x∈Rpx \in \mathbb{R}^p to a class label k∈{1,…,K}k \in \{1, \dots, K\}. The generative strategy models the class-conditional density p(x∣y=k)p(x \mid y = k) — how features are distributed within each class — together with the class prior πk=P(y=k)\pi_k = P(y=k). Bayes' theorem then gives the posterior:

P(y=k∣x)=πk p(x∣y=k)∑j=1Kπj p(x∣y=j).P(y = k \mid x) = \frac{\pi_k \, p(x \mid y=k)}{\sum_{j=1}^{K} \pi_j \, p(x \mid y=j)}.

Classification picks the class maximizing this posterior. This is exactly the strategy of Naive Bayes Classifiers, but Naive Bayes further assumes the features are conditionally independent given the class. LDA instead assumes each class-conditional density is a multivariate Gaussian,

p(x∣y=k)=1(2π)p/2∣Σk∣1/2exp⁡ ⁣(−12(x−μk)⊤Σk−1(x−μk)),p(x \mid y=k) = \frac{1}{(2\pi)^{p/2} |\Sigma_k|^{1/2}} \exp\!\left(-\tfrac{1}{2}(x-\mu_k)^\top \Sigma_k^{-1} (x-\mu_k)\right),

with mean μk\mu_k and covariance Σk\Sigma_k specific to class kk, but crucially adds the restriction that all classes share the same covariance matrix, Σk=Σ\Sigma_k = \Sigma for every kk. This shared-covariance assumption is the entire reason the resulting boundary is linear rather than curved — the quadratic terms in xx that would otherwise appear cancel between classes. If instead each class is allowed its own covariance Σk\Sigma_k, the method is called Quadratic Discriminant Analysis (QDA): it keeps the Gaussian assumption but drops the shared-covariance restriction, producing quadratic (curved, e.g. elliptical or hyperbolic) decision boundaries. LDA and QDA thus form a bias–variance pair: LDA has higher bias (a stricter model) but lower variance (fewer parameters to estimate — one Σ\Sigma instead of KK of them), while QDA is more flexible but needs more data to estimate its per-class covariances reliably.

How it works

Deriving the linear boundary. Classification compares posteriors across classes; because the denominator of Bayes' rule is common to all classes, it suffices to compare the numerators πk p(x∣y=k)\pi_k\, p(x\mid y=k), or equivalently their logarithms, the discriminant functions:

δk(x)=log⁡πk+log⁡p(x∣y=k).\delta_k(x) = \log \pi_k + \log p(x \mid y = k).

Substituting the shared-covariance Gaussian density and dropping terms that do not depend on kk (they cancel when comparing classes) gives, after expanding the quadratic form (x−μk)⊤Σ−1(x−μk)(x-\mu_k)^\top \Sigma^{-1} (x-\mu_k):

δk(x)=x⊤Σ−1μk  −  12μk⊤Σ−1μk  +  log⁡πk.\delta_k(x) = x^\top \Sigma^{-1} \mu_k \;-\; \tfrac{1}{2}\mu_k^\top \Sigma^{-1} \mu_k \;+\; \log \pi_k.

The term −12x⊤Σ−1x-\tfrac{1}{2}x^\top \Sigma^{-1} x, which is quadratic in xx, is identical for every class (since Σ\Sigma does not depend on kk) and was dropped precisely because it cancels in any pairwise comparison. What remains, δk(x)\delta_k(x), is linear in xx — an affine function wk⊤x+bkw_k^\top x + b_k with

wk=Σ−1μk,bk=−12μk⊤Σ−1μk+log⁡πk.w_k = \Sigma^{-1}\mu_k, \qquad b_k = -\tfrac12 \mu_k^\top \Sigma^{-1}\mu_k + \log\pi_k.

The predicted class is y^=arg⁡max⁡kδk(x)\hat y = \arg\max_k \delta_k(x), and the boundary between any two classes k,lk, l — the set where δk(x)=δl(x)\delta_k(x) = \delta_l(x) — is a hyperplane, since it is defined by a linear equation in xx.

Estimating parameters from data. Given a training set {(xi,yi)}i=1n\{(x_i, y_i)\}_{i=1}^n with nkn_k examples in class kk, the maximum-likelihood estimates are:

π^k=nkn,μ^k=1nk∑i: yi=kxi,\hat\pi_k = \frac{n_k}{n}, \qquad \hat\mu_k = \frac{1}{n_k}\sum_{i:\,y_i=k} x_i,
Σ^=1n−K∑k=1K∑i: yi=k(xi−μ^k)(xi−μ^k)⊤.\hat\Sigma = \frac{1}{n - K}\sum_{k=1}^K \sum_{i:\,y_i=k} (x_i - \hat\mu_k)(x_i - \hat\mu_k)^\top.

The covariance estimate pools the (mean-centered) scatter within each class across all classes — a weighted average of the per-class sample covariances — which is why it is called the pooled within-class covariance. Dividing by n−Kn-K rather than nn makes it an unbiased estimator, mirroring the degrees-of-freedom correction in ordinary sample variance.

Two-class special case. For K=2K=2, comparing δ1(x)\delta_1(x) and δ2(x)\delta_2(x) reduces to thresholding a single linear score:

δ1(x)−δ2(x)=x⊤Σ−1(μ1−μ2)−12(μ1+μ2)⊤Σ−1(μ1−μ2)+log⁡π1π2,\delta_1(x) - \delta_2(x) = x^\top \Sigma^{-1}(\mu_1 - \mu_2) - \tfrac12(\mu_1+\mu_2)^\top\Sigma^{-1}(\mu_1-\mu_2) + \log\frac{\pi_1}{\pi_2},

classify as class 1 if this quantity is positive. The vector Σ−1(μ1−μ2)\Sigma^{-1}(\mu_1-\mu_2) is the Fisher discriminant direction: projecting data onto it maximizes the ratio of between-class separation to within-class spread, which is Fisher's original 1936 formulation of the problem, independent of any Gaussian assumption. ``` ALGORITHM: Fit LDA (K classes, n samples, p features) INPUT: training pairs (x_i, y_i), i = 1..n, y_i in {1,...,K} OUTPUT: priors {pi_k}, means {mu_k}, shared covariance Sigma 1. for k = 1 to K: 2. S_k <- { x_i : y_i = k } 3. n_k <- |S_k| 4. pi_k <- n_k / n 5. mu_k <- (1 / n_k) sum_{x in S_k} x 6. 7. Sigma <- zero matrix (p x p) 8. for k = 1 to K: 9. for each x in S_k: 10. Sigma <- Sigma + (x - mu_k)(x - mu_k)^T 11. Sigma <- Sigma / (n - K) 12. return {pi_k}, {mu_k}, Sigma ALGORITHM: Predict LDA INPUT: new point x, fitted {pi_k}, {mu_k}, Sigma OUTPUT: predicted class label 1. SigmaInv <- Sigma^{-1} // computed once, reused for all queries 2. best_score <- -infinity; best_k <- none 3. for k = 1 to K: 4. w_k <- SigmaInv mu_k 5. b_k <- -0.5 mu_k^T SigmaInv mu_k + log(pi_k) 6. score_k <- w_k^T x + b_k 7. if score_k > best_score: 8. best_score <- score_k; best_k <- k 9. return best_k ``` The fitting step is a single closed-form pass over the data with no iteration, gradient descent, or convergence check required — a sharp contrast to Logistic Regression and the Sigmoid, whose maximum-likelihood parameters require iterative optimization (e.g. Newton's method or gradient ascent) because the logistic log-likelihood has no closed-form maximizer.

Figure
LDA as Gaussian ellipses sharing one covariance shape, separated by a linear boundary
Two Gaussian classes, shared covariance ⇒ linear boundary x1 x2 μ1 μ2 decision boundary (linear) Σ⁻¹(μ1 − μ2) direction

Complexity & correctness

Time complexity. Fitting requires one pass over the nn training points to accumulate class sums (means) — O(np)O(np) — and a second pass to accumulate the pooled scatter matrix, which costs O(np2)O(np^2) since each point contributes an outer product of size p×pp \times p. Inverting the resulting p×pp \times p covariance matrix costs O(p3)O(p^3) via standard methods (e.g. Cholesky decomposition, which is preferred since Σ\Sigma is symmetric positive semi-definite). Total fitting time is

O(np2+p3),O(np^2 + p^3),

dominated by the scatter accumulation when n≫pn \gg p, and by the matrix inversion when pp is large relative to nn. Prediction for a single new point, after the inverse is precomputed once, costs O(Kp)O(Kp) to evaluate the KK linear discriminant scores — extremely fast, since it is just KK dot products.

Space complexity. Storing the pooled covariance matrix requires O(p2)O(p^2) space; storing the KK mean vectors requires O(Kp)O(Kp). Total space is O(p2+Kp)O(p^2 + Kp), independent of nn once fitting is complete — the training data itself need not be retained.

Correctness argument. The core claim is that under the shared-covariance Gaussian model, the Bayes-optimal classifier (the one minimizing expected misclassification rate) is exactly arg⁡max⁡kδk(x)\arg\max_k \delta_k(x) with δk\delta_k linear. This follows in three steps: 1. Bayes' decision theory guarantees that arg⁡max⁡kP(y=k∣x)\arg\max_k P(y=k\mid x) minimizes the 0-1 loss risk, for any correctly specified p(x∣y=k)p(x\mid y=k) and prior πk\pi_k — a fact independent of the Gaussian assumption. 2. Because the denominator ∑jπjp(x∣y=j)\sum_j \pi_j p(x\mid y=j) is the same for all kk, maximizing the posterior is equivalent to maximizing the numerator πkp(x∣y=k)\pi_k p(x\mid y=k), or its log, δk(x)\delta_k(x). 3. Expanding the Gaussian log-density with a common Σ\Sigma makes the quadratic term −12x⊤Σ−1x-\tfrac12 x^\top\Sigma^{-1}x identical across all kk, so it can be dropped without changing which kk attains the maximum — leaving a strictly linear function of xx. So given that the shared-covariance Gaussian model is correct, LDA implements the exact Bayes-optimal rule — no approximation is introduced beyond the modeling assumption itself. The maximum-likelihood parameter estimates (μ^k\hat\mu_k, Σ^\hat\Sigma, π^k\hat\pi_k) are consistent (converge to the true parameters as n→∞n\to\infty by the law of large numbers) and, for Gaussian data, are the unique maximizers of the joint likelihood — the sample mean and pooled sample covariance are exactly the MLE solutions obtainable by setting the gradient of the log-likelihood to zero.

Honest tradeoffs. The correctness argument is conditional: if the true class-conditional densities are not Gaussian, or if classes truly have different covariances, LDA's boundary is no longer Bayes-optimal, though it can still perform well as a biased but low-variance approximation — this is precisely why LDA sometimes beats both QDA and logistic regression on small or noisy datasets, trading a correctness guarantee for statistical stability. When the equal-covariance assumption is dropped, QDA removes this bias at the cost of estimating KK separate p×pp\times p covariance matrices, an O(Kp2)O(Kp^2) parameter cost that can overfit badly when nn is small relative to pp.

Worked example

Consider a two-class, two-feature problem — say, classifying wine as red (class 1) or white (class 2) from (acidity, sugar), both standardized. Training data (small illustrative sample):

ClassAcidity (x1x_1)Sugar (x2x_2)
Red1.02.0
Red1.51.5
Red0.52.5
White3.00.5
White3.51.0
White2.50.0

Step 1 — priors and means. n1=n2=3n_1 = n_2 = 3, n=6n=6, so π^1=π^2=0.5\hat\pi_1 = \hat\pi_2 = 0.5.

μ^1=(1.0,2.0),μ^2=(3.0,0.5).\hat\mu_1 = (1.0, 2.0), \qquad \hat\mu_2 = (3.0, 0.5).

Step 2 — pooled covariance. Centered class-1 points: (0,0),(0.5,−0.5),(−0.5,0.5)(0,0), (0.5,-0.5), (-0.5,0.5); centered class-2 points: (0,0),(0.5,0.5),(−0.5,−0.5)(0,0), (0.5,0.5), (-0.5,-0.5). Their outer-product sums each give (0.5−0.5−0.50.5)\begin{pmatrix}0.5 & -0.5\\-0.5 & 0.5\end{pmatrix} and (0.50.50.50.5)\begin{pmatrix}0.5 & 0.5\\0.5 & 0.5\end{pmatrix} respectively, summing to (1.0001.0)\begin{pmatrix}1.0 & 0\\0 & 1.0\end{pmatrix}. Dividing by n−K=6−2=4n - K = 6-2=4:

Σ^=(0.25000.25),Σ^−1=(4004).\hat\Sigma = \begin{pmatrix}0.25 & 0 \\ 0 & 0.25\end{pmatrix}, \qquad \hat\Sigma^{-1} = \begin{pmatrix}4 & 0\\0 & 4\end{pmatrix}.

Step 3 — Fisher direction. μ1−μ2=(−2.0,1.5)\mu_1 - \mu_2 = (-2.0, 1.5), so

w=Σ−1(μ1−μ2)=(4)(−2.0, 1.5)=(−8.0, 6.0).w = \Sigma^{-1}(\mu_1-\mu_2) = (4)(-2.0,\,1.5) = (-8.0,\, 6.0).

Step 4 — discriminant score for a new point. Take a test wine x=(2.0,1.0)x = (2.0, 1.0).

δ1(x)−δ2(x)=x⊤w−12(μ1+μ2)⊤w+log⁡π1π2.\delta_1(x)-\delta_2(x) = x^\top w - \tfrac12(\mu_1+\mu_2)^\top w + \log\frac{\pi_1}{\pi_2}.

Compute each piece: x⊤w=(2.0)(−8.0)+(1.0)(6.0)=−16+6=−10x^\top w = (2.0)(-8.0) + (1.0)(6.0) = -16 + 6 = -10. Midpoint 12(μ1+μ2)=(2.0,1.25)\tfrac12(\mu_1+\mu_2) = (2.0, 1.25), so 12(μ1+μ2)⊤w=(2.0)(−8.0)+(1.25)(6.0)=−16+7.5=−8.5\tfrac12(\mu_1+\mu_2)^\top w = (2.0)(-8.0)+(1.25)(6.0) = -16 + 7.5 = -8.5. Priors are equal so log⁡(π1/π2)=0\log(\pi_1/\pi_2)=0. Total:

δ1(x)−δ2(x)=−10−(−8.5)+0=−1.5.\delta_1(x)-\delta_2(x) = -10 - (-8.5) + 0 = -1.5.

Since this is negative, x=(2.0,1.0)x=(2.0,1.0) is classified as class 2 (white) — sensible, since it lies closer to the white cluster (3.0,0.5)(3.0, 0.5) than the red cluster (1.0,2.0)(1.0, 2.0) once the (here, isotropic) covariance is accounted for. Notice the classifier did not need to iterate or search: the entire boundary was determined algebraically from means, prior ratio, and one matrix inverse.

Contrast with logistic regression. Logistic regression would fit the same linear form w⊤x+bw^\top x + b by maximizing the conditional log-likelihood via iterative reweighted least squares or gradient ascent, without ever assuming the xx's are Gaussian. On this well-separated, roughly Gaussian, equal-spread toy dataset, both methods land on nearly the same boundary — but LDA got there in closed form, using information about the marginal distribution of xx that logistic regression ignores entirely.

Common pitfalls & traps

PitfallWhy it happensConsequence
Treating LDA's linear boundary as proof classes are linearly separableBoundary is a modeling consequence, not a data factPoor fit if classes actually need curved boundaries
Using LDA with wildly unequal class covariancesShared-Σ\Sigma assumption silently violatedSystematic bias; QDA or standardizing per class needed
Singular or near-singular Σ^\hat\Sigma (features ≫\gg samples, or collinear features)pp large relative to nn, or duplicated/correlated featuresΣ−1\Sigma^{-1} undefined or numerically unstable; requires regularized/shrinkage LDA
Ignoring class imbalance in π^k\hat\pi_kPriors estimated from raw class frequenciesBoundary shifts to favor majority class even when undesirable operationally
Confusing LDA (classifier) with PCA (unsupervised)Both project onto lower dimensions via eigen-analysisPCA ignores labels and may discard exactly the direction that separates classes
Applying LDA to raw, unscaled featuresCovariance dominated by high-variance featureDiscriminant direction distorted toward large-scale features

Pioneers & history

Origins · 1 minRonald Aylmer Fisher and how this was discovered
RA
Ronald Aylmer Fisher
1890–1962 · British statistician and geneticist, Rothamsted Experimental Station and University College London

Fisher developed the discriminant analysis framework in 1936 while working on taxonomic classification of iris flowers by petal and sepal measurements — the origin of the now-famous Iris dataset. He posed the problem geometrically: find the linear combination of measurements that maximizes the ratio of between-group variance to within-group variance, a criterion later shown to coincide with the Bayes-optimal rule under Gaussian, equal-covariance assumptions. Fisher's broader legacy in statistics — maximum likelihood, analysis of variance, experimental design — makes this one of many foundational tools he introduced that later became central to statistical and machine learning practice.

History
1936
— Fisher introduces linear discriminant analysis for classifying iris species from flower measurements.
1962
— C. R. Rao generalizes Fisher's discriminant to multiple classes and connects it formally to the Gaussian Bayes classifier.
1973
— Quadratic Discriminant Analysis becomes standard in statistical pattern recognition texts as the natural relaxation of the equal-covariance assumption.
1989
— Regularized/shrinkage discriminant analysis is popularized to handle high-dimensional, small-sample settings.
2000
s — LDA and its variants become standard baselines in bioinformatics (gene-expression classification) and computer vision (Fisherfaces for face recognition).

Where this matters

LDA remains a workhorse baseline wherever data are moderately low-dimensional, classes are roughly Gaussian, and interpretability or speed matters. In computer vision, the classic Fisherfaces method applies LDA (often after a PCA preprocessing step) to face recognition, exploiting the fact that projecting onto the Fisher discriminant direction is far more robust to lighting variation than PCA alone. In bioinformatics, LDA and shrinkage-LDA variants classify tumor subtypes from gene-expression profiles, where sample sizes are small and a closed-form, low-variance estimator is preferable to an iteratively-fit high-variance one. In finance, credit-scoring and bankruptcy-prediction models have historically used LDA for its linear, auditable decision rule — a regulatory advantage over opaque nonlinear classifiers. It is also a standard dimensionality-reduction preprocessing step: unlike PCA, LDA's projection direction is chosen using label information, making it a supervised complement to unsupervised techniques. Modern deep learning systems rarely use LDA directly at scale, but its Gaussian-generative logic reappears in Gaussian mixture models, quadratic discriminant analysis, and as a theoretical benchmark against which discriminative methods like Logistic Regression and the Sigmoid are compared in statistics and machine learning coursework.

Ask the tutor: How does regularized (shrinkage) LDA choose the shrinkage parameter λ in practice, and how does that connect to ridge regression?

Is LDA the same thing as PCA?

No. Principal Component Analysis (PCA) is unsupervised: it finds directions of maximum variance in the data without using class labels at all. LDA is supervised: it uses labels to find the direction (or directions) that best separate known classes, maximizing between-class variance relative to within-class variance. Both involve eigen-analysis of matrices derived from the data, which is the source of the confusion, but PCA's matrix is the overall covariance while LDA's involves the between-class and within-class scatter matrices together. In practice they are sometimes combined: PCA first reduces noise and dimensionality, then LDA finds the label-aware separating direction within that reduced space, as in the classic Fisherfaces face-recognition pipeline.

How does LDA relate to logistic regression, given both produce linear boundaries?

Both methods can produce identical-looking linear decision boundaries, but they get there differently. Logistic regression is discriminative: it directly models P(y∣x)P(y\mid x) as a sigmoid of a linear function, fit by maximizing conditional likelihood via iterative optimization, without assuming anything about the marginal distribution of xx. LDA is generative: it models the full joint distribution of xx and yy via Gaussian class-conditionals, then derives the posterior via Bayes' rule, obtaining parameters in closed form. When the Gaussian, equal-covariance assumption holds, LDA is more statistically efficient (lower variance) with the same amount of data; when it doesn't hold, logistic regression's weaker assumptions make it more robust.

Why is the covariance matrix "pooled" across classes rather than estimated separately per class?

Pooling assumes every class shares the same covariance structure — the same "shape" of spread — differing only in mean location. This is the assumption that mathematically cancels the quadratic term in the discriminant function, producing a linear rather than curved boundary. Pooling also means all nn training points, not just the nkn_k points in one class, contribute to estimating Σ\Sigma, giving a lower-variance estimate especially valuable when some classes have few examples. The tradeoff is bias: if classes genuinely differ in spread or orientation, pooling introduces systematic error that only per-class covariances (as in QDA) can correct.

What happens if a class has very few training examples?

The class mean μ^k\hat\mu_k becomes noisy, and if computed per-class (as in QDA), the covariance estimate for that class can be singular or wildly unstable. LDA partially protects against this because the covariance is pooled across all classes, borrowing statistical strength from the more populous classes rather than relying solely on the sparse class's own data. Nonetheless, an extremely small class still yields an unreliable mean estimate, and its prior π^k=nk/n\hat\pi_k = n_k/n may misrepresent the true class frequency if the sample was not collected proportionally to the population.

Can LDA handle more than two classes directly?

Yes, and this is one of its practical advantages over methods like plain logistic regression, which needs a one-vs-rest or softmax extension for multi-class problems. LDA computes a discriminant function δk(x)\delta_k(x) for every class k=1,…,Kk = 1, \dots, K using the same shared covariance matrix, and simply predicts whichever class attains the highest score. The boundaries between every pair of classes are still linear (hyperplanes), so the full decision region of Rp\mathbb{R}^p is partitioned into KK polyhedral (piecewise-linear-boundaried) regions, one per class, at no extra algorithmic cost beyond computing KK linear scores.

When should I prefer QDA over LDA?

Prefer QDA when you have reasonable evidence that classes have genuinely different covariance structures — different spreads, orientations, or correlations among features — and, importantly, when you have enough training data per class to estimate each covariance matrix reliably. QDA needs roughly KK times as many covariance parameters as LDA (K⋅p(p+1)/2K \cdot p(p+1)/2 versus p(p+1)/2p(p+1)/2), so with limited data per class it can overfit and underperform LDA despite being the "more correct" model in principle. A practical approach is to try both and compare held-out accuracy, or use a regularized method that interpolates between the shared and per-class covariance extremes.

Does LDA require features to be exactly Gaussian to work well?

No — LDA is often useful even when the Gaussian assumption is only approximately true, because it is really solving a linear classification problem, and the Gaussian derivation is one principled way to get there. What matters more in practice is that classes have roughly similar spread and shape, and that no single feature or outlier dominates the covariance estimate. When features are strongly non-Gaussian (heavily skewed, multimodal, or categorical), transformations (log, Box-Cox) or switching to a discriminative method like logistic regression, or a tree-based classifier, often perform better than forcing the Gaussian assumption.

Before this