特征提取(機器學習數據預處理)
特征提取與特征選擇都是數據降維的技術,不過二者有着本質上的區別;特征選擇能夠保持數據的原始特征,最終得到的降維數據其實是原數據集的一個子集;而特征提取會通過數據轉換或數據映射得到一個新的特征空間,盡管新的特征空間是在原特征基礎上得來的,但是憑借人眼觀察可能看不出新數據集與原始數據集之間的關聯。
這里介紹2種常見的特征提取技術:
1)主成分分析(PCA)
2)線性判別分析(LDA)
1.主成分分析(PCA)
一種無監督的數據壓縮,數據提取技術,通常用於提高計算效率,幫助降低”維度災難“,尤其是當模型不適於正則化時。
PCA是一種線性轉換技術,其目標是在高緯度數據中找到最大方差的方向,並將數據映射到不大於原始數據的新的子空間上。(所謂數據方差最大的方向即數據沿着該方向的分布最分散)
PCA算法的流程:
1)對原始d維數據集做標准化處理;
2)構造樣本的協方差矩陣;
3)計算協方差矩陣的特征值和相應的特征向量;
4)選擇前k個最大特征值對應的特征向量,其中$k\leq d$;
5)通過前k個特征向量構建映射矩陣W;
6)通過映射矩陣W將d維的原始數據轉換為k維的特征子空間。
標准化處理之前的內容有,這里不再贅述;
1.1構造協方差矩陣
公式:
$\sigma_{jk}=\frac{1}{n}\sum_{i=1}^{n}(x_{j}^{(i)}-u_{j})(x_{k}^{(i)}-u_{k})$
n代表數據的總個數,$u_{j}$和$u_{k}$分別代表特征j和k的均值;在標准化后的數據中,樣本的均值為0,所以在標准化處理后的數據的協方差又可以表示為:
$\sigma_{jk}=\frac{1}{n}\sum_{i=1}^{n}x_{j}^{(i)}x_{k}^{(i)}$
1.2 協方差特征值與特征向量計算
數學原理不在這里細說,代碼實現見下面的小節。
1.3 特征值與特征向量的選取
選取那些包含信息最多的的特征向量組成子集,特征值的大小決定了特征向量的重要性,所以選擇特征值大小靠前的k個特征值作為選中的特征值,其對應的特征變量作為構建映射矩陣的特征向量。
我們還可以繪制特征值的貢獻率:
$\frac{\lambda_{j}}{\sum_{j=1}^{d}\lambda_{j}}$,$\lambda_{j}$表示第j個特征值。
1.4 構建映射矩陣W
將選中的k個特征向量構成一個(d,k)維的矩陣W。
1.5程序實現
import pandas as pd import numpy as np from sklearn.preprocessing import StandardScaler df = pd.DataFrame([\ [1,2,3,4,5,6],\ [2,4,6,3,3,4],\ [3,6,10,4,7,7],\ [2,4,7,6,5,4],\ [4,7,13,7,3,2],\ [1,2,3,3,6,4]\ ],columns=["A","B","C","D","E","F"]) #1.標准化 sc = StandardScaler() sc.fit(df.values) X_std = sc.transform(df.values) #2.生成協方差矩陣 cov_mat = np.cov(X_std) #3.協方差矩陣的特征值與特征向量 eigen_vals,eigen_vecs = np.linalg.eig(cov_mat) #4.按照重要程度由高往低將特征變量排序 sort_list = np.argsort(eigen_vals)
#取前兩個向量組成轉換矩陣 w = np.column_stack((eigen_vecs[:,sort_list[0]],eigen_vecs[:,sort_list[1]])) #5.取第一個數據進行轉換 x_1= X_std[0].dot(w) print(x_1)
結果如下:

scikit_learn.decomposition模塊中的PCA類也可實現此功能,使用方式如下:
from sklearn.decomposition import PCA pca = PCA(n_component=2) X_train_pca = pca(X_train_std)
PCA類中的n_component用於指定需要降到的維數。
2.線性判別分析(LDA)
LDA的目標是發現可以最優化分類的特征子空間,是一種監督算法。
LDA的執行步驟是:
1)對d維的原數據集進行標准化處理;
2)對於每一類別,計算d維的均值向量;
3)構造類間的散布矩陣$S_{B}$以及類內的散布矩陣$S_{W}$;
4)計算$S_{W}^{-1}S_{B}$的特征值及對應的特征向量;
5)選取前k個特征值所對應的特征向量,構造一個$d\timesk$維的轉換矩陣W,其中特征向量以列的形式排列;
6)使用轉換矩陣W將樣本映射到新的特征子空間上。
大致上與PCA很相似,這里只介紹與PCA中不同的部分。
2.1計算類內散布矩陣$S_{W}$
首先計算均值向量$m_{i}$,$m_{i}$儲存了類別i中樣本的特征均值$u_{m}$,$m_{i}$不是一個值,而是一個向量,包含了每一個特征的均值。
$m_{i}=\frac{1}{n_{i}}\sum_{x\in D_{i}}^{c}x_{m}$;
import pandas as pd import numpy as np df = pd.DataFrame([\ [1,2,3,4,5,"ONE"],\ [2,4,6,3,3,"TWO"],\ [2,4,7,6,5,"ONE"],\ [4,7,13,7,3,"TWO"],\ ],columns=["A","B","C","D","E","class_label"]) #類別列表 label_list = np.unique(df["class_label"].values) mean_by_label = {} #通過類別的數值作為key保存該類別對應的數據的均值 for label in label_list: mean_by_label[label] = np.mean(df[df["class_label"]==label].values[:,:-1],axis=0) for key,value in mean_by_label.items(): print(key,value)
結果如下:

每個類別i的散布矩陣$S_{i}$的表達式,Ni表示類別i內的樣本數量,這個和協方差的表達式是相同的。
$S_{i}=\frac{1}{N_i}\sum_{x\in D_{i}}^{c}(x-m_{i})(x-m_{i})^{T}N_i$
最終的類內散布矩陣$S_{W}$是由各個類別的散布矩陣累加得來的:
$S_{W}=\sum_{i=1}^{c}S_{i}$
2.2計算類間散布矩陣$S_{B}$
$S_{B}=\sum_{i=1}^{c}N_{i}(m_{i}-m)(m_{i}-m)^{T}$
其中c代表類別總數量,Ni表示類別i的樣本數量,mi是類別i的均值,m是所有數據的均值
2.3LDA轉換矩陣
PCA是對協方差舉證求特征值和特征向量,而LDA是對$S_{W}^{-1}S_{B}$矩陣求解廣義特征值和特征向量,剩下的與PCA相同。
同樣scikit-learn庫中也實現了LDA類
from sklearn.lda import LDA lda = LDA(n_componets=2)
