机器学习之线性判别分析(Linear Discriminant Analysis)

1 线性判别分析介绍

1.1 什么是线性判别分析

线性判别分析(Linear Discriminant Analysis,简称LDA)是一种经典的监督学习算法,也称"Fisher 判别分析"。LDA在模式识别领域(比如人脸识别,舰艇识别等图形图像识别领域)中有非常广泛的应用。

LDA的核心思想是给定训练样本集,设法将样例投影到一条直线上。使得同类样例的投影点尽可能接近、异类样例的投影点尽可能远;在对新样本进行分类时,将其投影到该直线上,再根据投影点的位置来确定新样本的类别。

与自然语言处理领域中的LDA不同,在自然语言处理领域,LDA是隐含狄利克雷分布(Latent DIrichlet Allocation,简称LDA),它是一种处理文档的主题模型,我们本文讨论的是线性判别分析,因此后面所说的LDA均为线性判别分析。

1.2 为什么要学习LDA算法

PCA是一种无监督的数据降维方法,LDA是一种有监督的数据降维方法。在训练样本上,即使对数据提供了类别标签,在使用PCA模型的时候不会使用类别标签,而LDA在进行数据降维的时候是利用类别标签的。

从几何的角度来看,PCA和LDA都是将数据投影到新的相互正交的坐标轴上。只不过在投影的过程中他们使用的约束是不同的,也可以说目标是不同的。PCA是将数据投影到方差最大的几个相互正交的方向上,以期待保留最多的样本信息。样本的方差越大表示样本的多样性越好,在训练模型的时候,我们当然希望数据的差别越大越好。否则即使样本很多但是他们彼此相似或者相同,提供的样本信息将相同,相当于只有很少的样本提供信息是有用的。样本信息不足将导致模型性能不够理想。这就是PCA降维的目的:将数据投影到方差最大的几个相互正交的方向上。这种约束有时候很有用,比如在下面这个例子:

对于这个样本集我们可以将数据投影到 x 轴或者 y 轴,但这都不是最佳的投影方向,因为这两个方向都不能最好的反映数据的分布。很明显还存在最佳的方向可以描述数据的分布趋势,那就是图中红色直线所在的方向。也是数据样本作投影,方差最大的方向。向这个方向做投影,投影后数据的方差最大,数据保留的信息最多。

但是,对于另外的一些不同分布的数据集,PCA的这个投影后方差最大的目标就不太适合了。比如对于下面图片中的数据集:

针对这个数据集,如果同样选择使用PCA,选择方差最大的方向作为投影方向,来对数据进行降维。那么PCA选出的最佳投影方向,将是图中红色直线所示的方向。这样做投影确实方差最大,但是是不是有其他问题。聪明的你发现了,这样做投影之后两类数据样本将混合在一起,将不再线性可分,甚至是不可分的。这对我们来说简直是地狱,本来线性可分的样本被我们亲手变得不再可分。而我们发现,如果使用图中黄色直线,向这条直线做投影即能使数据降维,同时还能保证两类数据仍然是线性可分的。上面的这个数据集如果使用LDA降维,找出的投影方向就是黄色直线所在的方向。

这其实就是LDA的思想,或者说LDA降维的目标:将带有标签的数据降维,投影到低维空间同时满足三个条件:

  • 尽可能多的保留数据样本的信息(即选择最大的特征是对应的特征向量所代表的方向)。
  • 寻找使样本尽可能好分的最佳投影方向。
  • 投影后使得同类样本尽可能近,不同类样本尽可能远。

1.3 LDA的思想

LDA的核心思想:类内小,类间大

  • 线性分类

指存在一个线性方程可以把待分类数据分开,或者说用一个超平面能将正负样本区分开,表达式为y=wx,这里先说一下超平面,对于二维的情况,可以理解为一条直线,如一次函数。它的分类算法是基于一个线性的预测函数,决策的边界是平的,比如直线和平面。一般的方法有感知器,最小二乘法。

  • 非线性分类

指不存在一个线性分类方程把数据分开,它的分类界面没有限制,可以是一个曲面,或者是多个超平面的组合。

LDA是一种监督学习的降维技术,也就是说它的数据集的每个样本是有类别输出的。这点和PCA不同,PCA是不考虑样本类别输出的无监督降维技术。LDA的思想可以用一句话概述,就是“投影后类内方差最小,类间方差最大”,什么意思呢?我们要将数据在低维度上进行投影,投影后希望每一种类别数据的投影点尽可能的接近,而不同类别的数据的类别中心之间的距离尽可能的大。

假设我们有两类数据分别是红色和蓝色,如下图所示,这些数据特征是二维的,我们希望将这些数据投影到一维的一条直线,让每一种类别数据的投影点尽可能的接近,而红色和蓝色数据中心之间的距离尽可能的大。

上图中提供了两种投影方式,从直观上看出,右边要比左边图的投影效果好,因为右边图的红色数据进而蓝色数据各个较为集中,且类别之间的距离明显,左边的则在边界处数据混杂。以上就是LDA的主要思想。在实际应用中,我们的数据是多个类别的,原始数据一般也是超过二维的,投影后的也一般不是直线,而是一个低维的超平面。

周志华老师的《机器学习》中简述了线性判别分析的中心思想,可以联想到方差分析中的组内偏差SSE和组间偏差SSA(Fisher线性判别分析和方差分析的发明者都是R.A.Fisher)。

Fisher判别分析的思想非常朴素:给定训练样本例集,设法将样例投影到一条直线上,使得同类样例的投影点尽可能接近,不同类样例的投影点尽可能远离。在对新样本进行分类时,将其投影到同样的这条直线上,再根据新样本投影点的位置来确定它的类别。

1.4 LDA算法的优化目标

LDA的原理:投影到维度更低的空间中,使得投影后的点,会形成按类别区分,一簇一簇的情况,相同类别的点,将会在投影后的空间中更接近方法。下图来自周志华《机器学习》,给出了一个二维示意图:

什么是线性判别分析呢?所谓的线性就是,我们要将数据点投影到直线上(可能是多条直线),直线的函数解析式又称为线性函数,通常直线的表达式为:

其实这里的 x 就是样本向量(列向量),如果投影到一条直线上 w 就是一个特征向量(列向量形式)或者多个特征向量构成的矩阵。至于 w 为什么是特征向量,后面我们就能推导出来。 y 为投影后的样本点(列向量)。我们首先使用两类样本来说明,然后再推广到多类问题。

将数据投影到直线 w 上,则两类样本的中心在直线上的投影分别为 W^{T}\mu _{0}W^{T}\mu _{1},若将所有的样本点都投影到直线上,则两类样本的协方差分别为 W^{T}\sum _{0}WW^{T}\sum _{1}W

投影后同类样本协方差矩阵的求法:

上式的中间部分(即第二行的式子)就是同类样本投影前的协方差矩阵。还可以看出同类样本投影前后协方差矩阵之间的关系。如果投影前的协方差矩阵为 \sum则投影后的为 W^{T}\sum W

上式的推导需要用到如下公式,a,b都是列向量:

欲使同类样例的投影点尽可能接近,可以让同类样本点的协方差矩阵尽可能小,即下面式子尽可能小:

欲使异类样例的投影点尽可能远离,可以让类中心之间的距离尽可能大,即下面式子尽可能大:

同时考虑二者,则可得到最大化的目标

 上式 ||*|| 表示欧几里得范数,其中:

上面说的同类样本点的协方差矩阵尽可能小,同类样例的投影点就尽可能接近,这句话如何理解呢?我们在最初接触协方差是用来表示两个变量的相关性,我们来看一下协方差和方差的公式:

可以看到协方差的公式和方差十分相近,甚至可以说方差是协方差的一种特例。我们知道方差可以用来度量数据的离散程度,(X - Xhat)越大,表示数据距离样本中心越远,数据越离散,数据的方差越大。同样我们观察,协方差的公式,(X - Xhat)和(Y - Yhat)越大,表示数据距离样本中心越远,数据分布越分散,协方差越大。相反他们越小表示数据距离样本中心越近,数据分布越集中,协方差越小。

所以协方差不仅是反映了变量之间的相关性,同样反映了多维样本分布的离散程度(一维样本使用方差),协方差越大(对于负相关来说是绝对值越大),表示数据的分布越分散。所以欲使同类样例的投影点尽可能接近,可以让同类样本点的协方差矩阵尽可能小。

首先LDA分类的一个目标是使得不同类别之间的距离越远越好,同一类别之中的距离越近越好。那么不同类别之间的距离越远越好,我们是可以理解的,就是越远越好区分。

比如每类样例的均值为:

 而投影后的均值为:

那投影后的两类样本中心点尽量分离:

那是不是说我们只最大化J(w) 就可以了?实际情况当然不是,比如下面情况:

我们发现,对上图来说,假设我们只有两种分类方向,一种是X1方向,一种是 X2方向。

我们看到X1的方向可以最大化J(w)的值,但是却分的不好,μ1 和 μ2 两个数据集之间还有交叉。但是X2方向,虽然不会最大化J(w)的值,但是却分的好。

基于这个问题,我们提出了散列值(也就是样本点的密集程度),当散列值越大,越分散,反之越集中。我们肯定是希望同类之间应该更密集些,表示如下:

所以,总结来说,就是我们希望不同类样本中心值尽量越分散越好,也就是J(w) 越大越好,而同类之间距离越小越好,也就是散列值之和越小越好。我们最终还是希望J(w)越大越好,所以我们可以将公式写成下面方式,基于此,我们得到目标函数为:

分子展示如下(其中SB称为类间散布矩阵):

散列值公式展示:

散列矩阵(scatter  matrices):

类间散布矩阵:

其中:

最终目标函数为:

瑞利商(Rayleigh quotient)与广义瑞利商(genralized Rayleigh quotient)

瑞利商是指这样的函数R(A, x):

其中 x 为非零向量,而A为 n*n 的Hermitan矩阵。所谓的 Hermitan矩阵就是满足共轭转置矩阵和自己相等的矩阵,即AH=A。如果我们的矩阵A是实矩阵,则满足 A^{H}=A的矩阵即为Hermitan矩阵。

瑞利商R(A,  x) 有一个非常重要的性质,即它的最大值等于矩阵A最大的特征值,而最小值等于矩阵A的最小的特征值,也就是满足:

当向量 x 是标准正交基时,即满足 X^{H}X=1= 1时,瑞利商退化为:R(A,X)=X^{H}AX,这个形式在谱聚类和PCA中都有出现。

广义瑞利商是指这样的函数 R(A, B, x):

其中 x 为非零向量,而A, B为 n*n 的Hermitan矩阵。B为正定矩阵。它的最大值和最小值是什么呢?其实我们只要通过标准化就可以转化为瑞利商的格式。我们令 X=B^{-1/2}X^{​{}'},则分母转化为:

而分子转化为:

此时我们的 R(A, B, x) 转化为 R(A, B, x'):

利用前面的瑞利商的性质,我们可以很快的知道,R(A, B, x')的最大值为矩阵B^{-1/2}AB^{-1/2} 的最大特征值,或者说矩阵B^{-1}A的最大特征值,而最小值为矩阵B^{-1}A的最小特征值(这里对矩阵进行了标准化)。

1.5 二类LDA原理

LDA希望投影后希望同一种类别数据的投影点尽可能的接近,而不同类别的数据的类别中心之间的距离尽可能的大,但是这只是一个感官的度量。现在我们首先从比较简单的二类LDA入手,严谨的分析LDA的原理。

LDA的原理:投影到维度更低的空间中,使得投影后的点,会形成按类别区分,一簇一簇的情况,相同类别的点,将会在投影后的空间中更接近方法

假设我们的数据集 D={(x1, y1),  (x2, y2), .... (xm, ym)},其中任意样本 xi 为n维向量,yi属于{0, 1}。我们定义 Nj(j=0, 1)为第 j 类样本的个数,Xj(j = 0, 1)为第 j 类 样本的集合,而 μj(j=0, 1)为第 j 类样本的均值向量,定义 Σj(j=0, 1) 为第 j 类样本的协方差矩阵(严格说是缺少分母部分的协方差矩阵)。

μj 的表达式为:

 其中 j = 0, 1

Σj的表达式为:

由于是两类数据,因此我们只需要将数据投影到一条直线上即可。假设我们的投影直线是向量 w,则对任意一个样本 xi,它在直线 w 上的投影为W^{T}X_{i},对于我们的两个类别的中心点 μ0, μ1,在直线 w 的投影为 W^{T}\mu _{0}W^{T}\mu _{1}。由于LDA需要让不同类别的数据的类别中心之间的距离尽可能的大,也就是我们要最大化  \left \| W^{T}\mu _{0}-W^{T}\mu _{1} \right \|^2{_{2}} ,同时我们希望同一种类别数据的投影点尽可能的接近,也就是要同类样本投影点的协方差W^{T}\sum _{0}WW^{T}\sum _{1}W尽可能的小,即最小化 W^{T}\sum _{0}W+W^{T}\sum _{1}W。综上所述,我们的优化目标为:

类内散度矩阵

我们一般定义类内散度矩阵 Sw为:

类间散度矩阵

类间散度矩阵其实就是协方差矩阵乘以样本数目,即散度矩阵与协方差矩阵只是相差一个系数。

同时定义类间散度矩阵 Sb为:

定义过类内散度矩阵和类间散度矩阵后,我们就可以将上述的优化目标重写为:

利用我们提到的广义瑞利商的性质,我们知道我们的 J(w') 最大值为矩阵 Sw-1/2SbSw-1/2 的最大特征值,而对应的w' 为S_{W}^{-1/2}S_{b}S_{W}^{-1/2}的最大特征值对应的特征向量!,而S_{W}^{-1/2}S_{b}的最大特征值对应的特征向量!,而S_{W}^{-1}S_{b}的特征值和S_{W}^{-1/2}S_{b}S_{W}^{-1/2}的特征值相同, S_{W}^{-1}S_{b}的特征向量 w' 满足 W=S_{W}^{-1/2}{W}'的关系。

注意到对于二类的时候,Sbw 的方向恒平行于 μ0 - μ1,不妨令 S_{b}W=\lambda (\mu _{0}-\mu _{1}),将其代入:(S_{W}^{-1}S_{b})W=\lambda W,可以得到W=S_{W}^{-1} (\mu _{0}-\mu _{1}) ,也就是我们只要求出原始二类样本的均值和方差就可以确定最佳的投影方向 w 了。

注意上面的分子和分母都是关于 w 的二次项,因此上面的解与 w 的长度无关,只与其方向有关,不失一般性,我们令:

(我们对分母进行归一化:因为如果分子,分母都是可以取任意值的,那就会使得有无穷解,我们将分母限制为长度为1)

 则优化目标等价于:

 使用拉格朗日乘子法,上式等价于:

可以看到上式就有转换为一个求解特征值和特征向量的问题了。W就是我们矩阵SW-1SB要求解的特征向量,这就验证了我们之前所说的式子:

w 就是特征向量构成的矩阵。但是在这里我们仍然有个问题要解决,就是Sw是否可逆,遗憾的是在实际的应用中,它通常是不可逆的,我们通常有两个办法解决它。

  • 方法1:令 Sw = Sw + γ I ,其中 γ 是一个特别小的数,这样 Sw一定可逆。
  • 方法2:先用PCA对数据进行降维,使得在降维后的数据上 Sw可逆,再使用LDA。

1.6 多类 LDA

假设我们的数据集 D={(x1, y1),  (x2, y2), .... (xm, ym)},其中任意样本 xi 为n维向量,yi属于{C1, C2,...  ,Ck}。我们定义 Nj(j=1, 2, ... k)为第 j 类样本的个数,Xj(j = 1, 2, ....k)为第 j 类样本的均值向量,定义 Σj(j = 1, 2, 3, ...k) 为第 j 类样本的协方差矩阵。在二类 LDA 里面定义的公式可以很容易的类推到多类LDA。

由于我们是多类向低维投影,则此时投影到的低维空间就不是一条直线,而是一个超平面了。假设我们投影到的低维空间的维度为 d,对应的基向量为 (w1, w2, ....wd),基向量组成的矩阵为 W,它是一个 n*d 的矩阵。

此时我们的优化目标应该可以变成为:

其中:μ 为所有样本均值向量

但是有一个问题,就是W^{T}S_{b}WW^{T}S_{W}W都是矩阵,不是标量,无法作为一个标量函数来优化!也就是说,我们无法直接用二类LDA的优化方法,怎么做呢?一般来说,我们使用其他的一些替代优化目标来实现。

常见的一个 LDA多类优化目标函数定义为:

其中  ∏A 为 A的主对角线元素的乘积,W为 n*d 的矩阵。

仔细观察上式最右边,这不就是广义瑞利商嘛!最大值是矩阵 S_{W}^{-1}S_{b}的最大特征值,最大的 d 个值的乘积就是矩阵 S_{W}^{-1}S_{b}的最大的 d个特征值的乘积,此时对应的矩阵 W 为这最大的 d 个特征值对应的特征向量张成的矩阵。

由于 W 是一个利用了样本的类别得到的投影矩阵,因此它的降维到的维度 d 最大值为 k-1,为什么最大维度不是类别 k 呢?因为Sb中每个 μj - μ 的秩为1,因此协方差矩阵相加后最大的秩为 k(矩阵的秩小于等于各个相加矩阵的秩的和),但是由于我们知道前 k-1 个 μj 后,最后一个 μk 可以由前 k-1 个 μj 线性表示,因此Sb的秩最大为 k-1,即特征向量最多有 K-1个。

1.7 LDA 算法流程

  下面我们对 LDA 降维的流程做一个总结。

  输入:数据集 D = {(x1, y1),  (x2, y2), .... (xm, ym)},其中任意样本 xi 为 n维向量, yi € {C1,  c2, ...Ck},降维到的维度 d。

  输出:降维后的样本集 D'

  • 1)计算类内散度矩阵Sw
  • 2)计算类间散度矩阵 Sb
  • 3)计算矩阵Sw-1Sb
  • 4)计算 Sw-1Sb 的最大的 d个特征值和对应的 d个特征向量 (w1, w2, ... wd),得到投影矩阵 W
  • 5)对样本集中的每一个样本特征 xi,转化为新的样本 Z_{i}=W^{T}X_{i}
  • 6)得到输出样本集 D' = {(z1, y1),  (z2, y2), .... (zm, ym)}

  以上就是使用 LDA 进行降维的算法流程。实际上LDA除了可以用于降维以外,还可以用于分类。一个常见的LDA分类基本思想是假设各个类别的样本数据符合高斯分布,这样利于LDA进行投影后,可以利用极大似然估计计算各个类别投影数据的均值和方差,进而得到该类别高斯分布的概率密度函数。当一个新的样本到来后,我们可以将它投影,然后将投影后的样本特征分别代入各个类别的高斯分布概率密度函数,计算它属于这个类别的概率,最大的概率对应的类别即为预测类别。

1.8 LDA vs PCA

LDA用于降维,和PCA有很多相同,也有很多不同的地方,因此值得好好地比较一下两者的降维异同点。首先我们看看相同点:

  • 两者均可以对数据进行降维
  • 两者在降维时均使用了矩阵特征分解的思想
  • 两者都假设数据符合高斯分布

不同点:

  • LDA 是由监督的降维方法,而PCA是无监督的降维方法
  • LDA降维最多降到类别数 k-1 的维度,而PCA没有这个限制
  • LDA除了可以用于降维,还可以用于分类
  • LDA选择分类性能最好的投影方向,而PCA选择样本点投影具有最大方差的方向

第四点可以从下图形象的看出,在某些数据分布下LDA比PCA降维较优

当然,某些数据分布下,PCA 比 LDA 降维较优,如下图所示:

 

2 LDA的优缺点

LDA是一种监督学习算法,用于将数据点投影到低维空间中,以实现分类任务。LDA算法的优缺点如下:

2.1 LDA优点

  • 降维效果优秀:LDA通过将数据点投影到低维空间,能够较好地保留类别之间的差异,从而实现对数据进行有效降维。在一些特征较多的数据集上,LDA能够显著减少计算复杂度,提高分类效率。

  • 考虑类别间差异:LDA不仅仅关注数据点在特征空间内的分布,还同时考虑了不同类别之间的差异。它试图最大化类别间的距离,从而更好地区分不同类别。

  • 可解释性强:LDA的投影向量是具有物理意义的,可以被解释为类别之间的线性差异。

  • 适用于多分类问题:LDA在处理多分类问题时表现良好,可以有效地将多个类别区分开来。

2.2 LDA缺点

  • 假设数据符合高斯分布:LDA对数据的分布做了严格的假设,即数据在每个类别内部服从高斯分布,且各个类别的协方差矩阵相等。在现实世界的一些复杂数据集中,这些假设可能不成立,从而影响LDA的性能。

  • 对异常值敏感:由于LDA的假设基于数据服从高斯分布,当数据集中存在异常值时,可能导致投影结果不准确。

  • 无法处理非线性关系:LDA是一种线性分类器,对于具有复杂非线性关系的数据集,其表现可能不佳。在这种情况下,可以考虑使用核化LDA等非线性方法。

  • 受维度灾难影响:当特征维度非常高时,LDA的性能可能会下降。虽然LDA可以进行降维,但当特征维度过大时,可能会导致类别内部的协方差矩阵估计不准确,影响分类效果。

3 LDA的应用场景

LDA在许多实际问题中都有广泛的应用,在应用LDA之前,需要确保数据符合LDA的假设,即数据在每个类别内部服从高斯分布,并且各个类别的协方差矩阵相等。对于非线性问题,可能需要考虑使用核化LDA或其他非线性方法来处理。

LDA常见的应用场景如下:

  • 模式识别和分类:LDA是一种监督学习算法,特别适用于解决分类问题。它可以用于将数据点投影到低维空间,并根据类别间的差异来划分不同类别。

  • 人脸识别:在计算机视觉领域,LDA常常用于人脸识别任务。通过将人脸图像投影到低维空间,可以实现对不同人脸的分类和识别。

  • 文本分类:在自然语言处理中,LDA可以用于文本分类任务。通过将文本表示为向量,并应用LDA进行降维和分类,可以实现对文本数据的分类和情感分析。

  • 生物信息学:LDA可以应用于基因表达数据分析和蛋白质功能分类等生物信息学问题,帮助识别不同基因或蛋白质的功能和分类。

  • 医学诊断:在医学领域,LDA可以用于疾病诊断和医学图像分析。例如,通过将医学图像数据降维并进行分类,可以帮助医生做出更准确的诊断。

  • 视频行为识别:LDA在视频分析中也有应用,可以帮助识别视频中的不同行为和动作,例如动作识别、运动分析等。

  • 财务分析:在金融领域,LDA可以用于对金融数据进行分类和预测,例如对股票市场趋势进行预测、信用评级等。

4 LDA代码实现鸢尾花数据降维

4.1 数据集介绍

Iris 鸢尾花数据集是一个经典数据集,在统计学习和机器学习领域都经常被用作示例。数据集内包含 3 类共 150 条记录,每类各 50 个数据,每条记录都有 4 项特征:花萼长度、花萼宽度、花瓣长度、花瓣宽度,可以通过这4个特征预测鸢尾花卉属于(iris-setosa, iris-versicolour, iris-virginica)三种中的哪一品种。

数据内容:

     sepal_len  sepal_wid  petal_len  petal_wid  label
0          5.1        3.5        1.4        0.2      0
1          4.9        3.0        1.4        0.2      0
2          4.7        3.2        1.3        0.2      0
3          4.6        3.1        1.5        0.2      0
4          5.0        3.6        1.4        0.2      0
..         ...        ...        ...        ...    ...
145        6.7        3.0        5.2        2.3      2
146        6.3        2.5        5.0        1.9      2
147        6.5        3.0        5.2        2.0      2
148        6.2        3.4        5.4        2.3      2
149        5.9        3.0        5.1        1.8      2

4.2 原生代码实现

import numpy as np
from sklearn.datasets import load_iris
from sklearn.preprocessing import MinMaxScaler
import matplotlib.pyplot as plt
import matplotlib.pyplot as plt2


# 定义LDA类
class LDA:
    def __init__(self, n_components=2, kernel='rbf', gamma=400):
        self.n_components = n_components
        self.kernel = kernel
        self.gamma = gamma

    def fit(self, X, y):
        # 计算内部和外部类别散度矩阵
        X_mean = np.mean(X, axis=0)
        S_W = np.zeros((X.shape[1], X.shape[1]))
        S_B = np.zeros((X.shape[1], X.shape[1]))
        for i in range(3):
            X_class = X[y == i, :]
            X_class_mean = np.mean(X_class, axis=0)
            S_W += np.dot((X_class - X_class_mean).T, (X_class - X_class_mean))
            S_B += len(X_class) * np.dot((X_class_mean - X_mean).reshape(-1, 1), (X_class_mean - X_mean).reshape(1, -1))

        # 使用LDA算法计算投影矩阵W
        eig_val, eig_vec = np.linalg.eig(np.dot(np.linalg.inv(S_W), S_B))
        idx = np.argsort(-eig_val.real)
        self.W = eig_vec[:, idx[:self.n_components]]

        # 归一化处理
        scaler = MinMaxScaler()
        self.W = scaler.fit_transform(self.W)

    def transform(self, X):
        # 投影到特征空间
        X_new = np.dot(X, self.W)
        # 归一化处理
        scaler = MinMaxScaler()
        X_new = scaler.fit_transform(X_new)
        return X_new


if __name__ == '__main__':
    # 加载数据集
    iris = load_iris()
    X = iris.data
    y = iris.target

    # 模型训练
    lda = LDA(n_components=2, kernel='rbf')
    lda.fit(X, y)

    # 数据转换
    X_new = lda.transform(X)

    # 可视化降维前的数据分布
    plt.scatter(X[:, 0], X[:, 1], c=y)
    plt.show()

    # 可视化降维后的数据分布
    plt2.scatter(X_new[:, 0], X_new[:, 1], c=y)
    plt2.show()

LDA降维前数据分布图:

 LDA降维后数据分布图:

4.3 基于sklearn代码实现

# 基于线性LDA算法对鸢尾花数据集进行分类
import numpy as np
import matplotlib.pyplot as plt
from sklearn import preprocessing
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import confusion_matrix
from matplotlib.colors import ListedColormap

# 加载数据集
iris = load_iris()
X = iris.data
y = iris.target

le = preprocessing.LabelEncoder()
le.fit(['Iris-setosa', 'Iris-versicolor', 'Iris-virginica'])
X = X[:, :2]

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)

if __name__ == '__main__':

    sc = StandardScaler()
    X_train = sc.fit_transform(X_train)
    X_test = sc.transform(X_test)

    lda = LDA(n_components=2)
    X_train = lda.fit_transform(X_train, y_train)
    X_test = lda.transform(X_test)

    classifier = LogisticRegression(random_state=0)
    classifier.fit(X_train, y_train)

    y_pred = classifier.predict(X_test)
    cm = confusion_matrix(y_test, y_pred)

    X_set, y_set = X_train, y_train
    X1, X2 = np.meshgrid(np.arange(start=X_set[:, 0].min() - 1, stop=X_set[:, 0].max() + 1, step=0.01),
                         np.arange(start=X_set[:, 1].min() - 1, stop=X_set[:, 1].max() + 1, step=0.01))
    plt.contourf(X1, X2, classifier.predict(np.array([X1.ravel(), X2.ravel()]).T).reshape(X1.shape),
                 alpha=0.75, cmap=ListedColormap(('red', 'green', 'blue')))
    plt.xlim(X1.min(), X1.max())
    plt.ylim(X2.min(), X2.max())
    for i, j in enumerate(np.unique(y_set)):
        plt.scatter(X_set[y_set == j, 0], X_set[y_set == j, 1],
                    c=ListedColormap(('yellow', 'green', 'blue'))(i), label=j)
    plt.title('Logistic Regression (Training set)')
    plt.xlabel('LD1')
    plt.ylabel('LD2')
    plt.legend()
    plt.show()

结果展示:

5 LDA总结

LDA是一种简单而有效的分类器和降维方法,特别适用于特征维度较低、数据符合高斯分布的问题。但在应用之前,需要仔细考虑数据是否符合LDA的假设,以及问题的特点是否适合使用LDA。

猜你喜欢

转载自blog.csdn.net/lsb2002/article/details/131843006