Skip to main content

Linear discriminant analysis

Give every class the same covariance and the quadratic terms of the log posteriors cancel, leaving a linear boundary. Derive the discriminant line by line, fit it to the twelve points by hand and in NumPy, and compare it with logistic regression.
ML02.9.2L2 Intermediate25 min
In review (what this means)

The maths and code on this page are checked by automated tests on every change, but an independent reader has not signed it off yet. Spot a mistake or a confusing step? Tell us.

Before this lesson: ML02.9.1 Classes as Gaussian clouds ML01.6 Logistic regression and classification

What you will be able to do
  • Derive the linear discriminant function from the Gaussian log posterior with a shared covariance, showing why the quadratic term cancels.
  • Estimate the pooled within-class covariance and compute the LDA boundary of a small data set by hand.
  • Show that the log-odds of two-class LDA are linear in the features, and say how LDA and logistic regression differ in the way they fit that form.
  • Explain when LDA tends to beat logistic regression and when logistic regression is the safer choice.

The question

Each class of the twelve points is a tilted cloud. Suppose we insist that all classes share one shape, the same covariance matrix, and differ only in where they sit. What does the boundary between them become, and why would anyone accept such a strong assumption?

From the last lesson

1. How are the axes of a Gaussian’s contour ellipses related to its covariance matrix?

Show answer

They point along the eigenvectors of \(\mat{\Sigma}\), and the ellipse \({\Delta = c}\) has semi-axes \({c\sqrt{\lambda_i}}\).

2. Write the squared Mahalanobis distance from \(\vect{x}\) to the mean.

Show answer

\({\Delta^2 = (\vect{x} - \vect{\mu})\T \mat{\Sigma}^{-1} (\vect{x} - \vect{\mu})}\).

Intuition

Give both classes the same ellipse and slide one copy over to the other mean. The two clouds are now identical apart from a shift. Walk along any straight line in the plane and the two densities rise and fall in the same way, one ahead of the other, so the place where they are equally high is a straight line too.

The twelve points with two identical ellipses, one around each class mean: a blue pair around (2.33, 2.33) and a sky-blue pair around (4.33, 3.33), both leaning slightly to the right. A thick vermillion line runs from about (3.8, minus 0.8) up to (2.8, 7.2); the region to its right is tinted and labelled predict 1, the left labelled predict 0. The line is labelled 125 x1 + 16 x2 = 462. Two points are ringed as on the wrong side: the blue circle at (5, 5) and the sky-blue square at (2, 5).
ML02.9.2-F1

Linear discriminant analysis on the twelve points. Both classes get the pooled covariance, so their ellipses are copies of each other and the boundary is the straight line \({125x_1 + 16x_2 = 462}\).

That straight line is linear discriminant analysis (LDA). It is one of the oldest classifiers in statistics, and it is still a strong, fast baseline: credit scoring and medical diagnosis used it for decades, and it remains the first thing to try when classes are few and examples are scarce.

Build it up

Step 1. Score each class in logs. As in the generative recipe of ML02.9.1, predict the class with the largest \({\pi_k\,N(\vect{x};\,\vect{\mu}_k, \mat{\Sigma})}\). The log is easier, and the largest stays the largest:

\[ \begin{aligned} &\ln \pi_k - \ln(2\pi) - \tfrac12\ln\det\mat{\Sigma} \\ &\quad - \tfrac12 (\vect{x} - \vect{\mu}_k)\T\mat{\Sigma}^{-1}(\vect{x} - \vect{\mu}_k). \end{aligned} \]

Step 2. Drop what every class shares. With one \(\mat{\Sigma}\) for all classes, \({-\ln(2\pi)}\) and \({-\tfrac12\ln\det\mat{\Sigma}}\) are the same in every score. They cannot change which score is largest.

Step 3. Open the bracket. The quadratic form contains a part with \(\vect{x}\) twice, a part with \(\vect{x}\) once and a part without it. The part with \(\vect{x}\) twice, \({\vect{x}\T\mat{\Sigma}^{-1}\vect{x}}\), does not depend on \(k\), so it drops out too. What is left is linear in \(\vect{x}\).

Step 4. See it as nearest mean. The picture behind the algebra: stretch the plane so that the shared ellipse becomes a circle. Then every class is a round cloud of the same size, and the closest mean wins (adjusted for the priors). The boundary between two round clouds of equal size is the perpendicular bisector of their means, a straight line, and stretching back keeps it straight.

Two panels joined by a green arrow labelled sphere with Sigma hat to the minus one half. Left, titled Shared ellipses: the twelve points with two identical tilted ellipses around the two means and the vermillion LDA line between them. Right, titled After sphering: the same points after the plane has been stretched; both ellipses are now circles of the same size, a dotted segment joins the two means, and the vermillion boundary crosses that segment at its midpoint at a right angle. Caption inside: circles; boundary bisects the means.
ML02.9.2-F2

Sphering. After the plane is stretched so that the shared covariance becomes the identity, LDA is “pick the nearest mean”, and the boundary is the perpendicular bisector of the two means.

The formal statement

NoteDefinition: linear discriminant analysis

Model each class as \({N(\vect{\mu}_k, \mat{\Sigma})}\) with one covariance shared by all classes, and priors \(\pi_k\). The linear discriminant function of class \(k\) is

\[ \begin{aligned} \delta_k(\vect{x}) &= \vect{x}\T\mat{\Sigma}^{-1}\vect{\mu}_k \\ &\quad - \tfrac12\vect{\mu}_k\T\mat{\Sigma}^{-1}\vect{\mu}_k + \ln\pi_k , \end{aligned} \]

and LDA predicts the class with the largest \(\delta_k(\vect{x})\).

Derivation. Start from the log score of Step 1 and drop the two constants. Expand the quadratic form, writing \({\mat{A} = \mat{\Sigma}^{-1}}\):

\[ \begin{aligned} &(\vect{x} - \vect{\mu}_k)\T\mat{A}(\vect{x} - \vect{\mu}_k) \\ &= \vect{x}\T\mat{A}\vect{x} - \vect{x}\T\mat{A}\vect{\mu}_k \\ &\quad - \vect{\mu}_k\T\mat{A}\vect{x} + \vect{\mu}_k\T\mat{A}\vect{\mu}_k . \end{aligned} \]

The two middle terms are equal. Each is a single number, a number is its own transpose, and \(\mat{A}\) is symmetric because \(\mat{\Sigma}\) is, so \({\vect{\mu}_k\T\mat{A}\vect{x} = (\vect{\mu}_k\T\mat{A}\vect{x})\T = \vect{x}\T\mat{A}\vect{\mu}_k}\). Hence

\[ \begin{aligned} &-\tfrac12(\vect{x} - \vect{\mu}_k)\T\mat{A}(\vect{x} - \vect{\mu}_k) \\ &= -\tfrac12\vect{x}\T\mat{A}\vect{x} + \vect{x}\T\mat{A}\vect{\mu}_k \\ &\quad - \tfrac12\vect{\mu}_k\T\mat{A}\vect{\mu}_k . \end{aligned} \]

The first term is the same for every class and drops out. Adding \({\ln\pi_k}\) to the other two gives \({\delta_k(\vect{x})}\). It is linear in \(\vect{x}\): a weight vector \({\mat{\Sigma}^{-1}\vect{\mu}_k}\) and an intercept.

Two classes: the log-odds are linear. The log-odds of class 1 against class 0 are \({\delta_1(\vect{x}) - \delta_0(\vect{x})}\), because the shared parts cancelled in both. Subtract:

\[ \begin{aligned} \delta_1 - \delta_0 &= \vect{x}\T\mat{A}(\vect{\mu}_1 - \vect{\mu}_0) \\ &\quad - \tfrac12\big(\vect{\mu}_1\T\mat{A}\vect{\mu}_1 - \vect{\mu}_0\T\mat{A}\vect{\mu}_0\big) \\ &\quad + \ln(\pi_1/\pi_0). \end{aligned} \]

For a symmetric \(\mat{A}\) the bracket factorises as \({(\vect{\mu}_1 + \vect{\mu}_0)\T\mat{A}(\vect{\mu}_1 - \vect{\mu}_0)}\) (exercise 2). So the log-odds are \({\vect{w}\T\vect{x} + b}\) with

\[ \begin{aligned} \vect{w} &= \mat{\Sigma}^{-1}(\vect{\mu}_1 - \vect{\mu}_0), \\ b &= -\tfrac12(\vect{\mu}_1 + \vect{\mu}_0)\T\vect{w} + \ln\frac{\pi_1}{\pi_0}, \end{aligned} \]

and the posterior is \({p(1 \mid \vect{x}) = \sigma(\vect{w}\T\vect{x} + b)}\), the sigmoid of ML01.6. LDA has exactly the form of logistic regression. The boundary \({\vect{w}\T\vect{x} + b = 0}\) is a straight line, a plane or a hyperplane, depending on the number of features.

Estimating the shared covariance. Each class contributes the scatter of its points about its own mean. The maximum-likelihood pooled covariance adds them up and divides by the number of points:

\[ \begin{aligned} \mat{S}_W &= \sum_k \sum_{i:\,y_i = k} \vect{v}_i\vect{v}_i\T, \\ \hat{\mat{\Sigma}} &= \frac{1}{n}\mat{S}_W = \sum_k \frac{n_k}{n}\hat{\mat{\Sigma}}_k , \end{aligned} \]

where \({\vect{v}_i = \vect{x}_i - \hat{\vect{\mu}}_k}\) is the deviation of a point from its own class mean.

It is the class covariances of ML02.9.1, averaged with weights \({n_k/n}\). The double sum \(\mat{S}_W\) is the within-class scatter matrix, which returns in ML02.9.4. Textbooks such as ESL divide by \({n - K}\) instead, which removes a small bias; scikit-learn divides by \(n\). With equal priors the boundary is the same either way. With unequal priors the cut moves a little, because rescaling \(\hat{\mat{\Sigma}}\) rescales \(\vect{w}\) but not \({\ln(\pi_1/\pi_0)}\).

Worked example

Fit LDA to the twelve points, with priors \({\pi_0 = \pi_1 = 1/2}\), and classify \({(3, 3)}\).

Scatter. Class 0’s scatter is six times its covariance, \({\tfrac13\begin{bmatrix}34 & 28\\ 28 & 34\end{bmatrix}}\); class 1’s is \({\tfrac13\begin{bmatrix}28 & -5\\ -5 & 40\end{bmatrix}}\). Their sum is

\[ \begin{aligned} \mat{S}_W &= \frac13\begin{bmatrix}62 & 23\\ 23 & 74\end{bmatrix}, \\ \hat{\mat{\Sigma}} &= \frac{\mat{S}_W}{12} = \frac{1}{36}\begin{bmatrix}62 & 23\\ 23 & 74\end{bmatrix}. \end{aligned} \]

A flow of boxes. Top left, blue: S W equals one third of the matrix 62, 23; 23, 74. Top right, blue: means (7/3, 7/3) and (13/3, 10/3), difference (2, 1). Middle left, vermillion: Sigma hat equals S W over 12, one thirty-sixth of the same matrix. Middle right: w equals Sigma hat inverse times the mean difference, (500, 64)/451 = (1.109, 0.142). Bottom left: b equals minus one half of the sum of the means times w, minus 1848/451 = minus 4.098. Bottom right: at (3, 3), w transpose x plus b = minus 0.346, P of class 1 = 0.414. A yellow box at the bottom: boundary w transpose x plus b = 0, that is 125 x1 + 16 x2 = 462. Green arrows join the boxes in this order.
ML02.9.2-F3

The worked example as a trace: from the scatter matrix to the weight vector, the intercept and the boundary.

Weight vector. The inverse of a 2 by 2 matrix swaps the diagonal, negates the off-diagonal and divides by the determinant. Here \({62 \cdot 74 - 23^2 = 4059}\), so

\[ \hat{\mat{\Sigma}}^{-1} = \frac{36}{4059}\begin{bmatrix}74 & -23\\ -23 & 62\end{bmatrix}. \]

With \({\hat{\vect{\mu}}_1 - \hat{\vect{\mu}}_0 = (2, 1)}\), the product is \({\tfrac{36}{4059}(148 - 23,\; -46 + 62)}\):

\[ \begin{aligned} \vect{w} &= \frac{36}{4059}\begin{bmatrix}125\\ 16\end{bmatrix} = \frac{1}{451}\begin{bmatrix}500\\ 64\end{bmatrix} \\ &\approx \begin{bmatrix}1.109\\ 0.142\end{bmatrix}. \end{aligned} \]

(\({4059 = 9 \cdot 451}\).) Almost all the weight is on \(x_1\): the classes differ mainly from left to right.

Intercept. The sum of the means is \({(20/3, 17/3)}\), and the priors are equal, so \({\ln(\pi_1/\pi_0) = 0}\):

\[ \begin{aligned} b &= -\tfrac12\cdot\frac{(20/3)\cdot 500 + (17/3)\cdot 64}{451} \\ &= -\frac{11088}{2706} = -\frac{1848}{451} \approx -4.098 . \end{aligned} \]

Boundary. \({\vect{w}\T\vect{x} + b = 0}\) means \({500x_1 + 64x_2 = 1848}\), or, dividing by 4, \({125x_1 + 16x_2 = 462}\). It passes through the midpoint of the means, \({(10/3, 17/6)}\), as it must with equal priors:

\[ \begin{aligned} &125 \cdot \tfrac{10}{3} + 16 \cdot \tfrac{17}{6} \\ &= 416.7 + 45.3 = 462 . \end{aligned} \]

The point \({(3, 3)}\). Here

\[ \begin{aligned} \vect{w}\T\vect{x} + b &= \frac{1500 + 192 - 1848}{451} \\ &= -\frac{156}{451} = -0.346, \end{aligned} \]

so

\[ p(1 \mid (3, 3)) = \frac{1}{1 + e^{0.346}} = 0.414, \]

and the point goes to class 0. On the training set, 10 of 12 points are right; the two ringed in the anchor figure, \({(5, 5)}\) and \({(2, 5)}\), sit across the line.

Code

From scratch for any number of classes, then checked against scikit-learn.

import numpy as np
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis

X = np.array([(1, 1), (2, 1), (1, 2), (2, 3), (3, 2), (5, 5),
              (4, 1), (5, 2), (5, 3), (4, 4), (2, 5), (6, 5)], dtype=float)
y = np.array([0] * 6 + [1] * 6)

def lda_fit(X, y):
    classes = np.unique(y)
    prior = np.array([np.mean(y == k) for k in classes])
    means = np.array([X[y == k].mean(axis=0) for k in classes])
    S_W = sum((X[y == k] - means[k]).T @ (X[y == k] - means[k]) for k in classes)
    Sigma = S_W / len(X)                                  # pooled, maximum likelihood
    W = np.linalg.solve(Sigma, means.T)                   # column k is Sigma^-1 mu_k
    c = -0.5 * np.sum(means.T * W, axis=0) + np.log(prior)
    return S_W, Sigma, W, c

def lda_scores(X, W, c):
    return X @ W + c                                      # delta_k(x) for every row and class

S_W, Sigma, W, c = lda_fit(X, y)
w, b = W[:, 1] - W[:, 0], c[1] - c[0]                     # two classes: log-odds w.x + b
print("S_W x 3:", (3 * S_W).round(4).tolist())
print("w =", w.round(4), " w x 451 =", (451 * w).round(4), " b =", round(b, 4))
p33 = 1 / (1 + np.exp(-(np.array([3.0, 3.0]) @ w + b)))
right = (lda_scores(X, W, c).argmax(axis=1) == y).sum()
print(f"P(class 1 | (3, 3)) = {p33:.4f}; training points right: {right} of 12")

lda = LinearDiscriminantAnalysis().fit(X, y)
print("scikit-learn coef_", lda.coef_.round(4), "intercept_", lda.intercept_.round(4),
      "P(1 | (3, 3))", lda.predict_proba([[3.0, 3.0]])[0, 1].round(4))
S_W x 3: [[62.0, 23.0], [23.0, 74.0]]
w = [1.1086 0.1419]  w x 451 = [500.  64.]  b = -4.0976
P(class 1 | (3, 3)) = 0.4144; training points right: 10 of 12
scikit-learn coef_ [[1.1086 0.1419]] intercept_ [-4.0976] P(1 | (3, 3)) 0.4144

For two classes, scikit-learn’s coef_ and intercept_ are the \(\vect{w}\) and \(b\) of the log-odds, and they match ours to every printed digit.

Now the same form fitted the other way. Logistic regression (ML01.6) also predicts \({\sigma(\vect{w}\T\vect{x} + b)}\), but it chooses \(\vect{w}\) and \(b\) to fit the labels directly. A very large C switches its penalty off almost entirely.

from sklearn.linear_model import LogisticRegression

logreg = LogisticRegression(C=1e4, max_iter=10000).fit(X, y)
w_lr, b_lr = logreg.coef_[0], logreg.intercept_[0]
print("logistic regression: w =", w_lr.round(2), " b =", round(b_lr, 2),
      " right:", int(logreg.score(X, y) * 12), "of 12")
for name, (ww, bb) in (("LDA", (w, b)), ("logistic", (w_lr, b_lr))):
    print(f"{name:9s} boundary crosses x2 = 0 at x1 = {-bb / ww[0]:.2f} and x2 = 6 at x1 = {-(bb + 6 * ww[1]) / ww[0]:.2f}")
logistic regression: w = [0.9  0.18]  b = -3.51  right: 10 of 12
LDA       boundary crosses x2 = 0 at x1 = 3.70 and x2 = 6 at x1 = 2.93
logistic  boundary crosses x2 = 0 at x1 = 3.89 and x2 = 6 at x1 = 2.68
The twelve points with two nearly vertical vermillion lines. The solid line, labelled LDA: from means and Sigma hat, runs from about (3.8, minus 0.6) to (2.9, 6.6). The dashed line, labelled logistic: from the labels, leans a little further from upright, from about (4.0, minus 0.6) to (2.6, 6.6). A note reads both: w transpose x plus b = 0.
ML02.9.2-F4

Two straight boundaries of the same form. LDA computes its line from the means and the pooled covariance; logistic regression searches for the line that best fits the labels.

The two lines are close but not equal. When is each better? ESL (section 4.4.5) puts the difference this way: LDA fits the full joint likelihood of features and labels, so it also uses how the features are spread; logistic regression fits only \({p(y \mid \vect{x})}\). When the classes really are Gaussian with a shared covariance, LDA’s extra assumption buys efficiency (Efron’s estimate, quoted there: in the worst case, ignoring it costs about 30% more data for the same error), and ISLR (section 4.4) adds that LDA then tends to win with small samples and stays stable when the classes are well separated, where the logistic estimates become unstable. The price is robustness: points far from the boundary still pull on \(\hat{\mat{\Sigma}}\), so LDA is hurt by gross outliers, and logistic regression is the safer bet when the Gaussian picture is doubtful. In practice the two often agree closely, as here.

Explore

The ellipse explorer is in lesson ML02.9.3. Switch on Shared covariance: the boundary becomes a straight line. Then turn one class’s ellipse and watch the line turn as well, although neither mean has moved: the shared covariance, not only the means, sets the direction of the boundary.

Pitfalls

Two panels with the same two classes of 50 sample points each: blue circles and sky-blue squares in long thin clouds that both lean at 45 degrees, one just above and to the left of the other. Left, marked with a cross and titled Nearest mean, plain distance: a vermillion boundary through the midpoint, at right angles to the line joining the means, cuts across both clouds, and many points are ringed in reddish purple as misclassified; caption errs 22% of the time. Right, marked with a tick and titled LDA: uses the shared tilt: the vermillion boundary runs between the two clouds along their length, and only a handful of points are ringed; caption errs 2% of the time.
ML02.9.2-F5

Wrong beside right, on two tilted clouds with a shared covariance. Ignoring the covariance cuts straight across both clouds; LDA cuts between them. The error rates are for the whole population.

“The LDA boundary is the perpendicular bisector of the two means.”

Not in general. The boundary is at right angles to \({\vect{w} = \mat{\Sigma}^{-1}(\vect{\mu}_1 - \vect{\mu}_0)}\), not to \({\vect{\mu}_1 - \vect{\mu}_0}\). The two directions agree when the shared covariance is a multiple of the identity (and then, with equal priors, the boundary is the bisector; ESL makes this remark in its discussion of Figure 4.5), or more generally when \({\vect{\mu}_1 - \vect{\mu}_0}\) happens to be an eigenvector of \(\mat{\Sigma}\). For long tilted clouds the difference is large: the nearest-mean rule errs 22% of the time, LDA 2%.

“LDA and logistic regression have the same form, so they give the same model.”

Same form, different fit. LDA plugs estimated means and a pooled covariance into a formula; logistic regression maximises the likelihood of the labels. They differ most when the data are not Gaussian or have outliers, and on data that a line separates perfectly, where the logistic estimates do not exist but LDA’s do.

“With unequal class sizes the boundary still passes through the midpoint of the means.”

The prior term \({\ln(\pi_1/\pi_0)}\) shifts it. A rarer class needs stronger evidence, so the line moves towards the rarer class’s mean (exercise 1), just as the threshold did in ML02.6.1.

Check yourself

Recall

1. Which assumption makes the discriminant functions linear?

Show answer

All classes share one covariance matrix \(\mat{\Sigma}\). Then \({\vect{x}\T\mat{\Sigma}^{-1}\vect{x}}\) and \({\ln\det\mat{\Sigma}}\) are the same for every class and drop out.

2. Write the linear discriminant function \(\delta_k(\vect{x})\).

Show answer

\({\delta_k(\vect{x}) = \vect{x}\T\mat{\Sigma}^{-1}\vect{\mu}_k}\) \({- \tfrac12\vect{\mu}_k\T\mat{\Sigma}^{-1}\vect{\mu}_k}\) \({+ \ln\pi_k}\).

3. How is the pooled covariance estimated?

Show answer

Add up each class’s scatter about its own mean, and divide by \(n\) (maximum likelihood, as scikit-learn does) or by \({n - K}\) (the unbiased version in ESL). Equivalently, average the class covariances with weights \({n_k/n}\).

4. For two classes, what are \(\vect{w}\) and \(b\) in the log-odds \({\vect{w}\T\vect{x} + b}\)?

Show answer

\({\vect{w} = \mat{\Sigma}^{-1}(\vect{\mu}_1 - \vect{\mu}_0)}\) and \({b = -\tfrac12(\vect{\mu}_1 + \vect{\mu}_0)\T\vect{w} + \ln(\pi_1/\pi_0)}\).

5. Name one situation that favours LDA and one that favours logistic regression.

Show answer

LDA: few examples and roughly Gaussian classes, or well-separated classes. Logistic regression: data far from Gaussian or with gross outliers.

Exercises

1. ★ For the twelve points, keep the means and \(\hat{\mat{\Sigma}}\) but set \({\pi_1 = 1/4}\). Find the new boundary and classify \({(4, 2)}\) under both priors.

Show solution

Only \(b\) changes, by \({\ln(\pi_1/\pi_0) = \ln(1/3) = -1.099}\). Since \({\vect{w}\T\vect{x} = 4(125x_1 + 16x_2)/451}\), the boundary \({\vect{w}\T\vect{x} = 1848/451 + \ln 3}\) becomes

\[ \begin{aligned} 125x_1 + 16x_2 &= 462 + \tfrac{451}{4}\ln 3 \\ &= 585.9 . \end{aligned} \]

At \({(4, 2)}\), \({125 \cdot 4 + 16 \cdot 2 = 532}\). That is above 462, so with equal priors the point goes to class 1; it is below 585.9, so with \({\pi_1 = 1/4}\) it goes to class 0. The line has moved right, towards the rarer class.

2. ★★ Show that for a symmetric matrix \(\mat{A}\),

\[ \begin{aligned} &\vect{\mu}_1\T\mat{A}\vect{\mu}_1 - \vect{\mu}_0\T\mat{A}\vect{\mu}_0 \\ &= (\vect{\mu}_1 + \vect{\mu}_0)\T\mat{A}(\vect{\mu}_1 - \vect{\mu}_0). \end{aligned} \]

Show solution

Expand the right-hand side:

\[ \begin{aligned} &(\vect{\mu}_1 + \vect{\mu}_0)\T\mat{A}(\vect{\mu}_1 - \vect{\mu}_0) \\ &= \vect{\mu}_1\T\mat{A}\vect{\mu}_1 - \vect{\mu}_1\T\mat{A}\vect{\mu}_0 \\ &\quad + \vect{\mu}_0\T\mat{A}\vect{\mu}_1 - \vect{\mu}_0\T\mat{A}\vect{\mu}_0 . \end{aligned} \]

The two middle terms are numbers, and transposing one gives the other because \({\mat{A}\T = \mat{A}}\): \({\vect{\mu}_0\T\mat{A}\vect{\mu}_1 = \vect{\mu}_1\T\mat{A}\T\vect{\mu}_0 = \vect{\mu}_1\T\mat{A}\vect{\mu}_0}\). So they cancel and the left-hand side remains. It is the matrix version of \({a^2 - c^2 = (a + c)(a - c)}\).

3. ★★★ Suppose \({\mat{\Sigma} = s^2\mat{I}}\) and the priors are equal. Show that LDA assigns \(\vect{x}\) to the class with the nearest mean, and that the two-class boundary is the perpendicular bisector of the means.

Show solution

With \({\mat{\Sigma}^{-1} = \mat{I}/s^2}\) and equal \({\ln\pi_k}\), which drop out,

\[ \delta_k(\vect{x}) = \frac{1}{s^2}\big(\vect{x}\T\vect{\mu}_k - \tfrac12\norm{\vect{\mu}_k}^2\big). \]

Since

\[ \begin{aligned} &\norm{\vect{x} - \vect{\mu}_k}^2 \\ &= \norm{\vect{x}}^2 - 2\vect{x}\T\vect{\mu}_k + \norm{\vect{\mu}_k}^2, \end{aligned} \]

we have

\[ \delta_k(\vect{x}) = \frac{\norm{\vect{x}}^2 - \norm{\vect{x} - \vect{\mu}_k}^2}{2s^2}. \]

The first term is the same for every class, so the largest \(\delta_k\) belongs to the smallest distance \({\norm{\vect{x} - \vect{\mu}_k}}\). The boundary between two classes is the set of points equally far from both means, which is the perpendicular bisector of the segment joining them.

Summary card

One shared covariance: the quadratic terms cancel and the boundary is a straight line.

The anchor figure again: the twelve points with two identical ellipses, one per class, and the straight vermillion LDA boundary 125 x1 + 16 x2 = 462.
ML02.9.2-F1

Same shape, straight boundary.

  • Discriminant: \({\delta_k(\vect{x}) = \vect{x}\T\mat{\Sigma}^{-1}\vect{\mu}_k}\) \({- \tfrac12\vect{\mu}_k\T\mat{\Sigma}^{-1}\vect{\mu}_k}\) \({+ \ln\pi_k}\).
  • Pooled covariance: \({\hat{\mat{\Sigma}} = \sum_k (n_k/n)\hat{\mat{\Sigma}}_k}\).
  • Two classes: \({p(1 \mid \vect{x}) = \sigma(\vect{w}\T\vect{x} + b)}\) with \({\vect{w} = \mat{\Sigma}^{-1}(\vect{\mu}_1 - \vect{\mu}_0)}\).
  • Versus logistic regression: same form, fitted from the joint likelihood instead of the labels alone.

Sources and next steps

Sources. Each was opened and checked against this lesson on 15 November 2026.

  • T. Hastie, R. Tibshirani and J. Friedman, The Elements of Statistical Learning, 2nd edition, corrected 12th printing (2017). Section 4.3: the linear discriminant functions, equation (4.10); the estimates of \(\pi_k\), \(\mu_k\) and the pooled covariance divided by \({N - K}\); the remark under Figure 4.5 that the boundaries are perpendicular bisectors only for a spherical covariance and equal priors; section 4.3.2 on sphering. Section 4.4.5: LDA and logistic regression have the same linear log-odds (4.33, 4.34) but are fitted by the full and the conditional likelihood; Efron’s 30% efficiency result; LDA is not robust to gross outliers; with separable data the logistic estimates are undefined.
  • G. James, D. Witten, T. Hastie and R. Tibshirani, An Introduction to Statistical Learning, 2nd edition (with R). Section 4.4: three reasons to prefer LDA (instability of logistic regression under substantial separation, small samples with roughly normal predictors, more than two classes); section 4.4.2: the discriminant function (4.24).
  • scikit-learn, Linear and Quadratic Discriminant Analysis, User Guide section 1.2 (the LDA log posterior and its coef_ and intercept_), and the LinearDiscriminantAnalysis reference: covariance_ is the weighted within-class covariance \({\sum_k \text{prior}_k C_k}\) built from the biased class covariances.

Next. ML02.9.3 Quadratic discriminant analysis and shrinkage lets every class keep its own covariance, and the line bends into a curve.

This lesson unlocks

ML02.9.3 Quadratic discriminant analysis and shrinkage

Your progress is saved in this browser only. No account, no tracking.
Back to top