特徵選擇是識別和選擇與目標變量最相關的輸入變量子集的過程。
特徵選擇最簡單的情況可能是存在數字輸入變量和用於迴歸預測建模的數字目標的情況。這是因為可以計算出每個輸入變量與目標之間的關係強度,稱為相關性,並進行相對比較。
本文中我們將展示如何使用數值輸入數據執行特徵選擇以進行迴歸預測建模。
本文分為四部分:
- 1、迴歸數據集
- 2、數值特徵選擇
- 2.1、相關特徵選擇
- 2.2、相關信息特徵選擇
- 3、使用選定特徵建模
- 3.1、使用所有特徵構建的模型
- 3.2、使用相關特徵構建的模型
- 3.3、使用相關信息特徵構建的模型
- 4、調整所選特徵的數量
一、迴歸數據集
我們將使用綜合迴歸數據集作為本文的基礎。
迴歸問題是我們要預測數值的問題。在這種情況下,我們需要一個具有數字輸入變量的數據集。
scikit-learn庫中的make_regression()函數可用於定義數據集。它提供了對樣本數量,輸入特徵數量以及重要的是相關和冗餘輸入特徵數量的控制。這一點至關重要,因為我們特別希望我們知道的數據集具有一些冗餘輸入特徵。
在這種情況下,我們將定義一個包含1000個樣本的數據集,每個樣本具有100個輸入特徵,其中10個是信息性的,其餘90個是冗餘的。
<code># generate regression dataset X, y = make_regression(n_samples=1000, n_features=100, n_informative=10, noise=0.1, random_state=1)/<code>
希望特徵選擇技術可以識別與目標相關的那些特徵中的一些或全部,或者至少識別併除去某些冗餘輸入特徵。
定義後,我們可以將數據分為訓練集和測試集,以便我們擬合和評估學習模型。
我們將使用scikit-learn形式的train_test_split()函數,並將67%的數據用於訓練,並將33%的數據用於測試。
<code> ... # split into train and test sets X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=1) 1 2 3 ... # split into train and test sets X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=1)/<code>
將這些特徵結合在一起,下面列出了定義,拆分和彙總原始迴歸數據集的完整示例。
<code># load and summarize the dataset from sklearn.datasets import make_regression from sklearn.model_selection import train_test_split # generate regression dataset X, y = make_regression(n_samples=1000, n_features=100, n_informative=10, noise=0.1, random_state=1) # split into train and test sets X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=1) # summarize print('Train', X_train.shape, y_train.shape) print('Test', X_test.shape, y_test.shape)/<code>
運行示例將報告訓練和測試集的輸入和輸出特徵的大小。
我們可以看到,我們有670個訓練示例和330個測試示例。
現在,我們已經加載並準備了數據集,我們可以探索特徵選擇。
二、數值特徵選擇
有兩種流行的特徵選擇技術,可用於數字輸入數據和數字目標變量。
他們是:
- 相關統計。
- 相互信息統計。
(一)相關特徵選擇
相關性是兩個變量如何一起變化的度量。也許最常見的相關度量是Pearson相關,它假設每個變量的高斯分佈並報告它們的線性關係。
對於數字預測變量,量化與結果之間的每個關係的經典方法是使用樣本相關性統計量。
線性相關分數通常是介於-1和1之間的值,0表示沒有關係。對於特徵選擇,我們通常對正值感興趣,正值越大,關係越大,並且應該更可能選擇特徵進行建模。這樣,線性相關可以轉換為僅具有正值的相關統計量。
scikit-learn庫在f_regression()函數中提供了相關統計的實現。此函數可用於特徵選擇策略中,例如通過SelectKBest類選擇前k個最相關的特徵(最大值)。
例如,我們可以定義SelectKBest類以使用f_regression()函數並選擇所有特徵,然後轉換訓練和測試集。
<code># configure to select all features fs = SelectKBest(score_func=f_regression, k='all') # learn relationship from training data fs.fit(X_train, y_train) # transform train input data X_train_fs = fs.transform(X_train) # transform test input data X_test_fs = fs.transform(X_test) return X_train_fs, X_test_fs, fs/<code>
然後,我們可以輸出每個變量的分數(越大越好),並將每個變量的分數繪製為條形圖,以瞭解應該選擇多少個特徵。
<code>for i in range(len(fs.scores_)): print('Feature %d: %f' % (i, fs.scores_[i])) # plot the scores pyplot.bar([i for i in range(len(fs.scores_))], fs.scores_) pyplot.show()/<code>
將其與上一節中數據集的數據準備一起進行綁定,下面列出了完整的示例。
<code>from sklearn.datasets import make_regression from sklearn.model_selection import train_test_split from sklearn.feature_selection import SelectKBest from sklearn.feature_selection import f_regression from matplotlib import pyplot # feature selection def select_features(X_train, y_train, X_test): # configure to select all features fs = SelectKBest(score_func=f_regression, k='all') # learn relationship from training data fs.fit(X_train, y_train) # transform train input data X_train_fs = fs.transform(X_train) # transform test input data X_test_fs = fs.transform(X_test) return X_train_fs, X_test_fs, fs # load the dataset X, y = make_regression(n_samples=1000, n_features=100, n_informative=10, noise=0.1, random_state=1) # split into train and test sets X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=1) # feature selection X_train_fs, X_test_fs, fs = select_features(X_train, y_train, X_test) # what are scores for the features for i in range(len(fs.scores_)): print('Feature %d: %f' % (i, fs.scores_[i])) # plot the scores pyplot.bar([i for i in range(len(fs.scores_))], fs.scores_) pyplot.show()/<code>
首先運行示例將輸出為每個輸入特徵和目標變量計算的分數。
請注意,您的特定結果可能會有所不同。嘗試運行該示例幾次。
我們可以看到,某些變量的分數高於其他變量,而其他變量的分數則大得多,例如Feature 9的分數為101。
為每個輸入特徵創建一個特徵重要性評分的條形圖。
該圖清楚地表明8至10個特徵比其他重要得多。
在配置SelectKBest時,我們可以設置k=10來選擇這些最重要的特徵。
(二)相關信息特徵選擇
來自信息理論領域的相關信息是信息增益(通常用於決策樹的構建)在特徵選擇中的應用。
在兩個變量之間計算相關信息,並在給定另一個變量的已知值的情況下測量一個變量的不確定性降低。
考慮兩個離散(分類或有序)變量(例如分類輸入和分類輸出數據)的分佈時,相關信息很簡單。儘管如此,它仍可適用於數字輸入和輸出變量。
scikit-learn庫中的common_info_regression()函數通過數字輸入和輸出變量提供了用於信息選擇的相關信息實現。
與f_regression()一樣,它可以用於SelectKBest特徵選擇策略(和其他策略)中。
<code># configure to select all features fs = SelectKBest(score_func=mutual_info_regression, k='all') # learn relationship from training data fs.fit(X_train, y_train) # transform train input data X_train_fs = fs.transform(X_train) # transform test input data X_test_fs = fs.transform(X_test) return X_train_fs, X_test_fs, fs/<code>
我們可以使用數據集上的相關信息來執行特徵選擇。
下面列出了使用相關信息進行數字特徵選擇的完整示例。
<code>from sklearn.datasets import make_regression from sklearn.model_selection import train_test_split from sklearn.feature_selection import SelectKBest from sklearn.feature_selection import mutual_info_regression from matplotlib import pyplot # feature selection def select_features(X_train, y_train, X_test): # configure to select all features fs = SelectKBest(score_func=mutual_info_regression, k='all') # learn relationship from training data fs.fit(X_train, y_train) # transform train input data X_train_fs = fs.transform(X_train) # transform test input data X_test_fs = fs.transform(X_test) return X_train_fs, X_test_fs, fs # load the dataset X, y = make_regression(n_samples=1000, n_features=100, n_informative=10, noise=0.1, random_state=1) # split into train and test sets X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=1) # feature selection X_train_fs, X_test_fs, fs = select_features(X_train, y_train, X_test) # what are scores for the features for i in range(len(fs.scores_)): print('Feature %d: %f' % (i, fs.scores_[i])) # plot the scores pyplot.bar([i for i in range(len(fs.scores_))], fs.scores_) pyplot.show()/<code>
首先運行示例將輸出為每個輸入特徵和目標變量計算的分數。
請注意,您的特定結果可能會有所不同。
我們可以看到許多特徵的分數為0.0,而這已經確定了許多可能與目標有關的特徵。
為每個輸入特徵創建一個特徵重要性評分的條形圖。
與相關特徵選擇方法相比,我們可以清楚地看到更多的特徵被標記為相關。這可能是由於我們在其構造中添加到數據集中的統計噪聲。
既然我們知道如何針對迴歸預測建模問題對數字輸入數據執行特徵選擇,那麼我們可以嘗試使用選定的特徵開發模型並比較結果。
三、使用選定特徵建模
有許多不同的技術可用來對特徵評分和根據分數選擇特徵。您怎麼知道要使用哪個?
一種可靠的方法是使用不同的特徵選擇方法(和特徵數量)評估模型,然後選擇能夠產生最佳性能的模型的方法。
在本節中,我們將評估具有所有特徵的線性迴歸模型,並將其與根據相關統計選擇的特徵和通過互信息選擇的特徵構建的模型進行比較。
線性迴歸是測試特徵選擇方法的良好模型,因為如果從模型中刪除了不相關的特徵,則線性迴歸性能會更好。
(一)使用所有特徵構建的模型
第一步,我們將使用所有可用特徵來評估LinearRegression模型。
該模型適合訓練數據集,並在測試數據集上進行評估。
下面列出了完整的示例。
<code>from sklearn.datasets import make_regression from sklearn.model_selection import train_test_split from sklearn.linear_model import LinearRegression from sklearn.metrics import mean_absolute_error # load the dataset X, y = make_regression(n_samples=1000, n_features=100, n_informative=10, noise=0.1, random_state=1) # split into train and test sets X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=1) # fit the model model = LinearRegression() model.fit(X_train, y_train) # evaluate the model yhat = model.predict(X_test) # evaluate predictions mae = mean_absolute_error(y_test, yhat) print('MAE: %.3f' % mae)/<code>
運行示例將在訓練數據集上輸出模型的平均絕對誤差(MAE)。
由於學習算法的隨機性,結果可能會有所不同。
在這種情況下,我們可以看到該模型實現了約0.086的誤差。
(二)使用相關特徵構建的模型
我們可以使用相關方法對特徵進行評分,然後選擇10個最相關的特徵。
下面的select_features()函數已更新以實現此目的。
<code># feature selection def select_features(X_train, y_train, X_test): # configure to select a subset of features fs = SelectKBest(score_func=f_regression, k=10) # learn relationship from training data fs.fit(X_train, y_train) # transform train input data X_train_fs = fs.transform(X_train) # transform test input data X_test_fs = fs.transform(X_test) return X_train_fs, X_test_fs, fs/<code>
下面列出了使用此特徵選擇方法評估線性迴歸模型擬合和對數據進行評估的完整示例。
<code>from sklearn.datasets import make_regression from sklearn.model_selection import train_test_split from sklearn.feature_selection import SelectKBest from sklearn.feature_selection import f_regression from sklearn.linear_model import LinearRegression from sklearn.metrics import mean_absolute_error # feature selection def select_features(X_train, y_train, X_test): # configure to select a subset of features fs = SelectKBest(score_func=f_regression, k=10) # learn relationship from training data fs.fit(X_train, y_train) # transform train input data X_train_fs = fs.transform(X_train) # transform test input data X_test_fs = fs.transform(X_test) return X_train_fs, X_test_fs, fs # load the dataset X, y = make_regression(n_samples=1000, n_features=100, n_informative=10, noise=0.1, random_state=1) # split into train and test sets X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=1) # feature selection X_train_fs, X_test_fs, fs = select_features(X_train, y_train, X_test) # fit the model model = LinearRegression() model.fit(X_train_fs, y_train) # evaluate the model yhat = model.predict(X_test_fs) # evaluate predictions mae = mean_absolute_error(y_test, yhat) print('MAE: %.3f' % mae)/<code>
該示例僅報告了使用相關統計數據選擇的100個輸入特徵中的10個的模型性能。
在這種情況下,我們看到該模型實現了約2.7的誤差分,這比使用所有特徵並獲得0.086的MAE的基線模型要大得多。
這表明,儘管該方法對選擇哪些特徵有很強的想法,但是僅從這些特徵構建模型並不能帶來更熟練的模型。這可能是因為對目標很重要的特徵被忽略了。
讓我們採用另一種方法,嘗試使用該方法刪除一些冗餘特徵,而不是所有冗餘特徵。
為此,我們可以將所選特徵的數量設置為一個更大的值(在本例中為88),希望它可以找到並丟棄90個冗餘特徵中的12個。
下面列出了完整的示例。
<code> /<code>
該示例報告了使用相關統計量選擇的100個輸入特徵中的88個的模型性能。
在本例中,我們可以看到,刪除一些冗餘特徵使性能有了小幅提升,誤差約為0.085,而基線的誤差約為0.086。
(三)使用相關信息特徵構建的模型
下面列出了實現此目的的select_features()函數的更新版本。
<code>def select_features(X_train, y_train, X_test): # configure to select a subset of features fs = SelectKBest(score_func=mutual_info_regression, k=88) # learn relationship from training data fs.fit(X_train, y_train) # transform train input data X_train_fs = fs.transform(X_train) # transform test input data X_test_fs = fs.transform(X_test) return X_train_fs, X_test_fs, fs/<code>
下面列出了使用相關信息進行特徵選擇以擬合線性迴歸模型的完整示例。
<code>from sklearn.datasets import make_regression from sklearn.model_selection import train_test_split from sklearn.feature_selection import SelectKBest from sklearn.feature_selection import mutual_info_regression from sklearn.linear_model import LinearRegression from sklearn.metrics import mean_absolute_error # feature selection def select_features(X_train, y_train, X_test): # configure to select a subset of features fs = SelectKBest(score_func=mutual_info_regression, k=88) # learn relationship from training data fs.fit(X_train, y_train) # transform train input data X_train_fs = fs.transform(X_train) # transform test input data X_test_fs = fs.transform(X_test) return X_train_fs, X_test_fs, fs # load the dataset X, y = make_regression(n_samples=1000, n_features=100, n_informative=10, noise=0.1, random_state=1) # split into train and test sets X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=1) # feature selection X_train_fs, X_test_fs, fs = select_features(X_train, y_train, X_test) # fit the model model = LinearRegression() model.fit(X_train_fs, y_train) # evaluate the model yhat = model.predict(X_test_fs) # evaluate predictions mae = mean_absolute_error(y_test, yhat) print('MAE: %.3f' % mae)/<code>
運行這個例子符合該模型在前88個選擇使用相關信息特徵選擇。
在這種情況下,我們可以看到與相關統計量相比誤差的進一步減少,在這種情況下,相對於上一節的0.085,MAE達到了大約0.084。
四、調整所選特徵的數量
在上一個示例中,我們選擇了88個特徵,但是如何知道要選擇的特徵數量是否是最佳。
無需猜測,我們可以系統地測試一系列不同數量的所選特徵,並發現哪種結果會產生最佳性能的模型。這稱為網格搜索,其中可以調整SelectKBest類的k參數。
使用重複分層k-fold cross-validation來評估迴歸任務上的模型配置是一種好習慣。我們將通過RepeatedKFold類使用三個重複的10倍交叉驗證。
<code>cv = RepeatedKFold(n_splits=10, n_repeats=3, random_state=1)/<code>
我們可以定義一條通道,以正確準備訓練集上的特徵選擇變換,並將其應用於交叉驗證的每一折的訓練集和測試集。
在這種情況下,我們將使用相關信息統計方法來選擇特徵。
<code># define the pipeline to evaluate model = LinearRegression() fs = SelectKBest(score_func=mutual_info_regression) pipeline = Pipeline(steps=[('sel',fs), ('lr', model)])/<code>
然後,我們可以定義值的網格以評估為80到100。
請注意,網格是要搜索的參數到值的字典映射,並且假設我們使用的是Pipeline,則可以通過給我們提供的名稱“ sel ”和參數名稱“ k ” 來訪問SelectKBest對象。兩個下劃線或“ sel__k ”。
<code># define the grid grid = dict() grid['sel__k'] = [i for i in range(X.shape[1]-20, X.shape[1]+1)]/<code>
然後,我們可以定義並運行搜索。
在這種情況下,我們將使用負平均絕對誤差(neg_mean_absolute_error)評估模型。它是負數,因為scikit-learn需要使分數最大化,因此MAE變為負數,這意味著分數從-infinity到0(最佳)。
<code># define the grid search search = GridSearchCV(pipeline, grid, scoring='neg_mean_absolure_error', n_jobs=-1, cv=cv) # perform the search results = search.fit(X, y)/<code>
下面列出了完整的示例
<code>from sklearn.datasets import make_regression from sklearn.model_selection import RepeatedKFold from sklearn.feature_selection import SelectKBest from sklearn.feature_selection import mutual_info_regression from sklearn.linear_model import LinearRegression from sklearn.pipeline import Pipeline from sklearn.model_selection import GridSearchCV # define dataset X, y = make_regression(n_samples=1000, n_features=100, n_informative=10, noise=0.1, random_state=1) # define the evaluation method cv = RepeatedKFold(n_splits=10, n_repeats=3, random_state=1) # define the pipeline to evaluate model = LinearRegression() fs = SelectKBest(score_func=mutual_info_regression) pipeline = Pipeline(steps=[('sel',fs), ('lr', model)]) # define the grid grid = dict() grid['sel__k'] = [i for i in range(X.shape[1]-20, X.shape[1]+1)] # define the grid search search = GridSearchCV(pipeline, grid, scoring='neg_mean_squared_error', n_jobs=-1, cv=cv) # perform the search results = search.fit(X, y) # summarize best print('Best MAE: %.3f' % results.best_score_) print('Best Config: %s' % results.best_params_) # summarize all means = results.cv_results_['mean_test_score'] params = results.cv_results_['params'] for mean, param in zip(means, params): print(">%.3f with: %r" % (mean, param))/<code>
運行示例選擇不同數量的網格搜索功能使用相關信息統計,其中每個建模評估通道使用重複交叉驗證。
在這種情況下,我們可以看到,選擇的特徵的最佳數量是81,這使得MAE達到大約0.082(忽略符號)。
我們可能希望查看所選特徵的數量與MAE之間的關係。在這種關係中,我們可以預期到更多的特徵會帶來更好的性能。
通過手動評估SelectKBest從81到100 的k的每個配置,收集MAE分數樣本,並使用箱型圖和須狀圖並排繪製結果來探索結果。這些箱形圖的分佈和均值將顯示所選特徵的數量與管道的MAE之間任何有趣的關係。
請注意,由於k = 80的MAE分數的分佈遠大於所考慮的k的所有其他值,因此我們從81而不是80開始了k值的傳播。
下面列出了實現此目的的完整示例。
<code>from numpy import mean from numpy import std from sklearn.datasets import make_regression from sklearn.model_selection import cross_val_score from sklearn.model_selection import RepeatedKFold from sklearn.feature_selection import SelectKBest from sklearn.feature_selection import mutual_info_regression from sklearn.linear_model import LinearRegression from sklearn.pipeline import Pipeline from matplotlib import pyplot # define dataset X, y = make_regression(n_samples=1000, n_features=100, n_informative=10, noise=0.1, random_state=1) # define number of features to evaluate num_features = [i for i in range(X.shape[1]-19, X.shape[1]+1)] # enumerate each number of features results = list() for k in num_features: # create pipeline model = LinearRegression() fs = SelectKBest(score_func=mutual_info_regression, k=k) pipeline = Pipeline(steps=[('sel',fs), ('lr', model)]) # evaluate the model cv = RepeatedKFold(n_splits=10, n_repeats=3, random_state=1) scores = cross_val_score(pipeline, X, y, scoring='neg_mean_absolute_error', cv=cv, n_jobs=-1) results.append(scores) # summarize the results print('>%d %.3f (%.3f)' % (k, mean(scores), std(scores))) # plot model performance for comparison pyplot.boxplot(results, labels=num_features, showmeans=True) pyplot.show()/<code>
運行這個示例,顯示了每個選定特徵數量的平均值和標準差MAE。
在這種情況下,報告MAE的均值和標準差不是很有趣,除了80的k值比90的k值更好。
並排創建了箱形圖和須狀圖,顯示了k與MAE 的趨勢,其中綠色三角形代表平均值,橙色線代表分佈的中值。
總結
在本文中,您發現瞭如何使用數字輸入數據執行特徵選擇以進行迴歸預測建模。
關鍵字: sklearn regression features