[Scikit-learn] 1.2 Dimensionality reduction - Linear and Quadratic Discriminant Analysis

Ref: http://scikit-learn.org/stable/modules/lda_qda.htmlhtml

Ref: http://bluewhale.cc/2016-04-10/linear-discriminant-analysis.html算法

Ref: http://blog.csdn.net/lizhe_dashuju/article/details/50329663 【該系列,做者很用心,講得很通透】dom

 

線性判別分析(Linear Discriminant Analysis)簡稱LDA,是分類算法中的一種。機器學習

LDA經過對歷史數據進行投影,以保證投影后同一類別的數據儘可能靠近,不一樣類別的數據儘可能分開。並生成線性判別模型對新生成的數據進行分離和預測。函數

 

1、與PCA的幾點不一樣

  1. 出發思想不一樣。PCA主要是從特徵的協方差角度,去找到比較好的投影方式,即選擇樣本點投影具備最大方差的方向;而LDA則更多的是考慮了分類標籤信息,尋求投影后不一樣類別之間數據點距離更大化以及同一類別數據點距離最小化,即選擇分類性能最好的方向。
  2. 學習模式不一樣。PCA屬於無監督式學習,所以大多場景下只做爲數據處理過程的一部分,須要與其餘算法結合使用,例如將PCA與聚類、判別分析、迴歸分析等組合使用;LDA是一種監督式學習方法,自己除了能夠降維外,還能夠進行預測應用,所以既能夠組合其餘模型一塊兒使用,也能夠獨立使用。
  3. 降維後可用維度數量不一樣。LDA降維後最多可生成C-1維子空間(分類標籤數-1),所以LDA與原始維度數量無關,只有數據標籤分類數量有關;而PCA最多有n維度可用,即最大能夠選擇所有可用維度。

 

從直接可視化的角度,以二維數據降維爲例,PCA和LDA的區別以下圖:性能

綠線:LDA,考慮了類內散度。學習

藍線:PCA,不考慮類別,只關心降維後的總體方差最大。spa

 

上圖左側是PCA的降維思想,它所做的只是將整組數據總體映射到最方便表示這組數據的座標軸上,映射時沒有利用任何數據內部的分類信息。所以,雖然PCA後的數據在表示上更加方便(下降了維數並能最大限度的保持原有信息),但在分類上也許會變得更加困難;上圖右側是LDA的降維思想,能夠看到LDA充分利用了數據的分類信息,將兩組數據映射到了另一個座標軸上,使得數據更易區分了(在低維上就能夠區分,減小了運算量)。.net

線性判別分析LDA算法因爲其簡單有效性在多個領域都獲得了普遍地應用,是目前機器學習、數據挖掘領域經典且熱門的一個算法;可是算法自己仍然存在一些侷限性:3d

    • 當樣本數量遠小於樣本的特徵維數,樣本與樣本之間的距離變大使得距離度量失效,使LDA算法中的類內、類間離散度矩陣奇異,不能獲得最優的投影方向,在人臉識別領域中表現得尤其突出
    • LDA不適合對非高斯分佈的樣本進行降維
    • LDA在樣本分類信息依賴方差而不是均值時,效果很差
    • LDA可能過分擬合數據

 

 

2、使用方法 

爲什麼降維

當特徵選擇完成後,能夠直接訓練模型了,可是可能因爲特徵矩陣過大,致使計算量大,訓練時間長的問題,所以下降特徵矩陣維度也是必不可少的。

 

常見的降維方法除了基於L1懲罰項的模型之外,另外還有主成分分析法(PCA)和線性判別分析(LDA),線性判別分析自己也是一個分類模型。

PCA和LDA有不少的類似點,其本質是要將原始的樣本映射到維度更低的樣本空間中,可是PCA和LDA的映射目標不同:PCA是爲了讓映射後的樣本具備最大的發散性;而LDA是爲了讓映射後的樣本有最好的分類性能

因此說PCA是一種無監督的降維方法,而LDA是一種有監督的降維方法。

 

4.1 主成分分析法(PCA) 

使用decomposition庫的PCA類選擇特徵的代碼以下:

from sklearn.decomposition import PCA #主成分分析法,返回降維後的數據
#參數n_components爲主成分數目
PCA(n_components=2).fit_transform(iris.data)

 

4.2 線性判別分析法(LDA)

使用lda庫的LDA類選擇特徵的代碼以下:

from sklearn.lda import LDA #線性判別分析法,返回降維後的數據
#參數n_components爲降維後的維數
LDA(n_components=2).fit_transform(iris.data, iris.target)

 

  

3、引入了以下概念

類間散度, 

類內散度,

判別函數,

 

 
 

4、線性判別 和 二次判別

Ref: Quadratic Discriminant Analysis(QDA)

與線性判別分析相似,二次判別分析是另一種線性判別分析算法,兩者擁有相似的算法特徵,區別僅在於:

    • 當不一樣分類樣本的協方差矩陣相同時,使用線性判別分析
    • 當不一樣分類樣本的協方差矩陣不一樣時,則應該使用二次判別

 

下圖顯示了在固定協方差矩陣以及不一樣協方差矩陣下LDA和QDA的表現差別:

  • 由圖中能夠看出,在固定協方差矩陣下,LDA和QDA是沒有分類結果差別的(上面兩張圖);
  • 在不一樣的協方差矩陣下,LDA和QDA的分類邊界明顯存在差別,並且LDA已經不能準確的劃分數據(下面兩張圖)。

【怎麼可能樣本都是一樣的協方差,感受LDA沒啥用處?】

 

print(__doc__) from scipy import linalg import numpy as np import matplotlib.pyplot as plt import matplotlib as mpl from matplotlib import colors from sklearn.discriminant_analysis import LinearDiscriminantAnalysis from sklearn.discriminant_analysis import QuadraticDiscriminantAnalysis # ############################################################################# # Colormap
cmap = colors.LinearSegmentedColormap( 'red_blue_classes', {'red': [(0, 1, 1), (1, 0.7, 0.7)], 'green': [(0, 0.7, 0.7), (1, 0.7, 0.7)], 'blue': [(0, 0.7, 0.7), (1, 1, 1)]}) plt.cm.register_cmap(cmap=cmap) # ############################################################################# # Generate datasets
def dataset_fixed_cov(): '''Generate 2 Gaussians samples with the same covariance matrix''' n, dim = 300, 2 np.random.seed(0) C = np.array([[0., -0.23], [0.83, .23]]) X = np.r_[np.dot(np.random.randn(n, dim), C), np.dot(np.random.randn(n, dim), C) + np.array([1, 1])] y = np.hstack((np.zeros(n), np.ones(n))) return X, y def dataset_cov(): '''Generate 2 Gaussians samples with different covariance matrices''' n, dim = 300, 2 np.random.seed(0) C = np.array([[0., -1.], [2.5, .7]]) * 2. X = np.r_[np.dot(np.random.randn(n, dim), C), np.dot(np.random.randn(n, dim), C.T) + np.array([1, 4])] y = np.hstack((np.zeros(n), np.ones(n))) return X, y # ############################################################################# # Plot functions
def plot_data(lda, X, y, y_pred, fig_index): splot = plt.subplot(2, 2, fig_index) if fig_index == 1: plt.title('Linear Discriminant Analysis') plt.ylabel('Data with\n fixed covariance') elif fig_index == 2: plt.title('Quadratic Discriminant Analysis') elif fig_index == 3: plt.ylabel('Data with\n varying covariances') tp = (y == y_pred)  # True Positive
    tp0, tp1 = tp[y == 0], tp[y == 1] X0, X1 = X[y == 0], X[y == 1] X0_tp, X0_fp = X0[tp0], X0[~tp0] X1_tp, X1_fp = X1[tp1], X1[~tp1] alpha = 0.5

    # class 0: dots
    plt.plot(X0_tp[:, 0], X0_tp[:, 1], 'o', alpha=alpha, color='red', markeredgecolor='k') plt.plot(X0_fp[:, 0], X0_fp[:, 1], '*', alpha=alpha, color='#990000', markeredgecolor='k')  # dark red

    # class 1: dots
    plt.plot(X1_tp[:, 0], X1_tp[:, 1], 'o', alpha=alpha, color='blue', markeredgecolor='k') plt.plot(X1_fp[:, 0], X1_fp[:, 1], '*', alpha=alpha, color='#000099', markeredgecolor='k')  # dark blue

    # class 0 and 1 : areas
    nx, ny = 200, 100 x_min, x_max = plt.xlim() y_min, y_max = plt.ylim() xx, yy = np.meshgrid(np.linspace(x_min, x_max, nx), np.linspace(y_min, y_max, ny)) Z = lda.predict_proba(np.c_[xx.ravel(), yy.ravel()]) Z = Z[:, 1].reshape(xx.shape) plt.pcolormesh(xx, yy, Z, cmap='red_blue_classes', norm=colors.Normalize(0., 1.)) plt.contour(xx, yy, Z, [0.5], linewidths=2., colors='k') # means
    plt.plot(lda.means_[0][0], lda.means_[0][1], 'o', color='black', markersize=10, markeredgecolor='k') plt.plot(lda.means_[1][0], lda.means_[1][1], 'o', color='black', markersize=10, markeredgecolor='k') return splot def plot_ellipse(splot, mean, cov, color): v, w = linalg.eigh(cov) u = w[0] / linalg.norm(w[0]) angle = np.arctan(u[1] / u[0]) angle = 180 * angle / np.pi  # convert to degrees
    # filled Gaussian at 2 standard deviation
    ell = mpl.patches.Ellipse(mean, 2 * v[0] ** 0.5, 2 * v[1] ** 0.5, 180 + angle, facecolor=color, edgecolor='yellow', linewidth=2, zorder=2) ell.set_clip_box(splot.bbox) ell.set_alpha(0.5) splot.add_artist(ell) splot.set_xticks(()) splot.set_yticks(()) def plot_lda_cov(lda, splot): plot_ellipse(splot, lda.means_[0], lda.covariance_, 'red') plot_ellipse(splot, lda.means_[1], lda.covariance_, 'blue') def plot_qda_cov(qda, splot): plot_ellipse(splot, qda.means_[0], qda.covariances_[0], 'red') plot_ellipse(splot, qda.means_[1], qda.covariances_[1], 'blue') for i, (X, y) in enumerate([dataset_fixed_cov(), dataset_cov()]): # Linear Discriminant Analysis
    lda = LinearDiscriminantAnalysis(solver="svd", store_covariance=True) y_pred = lda.fit(X, y).predict(X) splot = plot_data(lda, X, y, y_pred, fig_index=2 * i + 1) plot_lda_cov(lda, splot) plt.axis('tight') # Quadratic Discriminant Analysis
    qda = QuadraticDiscriminantAnalysis(store_covariances=True) y_pred = qda.fit(X, y).predict(X) splot = plot_data(qda, X, y, y_pred, fig_index=2 * i + 2) plot_qda_cov(qda, splot) plt.axis('tight') plt.suptitle('Linear Discriminant Analysis vs Quadratic Discriminant'
             'Analysis') plt.show()

 

End. 

相關文章
相關標籤/搜索