为什么Python的scikit-learn LDA无法正常工作,它如何通过SVD计算LDA?


26

我使用来自scikit-learn机器学习库(Python)的线性判别分析(LDA)进行降维,并对结果有些好奇。我现在想知道LDA scikit-learn正在做什么,以便使结果看起来不同于例如手动方法或R中完成的LDA。如果有人可以在这里给我一些见解,那将是非常不错的。

基本上最令人担忧的是,该图scikit-plot显示了两个变量之间的相关性,其中应该有一个相关性0。

为了进行测试,我使用了虹膜数据集,前两个线性判别式如下所示:

IMG-1。通过scikit-learn进行LDA

在此处输入图片说明

这基本上与我在scikit-learn 文档中找到的结果一致

现在,我逐步进行了LDA,并得到了不同的预测。我尝试了不同的方法,以了解发生了什么事情:

IMG-2。基于原始数据的LDA(无中心,无标准化)

在此处输入图片说明

如果我先对数据进行标准化(z分数归一化;单位方差),这将是分步方法。我只用均值中心进行了相同的操作,这应该导致相同的相对投影图像(并且确实如此)。

IMG-3。均值居中或标准化后的逐步LDA

在此处输入图片说明

IMG-4。R中的LDA(默认设置)

我将数据居中的IMG-3中的LDA(这将是首选方法)看起来也与我在R中执行LDA的人帖子中找到的LDA完全相同 在此处输入图片说明


参考代码

我不想将所有代码粘贴到这里,但是我将其作为IPython笔记本上传到这里,该笔记本分为我用于LDA投影的几个步骤(请参见下文)。

  1. 步骤1:计算d维平均向量
    mi=1nixDinxk
  2. 步骤2:计算散点矩阵

    2.1类内散布矩阵由以下等式计算:SW

    SW=i=1cSi=i=1cxDin(xmi)(xmi)T

    2.2类间散布矩阵由以下公式计算: 其中是整体平均值。SB

    SB=i=1cni(mim)(mim)T
    m
  3. 步骤3.求解矩阵的广义特征值问题SW1SB

    3.1。通过减少特征值对特征向量进行排序

    3.2。选择具有最大特征值的k个特征向量。结合两个特征值最高的特征向量来构建维特征向量矩阵d×kW

  4. 步骤5:将样本转换到新的子空间

    y=WT×x.

我没有仔细研究差异,但是您可以从源代码中确切地看到scikit-learn在做什么。
Dougal

看起来它们也在标准化(居中,然后通过除以标准偏差进行缩放)。这是我希望得到的结果与我的第3个图(和R)图中的结果相似... hmm

奇怪:您使用scikit获得的绘图(及其在文档中显示的绘图)没有任何意义。LDA总是产生相关系数为零的投影,但是很明显,scikit在判别轴1和2上的投影之间存在非常强的相关性。这显然是错误的。
变形虫说恢复莫妮卡2014年

@ameoba是的,我也是。还奇怪的是,我在示例文档中为scikit显示的图是相同的:scikit-learn.org/stable/auto_examples/decomposition / ...这让我认为我对scikit的用法是正确的,但是有些奇怪关于LDA功能的问题

@SebastianRaschka:是的,我注意到了。确实很奇怪。但是,请注意,您自己的第一个(非scikit)LDA图也显示了非零相关性,因此它也一定有问题。您是否将数据居中?在第二个轴上的投影似乎没有零均值。
变形虫说恢复莫妮卡

Answers:


20

更新:由于此讨论,scikit-learn已更新并可以正常工作。可在此处找到其LDA源代码。最初的问题是由于一个小错误(请参阅此github讨论),而我的答案实际上并未正确指向它(对造成的任何混乱表示歉意)。由于所有这些都不再重要了(错误已修复),我编辑了答案,重点关注如何通过SVD解决LDA,这是的默认算法scikit-learn


在定义了类内和类间散布矩阵和,您的问题中指出的标准LDA计算是采用特征向量作为判别轴(例如参见此处)。但是,可以利用白化矩阵以稍微不同的方式计算相同的轴:ΣWΣBΣW1ΣB

  1. 计算。对于合并的类内协方差而言,这是一次美白转换(有关详细信息,请参阅我的链接答案)。ΣW1/2

    请注意,如果您具有特征分解,则。还要注意,通过对合并的类内数据进行SVD​​可以计算出相同的值:。ΣW=USUΣW1/2=US1/2UXW=ULVΣW1/2=UL1U

  2. 找出特征向量,我们称它们为。ΣW1/2ΣBΣW1/2A

    同样,请注意,可以通过对类间数据进行SVD​​进行计算,并用,即,相对于类内数据将类间数据白化协方差。XBΣW1/2

  3. 判别轴将由,即由再次转换的变换数据的主轴给出。AΣW1/2A

    确实,如果是上述矩阵的特征向量,则然后从左边乘以并定义,我们立即获得:a

    ΣW1/2ΣBΣW1/2a=λa,
    ΣW1/2a=ΣW1/2a
    ΣW1ΣBa=λa.

总而言之,LDA等效于针​​对类内协方差对类均值矩阵进行白化,对类均值进行PCA,然后将生成的主轴反向转换为原始(未白化)空间。

例如,在《统计学习的要素》第4.3.3节中指出了这一点。在scikit-learn这是默认的方式来计算LDA因为数据矩阵的SVD在数值上更稳定比其协方差矩阵的特征值分解。

请注意,可以使用任何白化转换来代替并且所有操作仍将完全相同。在中使用(而不是),然后它工作得很好(与我的答案中最初写的相反)。ΣW1/2scikit-learn L1UUL1U


1
感谢您的答复。感谢您花时间将其很好地编写出来。也许您可以在GitHub的讨论中提到它;我确信这对修复下一版sci-kit中的LDA会有所帮助

@SebastianRaschka:我在GitHub上没有帐户。但是,如果您愿意,可以在该链接处提供此线程的链接。
变形虫说恢复莫妮卡

@amoeba:教科书通常像您描述LDA一样-的特征值分解。奇怪的是,我知道许多LDA实现都采用不同的方法。它们的轴是使用转换的类均值的向量。您的LDA解决方案是这些向量的正交基础。Scikit-learn的LDA与这些实现提供的结果相同,因此我认为实际上没有错误。ΣW1ΣBΣW1
kazemakase


2
@kazemakase:嗯,当然,如果只有两个班,然后有1级,一切都简化了不少,作为唯一的特征向量的由下式给出,其中是类均值。我想那是你以前的意思?例如,Bishop的ML教科书第4.1.4节对此进行了很好的介绍。但是,要推广到更多类,则需要特征分析(同上,4.1.6)。另外,scikit的代码(我们在这里讨论!)确实使用了svd,实际上是两次。ΣBΣW1ΣBΣW1(μ1μ2)μi
变形虫说恢复莫妮卡2014年

3

为了解决这个问题,在scikit-learn 0.15.2中修复了与LDA讨论的问题。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.