天天看點

線性判别結合源碼分析LDA原理

1. LDA的思想

LDA線性判别分析也是一種經典的降維方法,LDA是一種監督學習的降維技術,也就是說它的資料集的每個樣本是有類别輸出的。這點和PCA不同。PCA是不考慮樣本類别輸出的無監督降維技術。LDA的思想可以用一句話概括,就是“投影後類内方差最小,類間方差最大”。什麼意思呢? 我們要将資料在低次元上進行投影,投影後希望每一種類别資料的投影點盡可能的接近,而不同類别的資料的類别中心之間的距離盡可能的大。

可能還是有點抽象,我們先看看最簡單的情況。假設我們有兩類資料分别為紅色和藍色,如下圖所示,這些資料特征是二維的,我們希望将這些資料投影到一維的一條直線,讓每一種類别資料的投影點盡可能的接近,而紅色和藍色資料中心之間的距離盡可能的大。

線性判别結合源碼分析LDA原理

上圖中提供了兩種投影方式,哪一種能更好的滿足我們的标準呢?從直覺上可以看出,右圖要比左圖的投影效果好,因為右圖的黑色資料和藍色資料各個較為集中,且類别之間的距離明顯。左圖則在邊界處資料混雜。以上就是LDA的主要思想了,當然在實際應用中,我們的資料是多個類别的,我們的原始資料一般也是超過二維的,投影後的也一般不是直線,而是一個低維的超平面。

線性判别結合源碼分析LDA原理
線性判别結合源碼分析LDA原理

2.執行個體結合源碼

導包

import numpy as np
from sklearn import datasets
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
import warnings 

warnings.filterwarnings("ignore") 
X,y = datasets.load_iris(True)
X[:5]      

array([[5.1, 3.5, 1.4, 0.2],

[4.9, 3. , 1.4, 0.2],

[4.7, 3.2, 1.3, 0.2],

[4.6, 3.1, 1.5, 0.2],

[5. , 3.6, 1.4, 0.2]])

#特征值和特征向量 solver='eigen'/svd
lda = LinearDiscriminantAnalysis(solver='eigen',n_components=2)
X_lda = lda.fit_transform(X,y)
X_lda[:5]      

array([[6.01716893, 7.03257409],

[5.0745834 , 5.9344564 ],

[5.43939015, 6.46102462],

[4.75589325, 6.05166375],

[6.08839432, 7.24878907]])

源碼截圖

def _solve_eigen(self, X, y, shrinkage):

線性判别結合源碼分析LDA原理

共分為五步

#1、總的散度矩陣
#協方差X.T 等同rowvar=False,源碼中有偏內插補點bias=1
St = np.cov(X,rowvar=False,bias=1)
St      

array([[ 0.68112222, -0.04215111, 1.26582 , 0.51282889],

[-0.04215111, 0.18871289, -0.32745867, -0.12082844],

[ 1.26582 , -0.32745867, 3.09550267, 1.286972 ],

[ 0.51282889, -0.12082844, 1.286972 , 0.57713289]])

#2、類内的散度矩陣
# Scatter 散點圖,within(内)
Sw = np.full(shape = (4,4),fill_value=0,dtype = np.float64)
for i in range(3):
    Sw += np.cov(X[y == i],rowvar=False,bias=1)
Sw/=3
Sw      

array([[0.259708 , 0.09086667, 0.164164 , 0.03763333],

[0.09086667, 0.11308 , 0.05413867, 0.032056 ],

[0.164164 , 0.05413867, 0.181484 , 0.041812 ],

[0.03763333, 0.032056 , 0.041812 , 0.041044 ]])

# 3、計算類間的散度矩陣
#Scatter between
Sb = St -Sw
Sb      

array([[ 0.42141422, -0.13301778, 1.101656 , 0.47519556],

[-0.13301778, 0.07563289, -0.38159733, -0.15288444],

[ 1.101656 , -0.38159733, 2.91401867, 1.24516 ],

[ 0.47519556, -0.15288444, 1.24516 , 0.53608889]])

# scipy 這個子產品下的線性代數子子產品
from scipy import linalg
# 4、特征值 和 特征向量
eigen,ev = linalg.eigh(Sb,Sw)

print(eigen )
print( ev)      

[-1.84103303e-14 1.18322589e-14 2.85391043e-01 3.21919292e+01]

[[ 1.54162331 -2.82590065 0.02434685 0.83779794]

[-2.49358543 1.05970269 2.18649663 1.55005187]

[-2.86907801 1.01439507 -0.94138258 -2.22355955]

[ 4.58628831 0.45101349 2.86801283 -2.83899363]]

ev= ev[:,np.argsort(eigen)[::-1]]
ev      

array([[ 0.83779794, 0.02434685, -2.82590065, 1.54162331],

[ 1.55005187, 2.18649663, 1.05970269, -2.49358543],

[-2.22355955, -0.94138258, 1.01439507, -2.86907801],

[-2.83899363, 2.86801283, 0.45101349, 4.58628831]])

# 5、篩選特征向量 ,進行矩陣運算
X.dot(ev[:,:])[:5]      

array([[ 6.01716893, 7.03257409, -9.19277808, -3.96472168],

[ 5.0745834 , 5.9344564 , -9.1574493 , -3.02625362],

[ 5.43939015, 6.46102462, -8.48176814, -3.54638757],

[ 4.75589325, 6.05166375, -8.10226933, -4.02500696],

[ 6.08839432, 7.24878907, -8.80421775, -4.36824255]])

3.LDA與PCA比較

相同點

1)兩者均可以對資料進行降維。

2)兩者在降維時均使用了矩陣特征分解的思想。

3)兩者都假設資料符合高斯分布【正态分布】。

不同點

1)LDA是有監督的降維方法,而PCA是無監督的降維方法

2)LDA降維最多降到類别數k-1的維數,而PCA沒有這個限制。