特征抽取是數(shù)據(jù)挖掘任務(wù)最為重要的一個(gè)環(huán)節(jié),一般而言,它對(duì)最終結(jié)果的影響要高過數(shù)據(jù)挖掘算法本身。
不幸的是,關(guān)于怎樣選取好的特征,還沒有嚴(yán)格、快捷的規(guī)則可循,其實(shí)這也是數(shù)據(jù)挖掘科學(xué)更像是一門藝術(shù)的所在。
創(chuàng)建好的規(guī)則離不開直覺,還需要專業(yè)領(lǐng)域知識(shí)和數(shù)據(jù)挖 掘經(jīng)驗(yàn),光有這些還不夠,還得不停地嘗試、摸索,在試錯(cuò)中前進(jìn),有時(shí)多少還要靠點(diǎn)運(yùn)氣。
通常特征數(shù)量很多,但我們只想選用其中一小部分。有如下幾個(gè)原因。
1、降低復(fù)雜度
隨著特征數(shù)量的增加,很多數(shù)據(jù)挖掘算法需要更多的時(shí)間和資源。減少特征數(shù)量,是提高算法運(yùn)行速度,減少資源使用的好方法。
2、降低噪音
增加額外特征并不總會(huì)提升算法的表現(xiàn)。額外特征可能擾亂算法的正常工作,這些額外特征間的相關(guān)性和模式?jīng)]有實(shí)際應(yīng)用價(jià)值(這種情況在小數(shù)據(jù)集上很常見)。只選擇合適的特征有助于減少出現(xiàn)沒有實(shí)際意義的相關(guān)性的幾率。
3、增加模型可讀性
根據(jù)成千上萬(wàn)個(gè)特征創(chuàng)建的模型來解答一個(gè)問題,對(duì)計(jì)算機(jī)來說很容易,但模型對(duì)我們自己來說就晦澀無比。因此,使用更少的特征,創(chuàng)建我們自己可以理解的模型,就很有必要。
有些分類算法確實(shí)很強(qiáng)壯,能夠處理噪音問題,特征再多也不在話下,但是選用干凈的數(shù)據(jù),選取更具描述性的特征,對(duì)算法效果提升很有幫助。
根據(jù)特征選擇的形式又可以將特征選擇方法分為三種
Filter:過濾法,按照發(fā)散性或者相關(guān)性對(duì)各個(gè)特征進(jìn)行評(píng)分,設(shè)定閾值或者待選擇閾值的個(gè)數(shù),選擇特征。
Wrapper:包裝法,根據(jù)目標(biāo)函數(shù)(通常是預(yù)測(cè)效果評(píng)分),每次選擇若干特征,或者排除若干特征。
Embedded:嵌入法,先使用某些機(jī)器學(xué)習(xí)的算法和模型進(jìn)行訓(xùn)練,得到各個(gè)特征的權(quán)值系數(shù),根據(jù)系數(shù)從大到小選擇特征。類似于Filter方法,但是是通過訓(xùn)練來確定特征的優(yōu)劣。
寫在前面為了幫助更好地理解特征選擇,這里使用我們常用的股市數(shù)據(jù)作為基礎(chǔ)數(shù)據(jù)。
由于文章較長(zhǎng),為方便閱讀,我將特征選擇與特征提取總結(jié)文章拆分為上下兩篇,上篇(本文)主要內(nèi)容包括如下圖所示,主要介紹過濾法中常用的幾種特征選擇方法。
導(dǎo)入相關(guān)模塊import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings(“ignore”)
import yfinance as yf
yf.pdr_override()
獲取數(shù)據(jù)仍然用騰訊股市數(shù)據(jù),輔助理解本文內(nèi)容。
symbol = ‘TCEHY’
start = ‘2016-01-01’
end = ‘2021-01-01’
df = yf.download(symbol, start, end)
# df = df.reset_index()# View columns
df.head()
特征構(gòu)造dataset = df.copy()
[‘Increase_Decrease’] = np.where(dataset[‘Volume’].shift(-1) 》 dataset[‘Volume’],1,0)
dataset[‘Buy_Sell_on_Open’] = np.where(dataset[‘Open’].shift(-1) 》 dataset[‘Open’],1,0)
dataset[‘Buy_Sell’] = np.where(dataset[‘Adj Close’].shift(-1) 》 dataset[‘Adj Close’],1,0)
dataset[‘Returns’] = dataset[‘Adj Close’].pct_change()
dataset = dataset.dropna()
dataset.head()
數(shù)據(jù)準(zhǔn)備設(shè)定目標(biāo)標(biāo)簽為收盤價(jià),研究哪些變量對(duì)收盤價(jià)影響加大。通過一定對(duì)方法剔除幾乎沒有影響的特征,選出影響較多對(duì)特征。特征選擇在維度較大時(shí)尤為重要。
features = dataset.drop([‘Adj Close’, ‘Close’, ‘Returns’], axis=1)
array = features.values
X = array.astype(int)
Y = dataset[‘Adj Close’].values.astype(int)
過濾法過濾方法通常用作預(yù)處理步驟,特征選擇完全獨(dú)立于任何機(jī)器學(xué)習(xí)算法。它是根據(jù)各種統(tǒng)計(jì)檢驗(yàn)中的分?jǐn)?shù)以及相關(guān)性的各項(xiàng)指標(biāo)來選擇特征。
方差過濾這是通過特征本身的方差來篩選特征的類。比如一個(gè)特征本身的方差很小,就表示樣本在這個(gè)特征上基本沒有差異,可能特征中的大多數(shù)值都一樣,甚至整個(gè)特征的取值都相同,那這個(gè)特征對(duì)于樣本區(qū)分沒有什么作用。
scikit-learn中的VarianceThreshold轉(zhuǎn)換器可用來刪除特征值的方差達(dá)不到最低標(biāo)準(zhǔn)的特征。
from sklearn.feature_selection import VarianceThreshold
vt = VarianceThreshold()
vt.fit_transform(X)
var_thd = pd.DataFrame(vt.variances_, columns = [“Variance”], index=features.columns)
var_thd = var_thd.reset_index()
var_thd.sort_values(‘Variance’,ascending=0)
無論什么時(shí)候,拿到數(shù)據(jù)后,先做下類似簡(jiǎn)單、直接的分析,對(duì)數(shù)據(jù)集的特點(diǎn)做到心中有數(shù)。方差為0的特征不但對(duì)數(shù)據(jù)挖掘沒有絲毫用處,相反還會(huì)拖慢算法的運(yùn)行速度。
單變量選擇單變量的特征選擇是通過基于一些單變量的統(tǒng)計(jì)度量方法來選擇最好的特征。屬于過濾法的一種。
scikit-learn提供了幾個(gè)用于選擇單變量特征的轉(zhuǎn)換器,其中SelectKBest返回 個(gè)最佳特征,SelectPercentile返回表現(xiàn)最佳的前 個(gè)特征。這兩個(gè)轉(zhuǎn)換器都提供計(jì)算特征表現(xiàn)的一系列方法。都將得分函數(shù)作為輸入,返回單變量的得分和p值??勺鳛檩斎氲脑u(píng)分函數(shù)有:
對(duì)于回歸: f_regression , mutual_info_regression, 互信息
對(duì)于分類: chi2 , f_classif , mutual_info_classif, 皮爾森相關(guān)系數(shù)
SelectKBest 選擇出前k個(gè)與標(biāo)簽最相關(guān)的特征,主要有兩個(gè)參數(shù):
1、score_func : callable,函數(shù)取兩個(gè)數(shù)組X和y,返回一對(duì)數(shù)組(scores, pvalues)或一個(gè)分?jǐn)?shù)的數(shù)組。默認(rèn)函數(shù)為f_classif,默認(rèn)函數(shù)只適用于分類函數(shù)。
2、k:int or “all”, optional, default=10。所選擇的topK個(gè)特征?!癮ll”選項(xiàng)則繞過選擇,用于參數(shù)搜索。
卡方單個(gè)特征和某一類別之間相關(guān)性的計(jì)算方法有很多。最常用的有卡方檢驗(yàn)。經(jīng)典的卡方檢驗(yàn)是檢驗(yàn)定性自變量對(duì)定性因變量的相關(guān)性。
卡方過濾是專門針對(duì)離散型標(biāo)簽(即分類問題)的相關(guān)性過濾??ǚ綑z驗(yàn)類 feature_selection.chi2 計(jì)算每個(gè)非負(fù)特征和標(biāo)簽之間的卡方統(tǒng)計(jì)量,并依照卡方統(tǒng)計(jì)量由高到低為特征排名。
再結(jié)合 feature_selection.SelectKBest 這個(gè)可以輸入”評(píng)分標(biāo)準(zhǔn)“來選出前K個(gè)分?jǐn)?shù)最高的特征的類,我們可以借此除去最可能獨(dú)立于標(biāo)簽,與我們分類目的無關(guān)的特征。
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2
# 再使用SelectKBest轉(zhuǎn)換器類,用卡方函數(shù)打分,初始化轉(zhuǎn)換器。test = SelectKBest(score_func=chi2, k=3)
test.fit(X, Y)
# 得分情況
np.set_printoptions(precision=3)
print(test.scores_)
[6.365e+03 6.416e+03 6.286e+03 8.295e+08
2.949e+01 2.240e+01 3.059e+01]
卡方檢驗(yàn)的本質(zhì)是推測(cè)兩組數(shù)據(jù)之間的差異,其檢驗(yàn)的原假設(shè)是”兩組數(shù)據(jù)是相互獨(dú)立的”。卡方檢驗(yàn)返回卡方值和P值兩個(gè)統(tǒng)計(jì)量,其中卡方值很難界定有效的范圍,而p值,我們一般使用0.01或0.05作為顯著性水平,即p值判斷的邊界。
從特征工程的角度,我們希望選取卡方值很大,p值小于0.05的特征,即和標(biāo)簽是相關(guān)聯(lián)的特征。而調(diào)用SelectKBest之前,我們可以直接從chi2實(shí)例化后的模型中獲得各個(gè)特征所對(duì)應(yīng)的卡方值和P值。
F檢驗(yàn)另外類似的方法還有F檢驗(yàn),又稱ANOVA,方差齊性檢驗(yàn),是用來捕捉每個(gè)特征與標(biāo)簽之間的線性關(guān)系的過濾方法。它即可以做回歸也可以做分類,因此包含feature_selection.f_classif(F檢驗(yàn)分類)和feature_selection.f_regression(F檢驗(yàn)回歸)兩個(gè)類。其中F檢驗(yàn)分類用于標(biāo)簽是離散型變量的數(shù)據(jù),而F檢驗(yàn)回歸用于標(biāo)簽是連續(xù)型變量的數(shù)據(jù)。
F檢驗(yàn)的本質(zhì)是尋找兩組數(shù)據(jù)之間的線性關(guān)系,其原假設(shè)是”數(shù)據(jù)不存在顯著的線性關(guān)系“。它返回F值和p值兩個(gè)統(tǒng) 計(jì)量。
和卡方過濾一樣,我們希望選取p值小于0.05或0.01的特征,這些特征與標(biāo)簽時(shí)顯著線性相關(guān)的,而p值大于 0.05或0.01的特征則被我們認(rèn)為是和標(biāo)簽沒有顯著線性關(guān)系的特征,應(yīng)該被刪除。
互信息互信息法是用來捕捉每個(gè)特征與標(biāo)簽之間的任意關(guān)系(包括線性和非線性關(guān)系)的過濾方法。和F檢驗(yàn)相似,它既可以做回歸也可以做分類,并且包含兩個(gè)類 feature_selection.mutual_info_classif(互信息分類)和feature_selection.mutual_info_regression(互信息回歸)。這兩個(gè)類的用法和參數(shù)都和F檢驗(yàn)一模一樣,不過互信息法比F檢驗(yàn)更加強(qiáng)大,F(xiàn)檢驗(yàn)只能夠找出線性關(guān)系,而互信息法可以找出任意關(guān)系。
互信息法不返回p值或F值類似的統(tǒng)計(jì)量,它返回“每個(gè)特征與目標(biāo)之間的互信息量的估計(jì)”,這個(gè)估計(jì)量在[0,1]之間取值,為0則表示兩個(gè)變量獨(dú)立,為1則表示兩個(gè)變量完全相關(guān)。
關(guān)于F檢驗(yàn)和互信息,可以參見官方例子:Comparison of F-test and mutual information[1]
提取簡(jiǎn)化后的特征
# 調(diào)用transform()或直接使用fit_transform方法,# 對(duì)相同的數(shù)據(jù)集進(jìn)行預(yù)處理和轉(zhuǎn)換。
new_features = test.transform(X)
# 打印出特征提取前后特征數(shù)print(‘原始特征數(shù):’, X.shape[1])
print(‘簡(jiǎn)化的特征數(shù):’, new_features.shape[1])
原始特征數(shù): 7
簡(jiǎn)化的特征數(shù): 3
chi_sq = pd.DataFrame(fit.scores_, columns = [“Chi_Square”], index=features.columns)
chi_sq = chi_sq.reset_index()
chi_sq.sort_values(‘Chi_Square’,ascending=0)
皮爾遜相關(guān)系數(shù)Pearsonr函數(shù)的接口幾乎與scikit-learn單變量轉(zhuǎn)換器接口一致,該函數(shù)接收兩個(gè)數(shù)組 (當(dāng)前例子中為x和y)作為參數(shù),返回兩個(gè)數(shù)組:每個(gè)特征的皮爾遜相關(guān)系數(shù)和p值,直接把它傳入到SelectKBest函數(shù)中。
SciPy的pearsonr函數(shù)參數(shù)為兩個(gè)數(shù)組,但要注意的是第一個(gè)參數(shù)x為一維數(shù)組。我們來實(shí)現(xiàn)一個(gè)包裝器函數(shù),這樣就能像前面那樣處理多維數(shù)組。
from scipy.stats import pearsonr
def multivariate_pearsonr(X, Y):
# 創(chuàng)建scores和pvalues數(shù)組,遍歷數(shù)據(jù)集的每一列。
scores, pvalues = [], []
for column in range(X.shape[1]):
# 只計(jì)算該列的皮爾遜相關(guān)系數(shù)和p值,并將其存儲(chǔ)到相應(yīng)數(shù)組中。
cur_score, cur_p = pearsonr(X[:,column], Y)
scores.append(abs(cur_score))
pvalues.append(cur_p)
#函數(shù)最后返回包含皮爾遜相關(guān)系數(shù)和p值的元組。
return (np.array(scores), np.array(pvalues))
該方法衡量的是變量之間的線性相關(guān)性,結(jié)果的取值區(qū)間為,
-1表示完全的負(fù)相關(guān);
+1表示完全的正相關(guān);
0表示沒有線性相關(guān)。
現(xiàn)在,就可以像之前那樣使用轉(zhuǎn)換器類,根據(jù)皮爾遜相關(guān)系數(shù)對(duì)特征進(jìn)行排序。
m_pearsonr = SelectKBest(score_func=multivariate_pearsonr, k=3)
X_pearson = m_pearsonr.fit_transform(X, Y)
print(m_pearsonr.scores_)
[9.989e-01 9.992e-01 9.994e-01 3.903e-01
9.078e-03 9.203e-04 2.001e-02]
pearsonr = pd.DataFrame(m_pearsonr.scores_, columns = [“pearsonr”], index=features.columns)
pearsonr = pearsonr.reset_index()
pearsonr.sort_values(‘pearsonr’,ascending=0)
多重共線性方差膨脹系數(shù)方差膨脹系數(shù)(variance inflation factor,VIF)是衡量多元線性回歸模型中復(fù) (多重)共線性嚴(yán)重程度的一種度量。它表示回歸系數(shù)估計(jì)量的方差與假設(shè)自變量間不線性相關(guān)時(shí)方差相比的比值。
多重共線性是指自變量之間存在線性相關(guān)關(guān)系,即一個(gè)自變量可以是其他一個(gè)或幾個(gè)自變量的線性組合。
通常以10作為判斷邊界。
當(dāng)VIF《10,不存在多重共線性;
當(dāng)10《=VIF《100,存在較強(qiáng)的多重共線性;
當(dāng)VIF》=100, 存在嚴(yán)重多重共線性。
from statsmodels.stats.outliers_influence import variance_inflation_factor
def calculate_vif(features):
vif = pd.DataFrame()
vif[“index”] = features.columns
vif[“VIF”] = [variance_inflation_factor(features.values, i) for i in range(features.shape[1])]
return(vif)
vif = calculate_vif(features)
while vif[‘VIF’][vif[‘VIF’] 》 10].any():
remove = vif.sort_values(‘VIF’,ascending=0)[‘index’][:1]
features.drop(remove,axis=1,inplace=True)
vif = calculate_vif(features)
vif
過濾法總結(jié)
最后用一張表格將過濾法做個(gè)總結(jié),方便大家查閱學(xué)習(xí)。
類 | 說明 | 超參數(shù)的選擇 |
---|---|---|
VarianceThreshold |
方差過濾,可輸入方差閾值, 返回方差大于閾值的新特征矩陣 |
看具體數(shù)據(jù)究竟是含有更多噪聲 還是更多有效特征一般就使用0或1 來篩選也可以畫學(xué)習(xí)曲線 或取中位數(shù)跑模型來幫助確認(rèn) |
SelectKBest |
用來選取K個(gè)統(tǒng)計(jì)量結(jié)果最佳的特征, 生成看配合使用的統(tǒng)計(jì)量 符合統(tǒng)計(jì)量要求的新特征矩陣 |
看配合使用的統(tǒng)計(jì)量 |
chi2 | 卡方檢驗(yàn),專用于分類算法,捕捉相關(guān)性 | 追求p小于顯著性水平的特征 |
f_classif |
F檢驗(yàn)分類,只能捕捉線性相關(guān)性 要求數(shù)據(jù)服從正態(tài)分布 |
追求p小于顯著性水平的特征 |
f_regression |
F檢驗(yàn)回歸,只能捕捉線性相關(guān)性 要求數(shù)據(jù)服從正態(tài)分布 |
追求p小于顯著性水平的特征 |
mutual_info_classif |
互信息分類,可以捕捉任何相關(guān)性 追求互信息估計(jì)大于0的特征 不能用于稀疏矩陣 |
追求互信息估計(jì)大于0的特征 |
mutual_info_regression |
互信息回歸,可以捕捉任何相關(guān)性 不能用于稀疏矩陣 |
追求互信息估計(jì)大于0的特征 |
pearsonr | 皮爾遜相關(guān)系數(shù),只能捕捉線性相關(guān)關(guān)系 | 追求p小于顯著性水平的特征 |
責(zé)任編輯:haq
-
數(shù)據(jù)
+關(guān)注
關(guān)注
8文章
6820瀏覽量
88747 -
模型
+關(guān)注
關(guān)注
1文章
3116瀏覽量
48661
原文標(biāo)題:特征選擇與提取最全總結(jié)之過濾法
文章出處:【微信號(hào):gh_6a53af9e8109,微信公眾號(hào):上海磐啟微電子有限公司】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論