1 特征工程是什麼?
有這麼一句話在業界廣泛流傳:資料和特征決定了機器學習的上限,而模型和算法隻是逼近這個上限而已。那特征工程到底是什麼呢?顧名思義,其本質是一項工程活動,目的是最大限度地從原始資料中提取特征以供算法和模型使用。通過總結和歸納,人們認為特征工程包括以下方面:
2 資料預處理
通過特征提取,我們能得到未經處理的特征,這時的特征可能有以下問題:
不屬于同一量綱:即特征的規格不一樣,不能夠放在一起比較。無量綱化可以解決這一問題。
資訊備援:對于某些定量特征,其包含的有效資訊為區間劃分,例如學習成績,假若隻關心“及格”或不“及格”,那麼需要将定量的考分,轉換成“1”和“0”表示及格和未及格。二值化可以解決這一問題。
定性特征不能直接使用:某些機器學習算法和模型隻能接受定量特征的輸入,那麼需要将定性特征轉換為定量特征。最簡單的方式是為每一種定性值指定一個定量值,但是這種方式過于靈活,增加了調參的工作。通常使用啞編碼的方式将定性特征轉換為定量特征:假設有N種定性值,則将這一個特征擴充為N種特征,當原始特征值為第i種定性值時,第i個擴充特征指派為1,其他擴充特征指派為0。啞編碼的方式相比直接指定的方式,不用增加調參的工作,對于線性模型來說,使用啞編碼後的特征可達到非線性的效果。
存在缺失值:缺失值需要補充。
資訊使用率低:不同的機器學習算法和模型對資料中資訊的利用是不同的,之前提到線上性模型中,使用對定性特征啞編碼可以達到非線性的效果。類似地,對定量變量多項式化,或者進行其他的轉換,都能達到非線性的效果。
我們使用sklearn中的preproccessing庫來進行資料預處理,可以覆寫以上問題的解決方案。
2.1 無量綱化
無量綱化使不同規格的資料轉換到同一規格。常見的無量綱化方法有标準化和區間縮放法。标準化的前提是特征值服從正态分布,标準化後,其轉換成标準正态分布。區間縮放法利用了邊界值資訊,将特征的取值區間縮放到某個特點的範圍,例如[0, 1]等。
2.1.1 标準化
标準化需要計算特征的均值和标準差,公式表達為:
1 from sklearn.preprocessing import StandardScaler
3 #标準化,傳回值為标準化後的資料
4 StandardScaler().fit_transform(iris.data)
2.1.2 區間縮放法
區間縮放法的思路有多種,常見的一種為利用兩個最值進行縮放,公式表達為:
使用preproccessing庫的MinMaxScaler類對資料進行區間縮放的代碼如下:
from sklearn.preprocessing import MinMaxScaler
#區間縮放,傳回值為縮放到[0, 1]區間的資料
MinMaxScaler().fit_transform(iris.data)
2.1.3 标準化與歸一化的差別
簡單來說,标準化是依照特征矩陣的列處理資料,其通過求z-score的方法,将樣本的特征值轉換到同一量綱下。歸一化是依照特征矩陣的行處理資料,其目的在于樣本向量在點乘運算或其他核函數計算相似性時,擁有統一的标準,也就是說都轉化為“機關向量”。規則為l2的歸一化公式如下:
使用preproccessing庫的Normalizer類對資料進行歸一化的代碼如下:
1 from sklearn.preprocessing import Normalizer
3 #歸一化,傳回值為歸一化後的資料
4 Normalizer().fit_transform(iris.data)
歸一化
不同的特征有不同的取值範圍,在有些算法中,例如線性模型或者距離相關的模型像聚類模型、knn模型等,特征的取值範圍會對最終的結果産生較大影響,例如二進制特征的取值範圍為[0,1],而距離特征取值可能是[0,正無窮),在實際使用中會對距離進行截斷,例如[0,3000000],但是這兩個特征由于取值範圍不一緻導緻了模型可能會更偏向于取值範圍較大的特征,為了平衡取值範圍不一緻的特征,需要對特征進行歸一化處理,将特征取值歸一化到[0,1]區間。常用的歸一化方法包括1.函數歸一化,通過映射函數将特征取值映射到[0,1]區間,例如最大最小值歸一化方法,是一種線性的映射。還有通過非線性函數的映射,例如log函數等。2.分次元歸一化,可以使用最大最小歸一化方法,但是最大最小值選取的是所屬類别的最大最小值,即使用的是局部最大最小值,不是全局的最大最小值。3.排序歸一化,不管原來的特征取值是什麼樣的,将特征按大小排序,根據特征所對應的序給予一個新的值。
2.2 對定量特征二值化
定量特征二值化的核心在于設定一個門檻值,大于門檻值的指派為1,小于等于門檻值的指派為0,公式表達如下:
使用preproccessing庫的Binarizer類對資料進行二值化的代碼如下:
1 from sklearn.preprocessing import Binarizer
3 #二值化,門檻值設定為3,傳回值為二值化後的資料
4 Binarizer(threshold=3).fit_transform(iris.data)
2.3 對定性特征啞編碼
在這個例子中,我們假設你有一個輸出序列如下3個标簽:
Cold,warm,hot
10個時間序列的示例順序可以是:
Cold,cold,warm,cold,hot,hot,warm,cold,warm,hot
這将首先需要一個整數編碼,如1,2,3,然後是整數到one hot編碼具有3個值的二進制向量,例如[1,0,0]。
這個情況下提供序列中每個可能值的至少一個示例。是以,我們可以使用自動方法來定義整數到二進制向量的映射。
在這個例子中,我們将使用scikit學習庫的編碼器。具體來說,LabelEncoder建立标簽的整數編碼,OneHotEncoder用于建立整數編碼值的one hot編碼。
from numpy import array
from numpy import argmax
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import OneHotEncoder
# define example
data = ['cold', 'cold', 'warm', 'cold', 'hot', 'hot', 'warm', 'cold', 'warm', 'hot']
values = array(data)
print(values)
# integer encode
label_encoder = LabelEncoder()
integer_encoded = label_encoder.fit_transform(values)
print(integer_encoded)
# binary encode
onehot_encoder = OneHotEncoder(sparse=False)
integer_encoded = integer_encoded.reshape(len(integer_encoded), 1)
onehot_encoded = onehot_encoder.fit_transform(integer_encoded)
print(onehot_encoded)
# invert first example
inverted = label_encoder.inverse_transform([argmax(onehot_encoded[0, :])])
print(inverted)
運作示例首先列印标簽序列。之後是标簽的整數編碼,最後是one hot編碼。訓練資料包含所有可能示例的集合,是以我們可以依靠整數和one hot編碼變換來建立标簽到編碼的完整映射。
預設情況下,OneHotEncoder類将傳回更高效的稀疏編碼,這可能不适用于某些應用程式。例如使用Keras深度學習庫。在這種情況下,我們通過設定sparse = False這個參數來禁用稀疏傳回類型。
首先,我們可以使用argmax()NumPy函數來找到具有最大值的列的索引。然後可以将其輸入到LabelEncoder,以計算反向變換回文本标簽。運作結果為:
['cold' 'cold' 'warm' 'cold' 'hot' 'hot' 'warm' 'cold' 'warm' 'hot']
[0 0 2 0 1 1 2 0 2 1]
[[ 1. 0. 0.]
[ 1. 0. 0.]
[ 0. 0. 1.]
[ 0. 1. 0.]
[ 0. 1. 0.]]
['cold']
在下一個例子中,我們來看一下如何直接對一個整數值進行one hot編碼。
您可能有一個已經是整數編碼的序列。
經過處理後,您可以直接使用整數。或者,您可以直接對整數進行one hot 編碼。這是非常重要的如果整數沒有真正的順序關系并且隻是标簽的占位符。
Keras提供了一個名為to_categorical()的函數,它可以幫助你使用one hot編碼整數資料。接下來我們看一個小例子:
在這個例子中,我們有4個整數值[0,1,2,3],我們有以下10個數字的輸入序列:
Data = [1,3,2,0,3,2,2,1,0,1]
該序列具有已知了所有值,是以我們可以直接使用to_categorical()函數。以下列出了此功能的完整示例。
from keras.utils import to_categorical
data = [1, 3, 2, 0, 3, 2, 2, 1, 0, 1]
data = array(data)
print(data)
# one hot encode
encoded = to_categorical(data)
print(encoded)
# invert encoding
inverted = argmax(encoded[0])
運作示例并列印輸入序列。
然後将整數編碼為二進制向量并列印。我們可以看到,正如我們預期的那樣,第一個整數值1被編碼為[0,1,0,0]。
然後,我們使用NumPy argmax()函數反轉編碼,該函數傳回第一個整數的期望值1的序列中的第一個值。
[1 3 2 0 3 2 2 1 0 1]
[[ 0. 1. 0. 0.]
[ 0. 0. 0. 1.]
[ 0. 0. 1. 0.]
[ 1. 0. 0. 0.]
[ 0. 1. 0. 0.]
1
2.4 缺失值填充與計算
預設值處理的一般步驟:确定預設值範圍、去除不需要的字段、填充預設值内容(經驗值、均值、中位數、衆數、推測值)、重新擷取資料。
1、缺失值剔除
python實作:data.dropna()
缺失值填充(填充可以填充均值/中位數/衆數)
python實作
from sklearn.preprocessing import Imputer
imputer=Imputer(strategy='mean') #mean, median, most_frequent
data['累計票房']=imputer.fit_transform(data[['累計票房']])
data['豆瓣評分']=imputer.fit_transform(data[['豆瓣評分']])
或者:
df['distance'] = df['Distance'].fillna(0).astype(int)#填充成固定值
data['累計票房'] = data['累計票房'].fillna(data['累計票房'].mean()))#均值
data['累計票房'] = data['累計票房'].fillna(data['累計票房']. mode ()))#衆數
data['累計票房'] = data['累計票房'].fillna(method='pad')#用前一個數進行填充
data['累計票房'] = data['累計票房'].fillna(method=’bfill’)#用後一個數進行填充
data['累計票房'] = data['累計票房'].interpolate()#用插值法進行填充
#用KNN進行填充
from fancyimpute import BiScaler, KNN, NuclearNormMinimization, SoftImpute
dataset = KNN(k=3).complete(dataset)
#用随機森林進行填充
from sklearn.ensemble import RandomForestRegressor
zero_columns_2 = ['機構查詢數量', '直接聯系人數量', '直接聯系人在黑名單數量', '間接聯系人在黑名單數量',
'引起黑名單的直接聯系人數量', '引起黑名單的直接聯系人占比']
#将出現空值的除了預測的列全部取出來,不用于訓練
dataset_list2 = [x for x in dataset if x not in zero_columns_2]
dataset_2 = dataset[dataset_list2]
# 取出灰階分不為空的全部樣本進行訓練
know = dataset_2[dataset_2['灰階分'].notnull()]
print(know.shape) #26417, 54
# 取出灰階分為空的樣本用于填充空值
unknow = dataset_2[dataset_2['灰階分'].isnull()]
print(unknow.shape) #2078, 54
y = ['灰階分']
x = [1]
know_x2 = know.copy()
know_y2 = know.copy()
print(know_y2.shape)
#
know_x2.drop(know_x2.columns[x], axis=1, inplace=True)
print(know_x2.shape)
know_y2 = know[y]
# RandomForestRegressor
rfr = RandomForestRegressor(random_state=666, n_estimators=2000, n_jobs=-1)
rfr.fit(know_x2, know_y2)
# 填充為空的樣本
unknow_x2 = unknow.copy()
unknow_x2.drop(unknow_x2.columns[x], axis=1, inplace=True)
print(unknow_x2.shape) #(2078, 53)
unknow_y2 = rfr.predict(unknow_x2)
unknow_y2 = pd.DataFrame(unknow_y2, columns=['灰階分'])
2.5離散化
在上面介紹過連續值的取值空間可能是無窮的,為了便于表示和在模型中處理,需要對連續值特征進行離散化處理。常用的離散化方法包括等值劃分和等量劃分。等值劃分是将特征按照值域進行均分,每一段内的取值等同處理。例如某個特征的取值範圍為[0,10],我們可以将其劃分為10段,[0,1),[1,2),...,[9,10)。等量劃分是根據樣本總數進行均分,每段等量個樣本劃分為1段。例如距離特征,取值範圍[0,3000000],現在需要切分成10段,如果按照等比例劃分的話,會發現絕大部分樣本都在第1段中。使用等量劃分就會避免這種問題,最終可能的切分是[0,100),[100,300),[300,500),..,[10000,3000000],前面的區間劃分比較密,後面的比較稀疏。
2.6資料變換
常見的資料變換有基于多項式的、基于指數函數的、基于對數函數的。4個特征,度為2的多項式轉換公式如下:
使用preproccessing庫的PolynomialFeatures類對資料進行多項式轉換的代碼如下:
1 from sklearn.preprocessing import PolynomialFeatures
3 #多項式轉換
4 #參數degree為度,預設值為2
5 PolynomialFeatures().fit_transform(iris.data)
基于單變元函數的資料變換可以使用一個統一的方式完成,使用preproccessing庫的FunctionTransformer對資料進行對數函數轉換的代碼如下:
1 from numpy import log1p
2 from sklearn.preprocessing import FunctionTransformer
3
4 #自定義轉換函數為對數函數的資料變換
5 #第一個參數是單變元函數
6 FunctionTransformer(log1p).fit_transform(iris.data)
2.6 回顧
類
功能
說明
StandardScaler
無量綱化
标準化,基于特征矩陣的列,将特征值轉換至服從标準正态分布
MinMaxScaler
區間縮放,基于最大最小值,将特征值轉換到[0, 1]區間上
Normalizer
基于特征矩陣的行,将樣本向量轉換為“機關向量”
Binarizer
二值化
基于給定門檻值,将定量特征按門檻值劃分
OneHotEncoder
啞編碼
将定性資料編碼為定量資料
Imputer
缺失值計算
計算缺失值,缺失值可填充為均值等
PolynomialFeatures
多項式資料轉換
FunctionTransformer
自定義單中繼資料轉換
使用單變元的函數來轉換資料
3 特征選擇
當資料預處理完成後,我們需要選擇有意義的特征輸入機器學習的算法和模型進行訓練。通常來說,從兩個方面考慮來選擇特征:
特征是否發散:如果一個特征不發散,例如方差接近于0,也就是說樣本在這個特征上基本上沒有差異,這個特征對于樣本的區分并沒有什麼用。
特征與目标的相關性:這點比較顯見,與目标相關性高的特征,應當優選選擇。除方差法外,本文介紹的其他方法均從相關性考慮。
根據特征選擇的形式又可以将特征選擇方法分為3種:
Filter:過濾法,按照發散性或者相關性對各個特征進行評分,設定門檻值或者待選擇門檻值的個數,選擇特征。
Wrapper:包裝法,根據目标函數(通常是預測效果評分),每次選擇若幹特征,或者排除若幹特征。
Embedded:嵌入法,先使用某些機器學習的算法和模型進行訓練,得到各個特征的權值系數,根據系數從大到小選擇特征。類似于Filter方法,但是是通過訓練來确定特征的優劣。
我們使用sklearn中的feature_selection庫來進行特征選擇。
3.1 Filter
2. 單變量特征選擇 (Univariate feature selection)
3.1.1 方差選擇法(移除低方差的特征)
假設某特征的特征值隻有0和1,并且在所有輸入樣本中,95%的執行個體的該特征取值都是1,那就可以認為這個特征作用不大。如果100%都是1,那這個特征就沒意義了。當特征值都是離散型變量的時候這種方法才能用,如果是連續型變量,就需要将連續變量離散化之後才能用。而且實際當中,一般不太會有95%以上都取某個值的特征存在,是以這種方法雖然簡單但是不太好用。可以把它作為特征選擇的預處理,先去掉那些取值變化小的特征,然後再從接下來提到的的特征選擇方法中選擇合适的進行進一步的特征選擇。
使用方差選擇法,先要計算各個特征的方差,然後根據門檻值,選擇方差大于門檻值的特征。使用feature_selection庫的VarianceThreshold類來選擇特征的代碼如下:
1 from sklearn.feature_selection import VarianceThreshold
3 #方差選擇法,傳回值為特征選擇後的資料
4 #參數threshold為方差的門檻值
5 VarianceThreshold(threshold=3).fit_transform(iris.data)
3.1.2單變量特征選擇 (Univariate feature selection)
單變量特征選擇的原理是分别單獨的計算每個變量的某個統計名額,根據該名額來判斷哪些名額重要,剔除那些不重要的名額。
對于分類問題(y離散),可采用:
卡方檢驗,f_classif, mutual_info_classif,互資訊
對于回歸問題(y連續),可采用:
皮爾森相關系數,f_regression, mutual_info_regression,最大資訊系數
這種方法比較簡單,易于運作,易于了解,通常對于了解資料有較好的效果(但對特征優化、提高泛化能力來說不一定有效)。這種方法有許多改進的版本、變種。
單變量特征選擇基于單變量的統計測試來選擇最佳特征。它可以看作預測模型的一項預處理。==Scikit-learn将特征選擇程式用包含 transform 函數的對象來展現==:
SelectKBest 移除得分前 k 名以外的所有特征(取top k)
SelectPercentile 移除得分在使用者指定百分比以後的特征(取top k%)
對每個特征使用通用的單變量統計檢驗: 假正率(false positive rate) SelectFpr, 僞發現率(false discovery rate) SelectFdr, 或族系誤差率 SelectFwe.
GenericUnivariateSelect 可以設定不同的政策來進行單變量特征選擇。同時不同的選擇政策也能夠使用超參數尋優,進而讓我們找到最佳的單變量特征選擇政策。
将特征輸入到評分函數,傳回一個單變量的f_score(F檢驗的值)或p-values(P值,假設檢驗中的一個标準,P-value用來和顯著性水準作比較),注意SelectKBest 和 SelectPercentile隻有得分,沒有p-value。
Notice:
The methods based on F-test estimate the degree of linear dependency between two random variables. (F檢驗用于評估兩個随機變量的線性相關性)On the other hand, mutual information methods can capture any kind of statistical dependency, but being nonparametric, they require more samples for accurate estimation.(另一方面,互資訊的方法可以捕獲任何類型的統計依賴關系,但是作為一個非參數方法,估計準确需要更多的樣本)
Feature selection with sparse data:
If you use sparse data (i.e. data represented as sparse matrices), chi2, mutual_info_regression, mutual_info_classif will deal with the data without making it dense.(如果你使用稀疏資料(比如,使用稀疏矩陣表示的資料), 卡方檢驗(chi2)、互資訊回歸(mutual_info_regression)、互資訊分類(mutual_info_classif)在處理資料時可保持其稀疏性.)
Pearson相關系數法
使用相關系數法,先要計算各個特征對目标值的相關系數以及相關系數的P值。用feature_selection庫的SelectKBest類結合相關系數來選擇特征的代碼如下:
1 from sklearn.feature_selection import SelectKBest
2 from scipy.stats import pearsonr
4 #選擇K個最好的特征,傳回選擇特征後的資料
5 #第一個參數為計算評估特征是否好的函數,該函數輸入特征矩陣和目标向量,輸出二進制組(評分,P值)的數組,數組第i項為第i個特征的評分和P值。在此定義為計算相關系數
6 #參數k為選擇的特征個數
7 SelectKBest(lambda X, Y: array(map(lambda x:pearsonr(x, Y), X.T)).T, k=2).fit_transform(iris.data, iris.target)
卡方檢驗
經典的卡方檢驗是檢驗定性自變量對定性因變量的相關性。假設自變量有N種取值,因變量有M種取值,考慮自變量等于i且因變量等于j的樣本頻數的觀察值與期望的差距,建構統計量:
這個統計量的含義簡而言之就是自變量對因變量的相關性。用feature_selection庫的SelectKBest類結合卡方檢驗來選擇特征的代碼如下:
2 from sklearn.feature_selection import chi2
5 SelectKBest(chi2, k=2).fit_transform(iris.data, iris.target)
互資訊法
經典的互資訊也是評價定性自變量對定性因變量的相關性的,互資訊計算公式如下:
為了處理定量資料,最大資訊系數法被提出,使用feature_selection庫的SelectKBest類結合最大資訊系數法來選擇特征的代碼如下:
1 from sklearn.feature_selection import SelectKBest
2 from minepy import MINE
4 #由于MINE的設計不是函數式的,定義mic方法将其為函數式的,傳回一個二進制組,二進制組的第2項設定成固定的P值0.5
5 def mic(x, y):
6 m = MINE()
7 m.compute_score(x, y)
8 return (m.mic(), 0.5)
10 #選擇K個最好的特征,傳回特征選擇後的資料
11 SelectKBest(lambda X, Y: array(map(lambda x:mic(x, Y), X.T)).T, k=2).fit_transform(iris.data, iris.target)
3.2 Wrapper
3.2.1 遞歸特征消除法
遞歸消除特征法使用一個基模型來進行多輪訓練,每輪訓練後,移除若幹權值系數的特征,再基于新的特征集進行下一輪訓練。
sklearn官方解釋:對特征含有權重的預測模型(例如,線性模型對應參數coefficients),RFE通過遞歸減少考察的特征集規模來選擇特征。首先,預測模型在原始特征上訓練,每個特征指定一個權重。之後,那些擁有最小絕對值權重的特征被踢出特征集。如此往複遞歸,直至剩餘的特征數量達到所需的特征數量。
RFECV 通過交叉驗證的方式執行RFE,以此來選擇最佳數量的特征:對于一個數量為d的feature的集合,他的所有的子集的個數是2的d次方減1(包含空集)。指定一個外部的學習算法,比如SVM之類的。通過該算法計算所有子集的validation error。選擇error最小的那個子集作為所挑選的特征。
使用feature_selection庫的RFE類來選擇特征的代碼如下:
1 from sklearn.feature_selection import RFE
2 from sklearn.linear_model import LogisticRegression
4 #遞歸特征消除法,傳回特征選擇後的資料
5 #參數estimator為基模型
6 #參數n_features_to_select為選擇的特征個數
7 RFE(estimator=LogisticRegression(), n_features_to_select=2).fit_transform(iris.data, iris.target)
3.3 Embedded
3.3.1 基于懲罰項的特征選擇法
使用帶懲罰項的基模型,除了篩選出特征外,同時也進行了降維。使用feature_selection庫的SelectFromModel類結合帶L1懲罰項的邏輯回歸模型,來選擇特征的代碼如下:
1 from sklearn.feature_selection import SelectFromModel
4 #帶L1懲罰項的邏輯回歸作為基模型的特征選擇
5 SelectFromModel(LogisticRegression(penalty="l1", C=0.1)).fit_transform(iris.data, iris.target)
L1懲罰項降維的原理在于保留多個對目标值具有同等相關性的特征中的一個,是以沒選到的特征不代表不重要。故,可結合L2懲罰項來優化。具體操作為:若一個特征在L1中的權值為1,選擇在L2中權值差别不大且在L1中權值為0的特征構成同類集合,将這一集合中的特征平分L1中的權值,故需要建構一個新的邏輯回歸模型:
1 from sklearn.linear_model import LogisticRegression
2
3 class LR(LogisticRegression):
4 def __init__(self, threshold=0.01, dual=False, tol=1e-4, C=1.0,
5 fit_intercept=True, intercept_scaling=1, class_weight=None,
6 random_state=None, solver='liblinear', max_iter=100,
7 multi_class='ovr', verbose=0, warm_start=False, n_jobs=1):
8
9 #權值相近的門檻值
10 self.threshold = threshold
11 LogisticRegression.__init__(self, penalty='l1', dual=dual, tol=tol, C=C,
12 fit_intercept=fit_intercept, intercept_scaling=intercept_scaling, class_weight=class_weight,
13 random_state=random_state, solver=solver, max_iter=max_iter,
14 multi_class=multi_class, verbose=verbose, warm_start=warm_start, n_jobs=n_jobs)
15 #使用同樣的參數建立L2邏輯回歸
16 self.l2 = LogisticRegression(penalty='l2', dual=dual, tol=tol, C=C, fit_intercept=fit_intercept, intercept_scaling=intercept_scaling, class_weight = class_weight, random_state=random_state, solver=solver, max_iter=max_iter, multi_class=multi_class, verbose=verbose, warm_start=warm_start, n_jobs=n_jobs)
18 def fit(self, X, y, sample_weight=None):
19 #訓練L1邏輯回歸
20 super(LR, self).fit(X, y, sample_weight=sample_weight)
21 self.coef_old_ = self.coef_.copy()
22 #訓練L2邏輯回歸
23 self.l2.fit(X, y, sample_weight=sample_weight)
24
25 cntOfRow, cntOfCol = self.coef_.shape
26 #權值系數矩陣的行數對應目标值的種類數目
27 for i in range(cntOfRow):
28 for j in range(cntOfCol):
29 coef = self.coef_[i][j]
30 #L1邏輯回歸的權值系數不為0
31 if coef != 0:
32 idx = [j]
33 #對應在L2邏輯回歸中的權值系數
34 coef1 = self.l2.coef_[i][j]
35 for k in range(cntOfCol):
36 coef2 = self.l2.coef_[i][k]
37 #在L2邏輯回歸中,權值系數之差小于設定的門檻值,且在L1中對應的權值為0
38 if abs(coef1-coef2) < self.threshold and j != k and self.coef_[i][k] == 0:
39 idx.append(k)
40 #計算這一類特征的權值系數均值
41 mean = coef / len(idx)
42 self.coef_[i][idx] = mean
43 return self
使用feature_selection庫的SelectFromModel類結合帶L1以及L2懲罰項的邏輯回歸模型,來選擇特征的代碼如下:
3 #帶L1和L2懲罰項的邏輯回歸作為基模型的特征選擇
4 #參數threshold為權值系數之差的門檻值
5 SelectFromModel(LR(threshold=0.5, C=0.1)).fit_transform(iris.data, iris.target)
3.3.2 基于樹模型的特征選擇法
樹模型中GBDT也可用來作為基模型進行特征選擇,使用feature_selection庫的SelectFromModel類結合GBDT模型,來選擇特征的代碼如下:
2 from sklearn.ensemble import GradientBoostingClassifier
4 #GBDT作為基模型的特征選擇
5 SelectFromModel(GradientBoostingClassifier()).fit_transform(iris.data, iris.target)
3.4 回顧
所屬方式
VarianceThreshold
Filter
方差選擇法
SelectKBest
可選關聯系數、卡方校驗、最大資訊系數作為得分計算的方法
RFE
Wrapper
遞歸地訓練基模型,将權值系數較小的特征從特征集合中消除
SelectFromModel
Embedded
訓練基模型,選擇權值系數較高的特征