Site icon Zdataset

A Brief Introduction to Linear Discriminant Analysis

This article was published as a part of the Data Science Blogathon

Introduction to LDA:

Linear Discriminant Analysis as its name suggests is a linear model for classification and dimensionality reduction.  Most commonly used for feature extraction in pattern classification problems. This has been here for quite a long time. First, in 1936 Fisher formulated linear discriminant for two classes, and later on, in 1948 C.R Rao generalized it for multiple classes. LDA projects data from a D dimensional feature space down to a D’ (D>D’) dimensional space in a way to maximize the variability between the classes and reducing the variability within the classes.

Why LDA?:

Shortcomings:

We will discuss this later.

Assumptions:

LDA makes some assumptions about the data:

However, it is worth mentioning that LDA performs quite well even if the assumptions are violated.

Fisher’s Linear Discriminant:

LDA is a generalized form of FLD. Fisher in his paper used a discriminant function to classify between two plant species Iris Setosa and Iris Versicolor.

The basic idea of FLD is to project data points onto a line to maximize the between-class scatter and minimize the within-class scatter.

This might sound a bit cryptic but it is quite straightforward. So, before delving deep into the derivation part we need to get familiarized with certain terms and expressions.

Datapoint X before and after projection

Scatter matrix: Used to make estimates of the covariance matrix. IT is a m X m positive semi-definite matrix.

Given by: sample variance * no. of samples.

Note: Scatter and variance measure the same thing but on different scales. So, we might use both words interchangeably. So, do not get confused.

Here we will be dealing with two types of scatter matrices

Now, assuming we are clear with the basics let’s move on to the derivation part.

As per Fisher’s LDA :

arg max J(W) = (M1 – M2)2 / S1+ S22       ………..    (1)

The numerator here is between class scatter while the denominator is within-class scatter.So tomaximize the function we need to maximize the numerator and minimize the denominator, simple math. To maximize the above function we need to first express the above equation in terms of W. 

Numerator:

Denominator:

For denominator we have S1+ S22  . 

Now, we have both the numerator and denominator expressed in terms of W

J(W) = WTSbW / WTSwW

Upon differentiating the above function w.r.t W and equating with 0, we get a generalized eigenvalue-eigenvector problem

SbW = vSwW    

Sw being a full-rank matrix , inverse is feasible

=> Sw-1SbW = vW

Where v = eigen value

W = eigen vector

LDA for multiple classes:

LDA can be generalized for multiple classes. Here are the generalized forms of between-class and within-class matrices.

Note: Sis the sum of C different rank 1 matrices. So, the rank of Sb <=C-1. That means we can onlyhave C-1 eigenvectors. Thus, we can project data points to a subspace of dimensions at most  C-1.

Above equation (4) gives us scatter for each of our classes and equation (5) adds all of them to give within-class scatter. Similarly, equation (6) gives us between-class scatter. Finally, eigendecomposition of Sw-1Sgives us the desired eigenvectors from the corresponding eigenvalues. Total eigenvalues can be at most C-1.

LDA for classification:

Until now, we only reduced the dimension of the data points, but this is strictly not yet discriminant. But the projected data can subsequently be used to construct a discriminant by using Bayes’ theorem as follows.

Assume X = (x1….xp) is drawn from a multivariate Gaussian distribution. K be the no. of classes and Y is the response variable. pik isthe prior probability: the probability that a given observation is associated with Kth class. Pr(X = x | Y = k) is the posterior probability.

Let fk(X) = Pr(X = x | Y = k) is our probability density function of X for an observation x thatbelongs to Kth class. fk(X) islarge if there is a high probability of an observation in  Kth class has X=x. 

As per Bayes’ theorem,

Now, to calculate the posterior probability we will need to find the prior pik and density function fk(X). 

pican be calculated easily. If we have a random sample of Ys from the population: we simply compute the fraction of the training observations that belong to Kth class. But the calculation of fk(X) can be a little tricky.

We assume thatthe probability density function of x is multivariate Gaussian with class means mk and a common covariance matrix sigma.

As a formula, multi-variate Gaussian density is given by:

|sigma| = determinant of covariance matrix ( same for all classes)

mk = class means

Now, by plugging the density function in the equation (8), taking the logarithm and doing some algebra, we will find the Linear score function

We will classify a sample unit to the class that has the highest Linear Score function for it.

Note that in the above equation (9) Linear discriminant function depends on x linearly, hence the name Linear Discriminant Analysis.

Addressing LDA shortcomings:

Linearity problem: LDA is used to find a linear transformation that classifies different classes. But if the classes are non-linearly separable, It can not find a lower-dimensional space to project. This problem arises when classes have the same means i.e, the discriminatory information does not exist in mean but in the scatter of data. That will effectively make Sb=0. To address this issue we can use Kernel functions. As used in SVM, SVR etc. The idea is to map theinput data to a newhigh dimensional feature space by a non-linear mapping where inner products in the feature space can be computed by kernel functions.

Small Sample problem: This problem arises when the dimension of samples is higher than the number of samples (D>N). This is the most common problem with LDA. The covariance matrix becomes singular, hence no inverse. So, to address this problem regularization was introduced. Instead of using sigma or the covariance matrix directly, we use

Here, alpha is a value between 0 and 1.and is a tuning parameter. i is the identity matrixThe diagonal elements of the covariance matrix are biased by adding this small element. However, the regularization parameter needs to be tuned to perform better.

Scikit Learn’s LinearDiscriminantAnalysis has a shrinkage parameter that is used to address this undersampling problem. It helps to improve the generalization performance of the classifier. when this is set to ‘auto’, this automatically determines the optimal shrinkage parameter. Remember that it only works when the solver parameter is set to ‘lsqr’ or ‘eigen’. This can manually be set between 0 and 1.There are several other methods also used to address this problem. Such as a combination of PCA and LDA. PCA first reduces the dimension to a suitable number then LDA is performed as usual.

Python Implementation:

Fortunately, we don’t have to code all these things from scratch, Python has all the necessary requirements for LDA implementations. For the following article, we will use the famous wine dataset.

Importing required libraries:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.metrics import confusion_matrix

Preparing dataset:

from sklearn.datasets import load_wine
dt = load_wine()
X = dt.data
y = dt.target

Fitting LDA to wine dataset:

lda = LinearDiscriminantAnalysis()
lda_t = lda.fit_transform(X,y)

Variance explained by each component:

lda.explained_variance_ratio_

Plotting LDA components:

plt.xlabel('LD1')
plt.ylabel('LD2')
plt.scatter(lda_t[:,0],lda_t[:,1],c=y,cmap='rainbow',edgecolors='r')

LDA for classification:

X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.3)
lda.fit(X_train,y_train)

Accuracy Score:

y_pred = lda.predict(X_test)
print(accuracy_score(y_test,y_pred))

Confusion Matrix:

confusion_matrix(y_test,y_pred)

Plotting Decision boundary for our dataset:

min1,max1 = lda_t[:,0].min()-1, lda_t[:,0].max()+1
min2,max2 = lda_t[:,1].min()-1,lda_t[:,1].max()+1
x1grid = np.arange(min1,max1,0.1)
x2grid = np.arange(min2,max2,0.1)
xx,yy = np.meshgrid(x1grid,x2grid)
r1,r2 = xx.flatten(),yy.flatten()
r1,r2 = r1.reshape((len(r1),1)), r2.reshape((len(r2),1))
grid = np.hstack((r1,r2))

model = LinearDiscriminantAnalysis()
model.fit(lda_t,y)
yhat = model.predict(grid)
zz = yhat.reshape(xx.shape)
plt.contourf(xx,yy,zz,cmap='Accent')

for class_value in range(3):
  row_ix = np.where( y== class_value)
  plt.scatter(lda_t[row_ix,0],lda_t[row_ix,1])

So, this was all about LDA, its mathematics, and implementation. Hope it was helpful.

Thanks for reading.

Source: An Introduction to Statistical Learning with Applications in R – Gareth James, DanielaThe media shown in this article are not owned by Analytics Vidhya and are used at the Author’s discretion.

Exit mobile version