特征提取(機器學習數據預處理)


特征提取(機器學習數據預處理)

 

特征提取與特征選擇都是數據降維的技術,不過二者有着本質上的區別;特征選擇能夠保持數據的原始特征,最終得到的降維數據其實是原數據集的一個子集;而特征提取會通過數據轉換或數據映射得到一個新的特征空間,盡管新的特征空間是在原特征基礎上得來的,但是憑借人眼觀察可能看不出新數據集與原始數據集之間的關聯。

這里介紹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)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM