1. 程式人生 > >機器學習:線性判別式分析(LDA)

機器學習:線性判別式分析(LDA)

get generated 分類 learn 參數 關註 ble 直線 圖片

1.概述

線性判別式分析(Linear Discriminant Analysis),簡稱為LDA。也稱為Fisher線性判別(Fisher Linear Discriminant,FLD),是模式識別的經典算法,在1996年由Belhumeur引入模式識別和人工智能領域。

基本思想是將高維的模式樣本投影到最佳鑒別矢量空間,以達到抽取分類信息和壓縮特征空間維數的效果,投影後保證模式樣本在新的子空間有最大的類間距離和最小的類內距離,即模式在該空間中有最佳的可分離性。

LDA與PCA都是常用的降維技術。PCA主要是從特征的協方差角度,去找到比較好的投影方式。LDA更多的是考慮了標註,即希望投影後不同類別之間數據點的距離更大,同一類別的數據點更緊湊。

但是LDA有兩個假設:1.樣本數據服從正態分布,2.各類得協方差相等。雖然這些在實際中不一定滿足,但是LDA被證明是非常有效的降維方法,其線性模型對於噪音的魯棒性效果比較好,不容易過擬合。

2.圖解說明(圖片來自網絡)

技術分享

可以看到兩個類別,一個綠色類別,一個紅色類別。左圖是兩個類別的原始數據,現在要求將數據從二維降維到一維。直接投影到x1軸或者x2軸,不同類別之間會有重復,導致分類效果下降。右圖映射到的直線就是用LDA方法計算得到的,可以看到,紅色類別和綠色類別在映射之後之間的距離是最大的,而且每個類別內部點的離散程度是最小的(或者說聚集程度是最大的)。

3.圖解LAD與PCA的區別(圖片來自網絡)

技術分享

兩個類別,class1的點都是圓圈,class2的點都是十字。圖中有兩條直線,斜率在1左右的這條直線是PCA選擇的映射直線,斜率在 -1左右的這條直線是LDA選擇的映射直線。其余不在這兩條直線上的點是原始數據點。可以看到由於LDA考慮了“類別”這個信息(即標註),映射後,可以很好的將class1和class2的點區分開。

4.LAD與PCA的對比

(1)PCA無需樣本標簽,屬於無監督學習降維;LDA需要樣本標簽,屬於有監督學習降維。二者均是尋找一定的特征向量w來降維的,其中LDA抓住樣本的判別特征,PCA則側重描敘特征。概括來說,PCA選擇樣本點投影具有最大方差的方向,LDA選擇分類性能最好的方向。

(2)PCA降維是直接和特征維度相關的,比如原始數據是d維的,那麽PCA後可以任意選取1維、2維,一直到d維都行。LDA降維是直接和類別的個數C相關的,與數據本身的維度沒關系,比如原始數據是d維的,一共有C個類別,那麽LDA降維之後,一般就是1維,2維到C-1維進行選擇。要求降維後特征向量維度大於C-1的,不能使用LDA。

(3)PCA投影的坐標系都是正交的,而LDA根據類別的標註關註分類能力,因此不保證投影到的坐標系是正交的(一般都不正交)

5.LAD的使用限制

(1)LDA至多可生成C-1維子空間
LDA降維後的維度區間在[1,C-1],與原始特征數n無關,對於二值分類,最多投影到1維。

(2)LDA不適合對非高斯分布樣本進行降維。如下圖所示的數據分布分類效果不好

技術分享

(3)LDA在樣本分類信息依賴方差而不是均值時,效果不好。

6.實驗及講解

1)生成實驗數據,如下圖:

技術分享

尋找一條直線,使按照橢圓圈出的分類進行投影,使得投影後模式樣本在新的子空間有最大的類間距離和最小的類內距離。

2)核心函數

a)sklearn.discriminant_analysis.LinearDiscriminantAnalysis

b)主要參數(詳細參數)

n_components :減少到多少維空間

c)主要屬性

coef_ :權重。如果是投影到一維空間,則兩個值對應的是直線的斜率和截距。

classes_ :分類

3)詳細代碼

技術分享
from sklearn.datasets.samples_generator import make_blobs
import numpy as np
import matplotlib.pyplot as plt
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from itertools import cycle

##產生隨機數據的中心
centers = [[2.5, 2],[1.8, 3] ]
##產生的數據個數
n_samples=100
##生產數據
X, labels = make_blobs(n_samples=n_samples, centers= centers, cluster_std=0.3, 
                  random_state =0)


clf = LinearDiscriminantAnalysis()
clf.fit(X,labels)

##直線的斜率和截距
#print(clf.coef_) #-7.16451571  10.65392594]

##選取兩個數進行預測
#print(clf.predict([[1.8, 3.2]]))  #1
#print(clf.predict([[2.7, 1.7]]))#0

##讀取直線的斜率和截距
k1 = clf.coef_[0,0]
b1 = clf.coef_[0,1]

##繪圖
plt.figure(1)
plt.clf()

‘‘‘
    說明:
     1)為了方便計算及說明,函數式1、2都采用了近似值
        y的斜率為-7.165,所以y1的斜率為0.14
     2)由於近似值或者繪圖精度的問題,當y1斜率為0.14時與y不垂直,
        效果圖中的綠色直線是下面函數繪制的:y1=0.37*x+1.7,即斜率為0.37
‘‘‘
#畫LDA直線
x=np.linspace(0,4,50) ##在0-15直接畫100個連續點
#y=k1*x+b1
y=-7.165*x+10.7 ##函數式1
plt.plot(x,y,color="red",linewidth=2)
#畫與LDA直線垂直的直線
y1=0.14*x+2.2 ##函數式2
#y1=0.37*x+1.7  ##這個函數僅僅是為了繪制效果圖用
plt.plot(x,y1,color="g",linewidth=2)


colors = cycle(mykbgrcmykbgrcmykbgrcmyk)
for k, col in zip(range(len(clf.classes_)), colors):
    ##根據lables中的值是否等於k,重新組成一個True、False的數組
    my_members = labels == k
    ##X[my_members, 0] 取出my_members對應位置為True的值的橫坐標
    plt.plot(X[my_members, 0], X[my_members, 1],o,c = col ,markersize=4)
    
plt.axis([0, 4, 0, 5])
plt.show()
View Code

4)結果圖

技術分享

在上圖中,紅線是LDA之後求出來的,綠線是通過數學的兩直線相交的關系求出來的。在代碼中,選取了兩個點:[1.8, 3.2],[2.7, 1.7],如果直接用訓練出的模型進行預測,點[1.8, 3.2] 屬於類型1,點[2.7, 1.7]屬於類型0.如果通過線與點的關系,使用綠線進行判斷,0.14×1.8+2.2=2.45 <3.2,所以點[1.8, 3.2]在綠線上面,因此屬於分類1。0.14×2.7+2.2=2.578>1.7,所以點[2.7, 1.7]在綠線下面,因此屬於分類0.

對應投影是一維的情況,個人感覺如果能求出綠線的方程,無論是從預測計算還是理解,都比較方便。但是由於樣本點分布的不確定性,綠線的斜率好求,但是截距難找,所以LDA算法並沒有給出相關的屬性內容。

機器學習:線性判別式分析(LDA)