LDA(Linear Discriminant Analysis)是一种经典的线性判别方法,又称Fisher判别分析。该方法思想比较简单:给定训练集样例,设法将样例投影到一维的直线上,使得同类样例的投影点尽可能接近和密集(即希望类内离散度越小越好),异类投影点尽可能远离(即希望两类的均值点之差越小越好)

两类数据点的类心分别是μ1=∣C1∣1x∈C1∑x和μ2=∣C2∣1x∈C2∑x。
样本点x投影到w方向上后,在一维直线上得到的点为:y=wTx。
投影后的类心为:mk=∣Ck∣1x∈Ck∑wTx=wT∣Ck∣1x∈Ck∑x=wTμk
类心间距为:(m1−m2)2=(m1−m2)(m1−m2)T=wT(μ1−μ2)(μ1−μ2)Tw=wTSbw
其中Sb称为类间散度矩阵:Sb=(μ1−μ2)(μ1−μ2)T
类内距离用类内样本的方差来衡量,对于第k个类别,方差为Sk=x∈Ck∑(y−mk)2=x∈Ck∑(wT(x−μk))2=x∈Ck∑(wT(x−μk))(wT(x−μk))T=x∈Ck∑(wT(x−μk)(x−μk)Tw)=wT[x∈Ck∑(x−μk)(x−μk)T]w
所有类别类内距离之和为:S12+S22=wT[x∈C1∑(x−μ1)(x−μ1)T+x∈C2∑(x−μ2)(x−μ2)T]w
所以类内散度矩阵为:Sw=x∈C1∑(x−μ1)(x−μ1)T+x∈C2∑(x−μ2)(x−μ2)T
我们的优化目标是提升类间距离,减小类内距离,所以可最大化函数:J(w)=S12+S22(m1−m2)2=wTSwwwTSbw
从上式可以看出,J与w的方向有关,确定方向后,与w的长度无关。求解过程中,分子分母会同时变化,所以首先固定分母为某一个非0常数,即:wTSww=c,c̸=0,此时求解J(w)等价于:wmaxwTSbws.t. wTSww=c,c̸=0
此时可应用拉格朗日(Lagrange)乘数法:L(w,λ)=wTSbw−λ(wTSww−c)
∂w∂L(w,λ)=(Sb+SbT)w−λ(Sw+SwT)w=2Sbw−2λSww=0
化简可得:
Sw−1Sbw=λw
Sbw=(μ1−μ2)(μ1−μ2)Tw=β(μ1−μ2)表明Sbw的方向恒为μ1−μ2,带入上式可得:
w=λβSw−1(μ1−μ2)
又因为w只与方向有关,与长度无关,所以上式可以写为:
w=Sw−1(μ1−μ2)
考虑到数值解的稳定性,在实践中通常对Sw进行奇异值分解,即Sw=UΣVT,然后再由Sw−1=VΣ−1UT。矩阵的奇异值分解可以参考:https://blog.csdn.net/winycg/article/details/83005881
sklearn实现LDA线性判别:
import numpy as np
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
X = np.array([[-1, -1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]])
y = np.array([1, 1, 1, 2, 2, 2])
clf = LinearDiscriminantAnalysis(solver='svd')
clf.fit(X, y)
print(clf.predict([[-0.8, -1]]))