专栏 | 基于 Jupyter 的特征工程手册:特征选择(四)
作者:陳穎祥、楊子晗
編譯:AI有道
數據預處理后,我們生成了大量的新變量(比如獨熱編碼生成了大量僅包含0或1的變量)。但實際上,部分新生成的變量可能是多余:一方面它們本身不一定包含有用的信息,故無法提高模型性能;另一方面過這些多余變量在構建模型時會消耗大量內存和計算能力。因此,我們應該進行特征選擇并選擇特征子集進行建模。
項目地址:
https://github.com/YC-Coder-Chen/feature-engineering-handbook/blob/master/%E4%B8%AD%E6%96%87%E7%89%88.md
本文將介紹特征工程中的 Wrapper Methods 封裝方法。
目錄:
封裝方法將特征選擇問題視作搜索問題,即其目標為從特征子集集合中搜索出一個最佳的子集,而這一子集在模型中表現最佳。在每一步中,其在特征子集上訓練模型,然后對其進行評估,并在下一步繼續調整特征子集,重新訓練評估,直到找到最佳子集或達到最大迭代次數為止。窮盡搜索在封裝方法中為NP-Hard,故人們提出了一些方法來降低封裝方法所需要的迭代次數,以便可以在有限的時間內達到一個較好的效果。
1.2.1?Deterministic Algorithms 確定性算法
在不考慮模型隨機性的情況下,給定相同的數據輸入,確定性算法將始終輸出相同的最優特征子集。
順序向前選擇(SFS),順序向后選擇(SBS)均為確定性算法。順序向前選擇(SFS)方法將從最優單變量模型開始,然后在迭代中,其會在上一步變量子集的基礎上,以窮舉的方法在現有變量子集中增加一個新變量,使得新增一個變量后的變量子集可以獲得最大的模型表現提升。迭代將持續直到所選變量的數量滿足要求為止。
順序向后選擇(SBS)則從適合一個包含所有變量的模型開始,然后在迭代中,其會在上一步變量子集的基礎上,以窮舉的方法在現有變量子集中刪除一個對模型負影響最低的變量,直到所選特征的數量滿足要求為止。
但是順序向前選擇(SFS)方法和順序向后選擇(SBS)均為逐步(step-wise)的方法,都可能會陷入局部最優狀態。
1.2.1.1 Recursive Feature Elimination (SBS) 遞歸式特征消除
在sklearn中,它僅實現遞歸特征消除(SBS)方法。其提供了兩個函數來實現這一方法,一個是RFE,另一個是RFECV。與RFE函數相比,REFCV使用交叉驗證的結果來選擇最優的特征數量,而在RFE中,要選擇的特征數量由用戶預定義。
# RFE函數 演示 import numpy as np from sklearn.feature_selection import RFE# 直接載入數據集 from sklearn.datasets import fetch_california_housing dataset = fetch_california_housing() X, y = dataset.data, dataset.target # 利用 california_housing 數據集來演示# 選擇前15000個觀測點作為訓練集 # 剩下的作為測試集 train_set = X[0:15000,:] test_set = X[15000:,] train_y = y[0:15000]# 選擇用于衡量子集表現的有監督的機器學習模型 from sklearn.ensemble import ExtraTreesRegressor # 使用ExtraTrees 模型作為示范 clf = ExtraTreesRegressor(n_estimators=25) selector = RFE(estimator = clf, n_features_to_select = 4, step = 1) # 與RFECV不同,此處RFE函數需要用戶定義選擇的變量數量,此處設置為選擇4個最好的變量,每一步我們僅刪除一個變量selector = selector.fit(train_set, train_y) # 在訓練集上訓練transformed_train = train_set[:,selector.support_] # 轉換訓練集 assert np.array_equal(transformed_train, train_set[:,[0,5,6,7]]) # 選擇了第一個,第六個,第七個及第八個變量transformed_test = test_set[:,selector.support_] # 轉換訓練集 assert np.array_equal(transformed_test, test_set[:,[0,5,6,7]]) # 選擇了第一個,第六個,第七個及第八個變量 # RFECV 函數 演示 import numpy as np from sklearn.feature_selection import RFECV# 直接載入數據集 from sklearn.datasets import fetch_california_housing dataset = fetch_california_housing() X, y = dataset.data, dataset.target # 利用 california_housing 數據集來演示# 選擇前15000個觀測點作為訓練集 # 剩下的作為測試集 train_set = X[0:15000,:] test_set = X[15000:,] train_y = y[0:15000]# 選擇用于衡量子集表現的有監督的機器學習模型 from sklearn.ensemble import ExtraTreesRegressor # 使用ExtraTrees 模型作為示范 clf = ExtraTreesRegressor(n_estimators=25) selector = RFECV(estimator = clf, step = 1, cv = 5) # 使用5折交叉驗證 # 每一步我們僅刪除一個變量 selector = selector.fit(train_set, train_y)transformed_train = train_set[:,selector.support_] # 轉換訓練集 assert np.array_equal(transformed_train, train_set) # 選擇了所有的變量transformed_test = test_set[:,selector.support_] # 轉換訓練集 assert np.array_equal(transformed_test, test_set) # 選擇了所有的變量1.2.2?Randomized Algorithms 隨機方法
與確定性算法相比,隨機方法在搜索最佳特征子集時引入了一定程度的隨機性。因此,在相同數據輸入的情形下,它可能會輸出不同的最優特征子集結果,但此方法中的隨機性將有助于避免模型陷入局部最優結果。
1.2.2.1?Simulated Annealing (SA) 基于模擬退火特征選擇
模擬退火是一種隨機最優化方法,近年來被引入到特征選擇領域。在每一步中,我們將根據當前的最優特征子集隨機選擇一個特征子集。若新的特征子集效果更好,那么我們將采用它并更新當前最優特征子集。若新特征子集的表現不佳,我們仍會以一定的概率接受它,這個接受概率取決于當前的狀態(溫度)。
以一定的概率接受變現不佳的特征子集對于模擬退火算法至關重要,因為這有助于算法避免陷入局部最優狀態。隨著迭代的進行,模擬退火算法可收斂為良好且穩定的最終結果。
由于未發現能較好實現SA算法的函數,因此我編寫了一個python腳本來實現SA算法,以供您參考。其能夠很好地兼容sklearn中的模型,支持分類及回歸問題。它還提供了內置交叉驗證方法。
公式:
在每一步中,接受表現不佳的特征子集的概率為:
Prob為接受表現不佳的特征子集的概率, ???????????????????? 為新特征子集的損失(loss), ???????????????????? 為新特征子集創建前的最優(最低)損失(loss), ????????????_???????????????????????????????????????????? 為當前的溫度。模擬退火的偽代碼為:
回歸問題演示
import sys sys.path.append("..") from SA import Simulated_Annealing # 導入我們撰寫的模塊# 直接載入數據集 from sklearn.datasets import fetch_california_housing dataset = fetch_california_housing() X, y = dataset.data, dataset.target # 利用 california_housing 數據集來演示# 選擇前15000個觀測點作為訓練集 # 剩下的作為測試集 train_set = X[0:15000,:] test_set = X[15000:,] train_y = y[0:15000]# 選擇用于衡量子集表現的有監督的機器學習模型 from sklearn.ensemble import ExtraTreesRegressor # 使用ExtraTrees 模型作為示范# 選擇模擬退火中評價特征子集的的損失函數 from sklearn.metrics import mean_squared_error # 回歸問題我們使用MSEclf = ExtraTreesRegressor(n_estimators=25) selector = Simulated_Annealing(loss_func = mean_squared_error, estimator = clf, init_temp = 0.2, min_temp = 0.005, iteration = 10, alpha = 0.9) # 在訓練集中訓練 # SA.py中有具體每個參數的含義,此處不贅述selector.fit(X_train = train_set, y_train = train_y, cv = 5) # 使用5折交叉驗證transformed_train = selector.transform(train_set) # 轉換訓練集 transformed_test = selector.transform(test_set) # 轉換測試集 selector.best_sol # 返回最優特征的索引 selector.best_loss; # 返回最優特征子集對應的損失分類問題演示
import sys sys.path.append("..") import numpy as np import random from SA import Simulated_Annealing # 導入我們撰寫的模塊from sklearn.datasets import load_iris # 利用iris數據作為演示數據集# 載入數據集 iris = load_iris() X, y = iris.data, iris.target# iris 數據集使用前需要被打亂順序 np.random.seed(1234) idx = np.random.permutation(len(X)) X = X[idx] y = y[idx]# 選擇前100個觀測點作為訓練集 # 剩下的前20個觀測點作為驗證集,剩下的30個觀測作為測試集 train_set = X[0:100,:] val_set = X[100:120,:] test_set = X[120:,:]train_y = y[0:100] val_y = y[100:120] test_y = y[120:]# 重制隨機種子 # 隨機方法需要隨機性的存在 random.seed() np.random.seed()# 選擇用于衡量子集表現的有監督的機器學習模型 from sklearn.ensemble import ExtraTreesClassifier # we use extratree as predictive model# 選擇模擬退火中評價特征子集的的損失函數 from sklearn.metrics import log_loss # 回歸問題中,我們使用交叉熵損失函數clf = ExtraTreesClassifier(n_estimators=25) selector = Simulated_Annealing(loss_func = log_loss, estimator = clf, init_temp = 0.2, min_temp = 0.005, iteration = 10, alpha = 0.9, predict_type = 'predict_proba') # 在訓練集中訓練 # SA.py中有具體每個參數的含義,此處不贅述selector.fit(X_train = train_set, y_train = train_y, X_val = val_set, y_val = val_y, stop_point = 15) # 此函數允許用戶導入自己定義的驗證集,此處嘗試一下transformed_train = selector.transform(train_set) # 轉換訓練集 transformed_test = selector.transform(test_set) # 轉換測試集 selector.best_sol # 返回最優特征的索引 selector.best_loss; # 返回最優特征子集對應的損失1.2.2.2?Genetic Algorithm (GA) 基于基因算法特征選擇
遺傳算法是一種基于進化生物學概念的最優化搜索算法。它借鑒了自然界中的進化過程,并通過允許個體候選解通過“交叉”和“變異”來進化得到更優的候選解及種群。其還結合了自然界中的競爭理念,即僅允許最合適或最優的幾個候選解“生存”下來并“繁殖”其后代。經過種群及個體候選解的持續迭代,基因算法(GA)會收斂到優化解決方案。?
與模擬退火類似,我也編寫了一個python腳本來實現GA算法,以供您參考。它提供了兩種算法,包括“one-max”和“ NSGA2”。“one-max”為傳統的單目標GA算法,“NSGA2”則為一個多目標GA算法。在特征選擇中,“one-max”的目標是減少模擬在驗證集上的損失,而“NSGA2”的目標一是減少損失,二是同時要最小化特征子集中特征的數量。?
此python腳本能夠很好地兼容sklearn中的模型,支持分類及回歸問題。它還提供了內置交叉驗證方法。?
基因算法的偽代碼如下:
回歸問題演示
import sys sys.path.append("..") from GA import Genetic_Algorithm # 導入我們撰寫的模塊# 直接載入數據集 from sklearn.datasets import fetch_california_housing dataset = fetch_california_housing() X, y = dataset.data, dataset.target # 利用 california_housing 數據集來演示# 選擇前15000個觀測點作為訓練集 # 剩下的作為測試集 train_set = X[0:15000,:] test_set = X[15000:,] train_y = y[0:15000]# 選擇用于衡量子集表現的有監督的機器學習模型 from sklearn.ensemble import ExtraTreesRegressor # 使用ExtraTrees 模型作為示范# 選擇模擬退火中評價特征子集的的損失函數 from sklearn.metrics import mean_squared_error # 回歸問題我們使用MSEclf = ExtraTreesRegressor(n_estimators=25) selector = Genetic_Algorithm(loss_func = mean_squared_error, estimator = clf, n_gen = 10, n_pop = 20, algorithm = 'NSGA2') # 在訓練集中訓練 # GA.py中有具體每個參數的含義,此處不贅述selector.fit(X_train = train_set, y_train = train_y, cv = 5) # 使用5折交叉驗證transformed_train = selector.transform(train_set) # 轉換訓練集 transformed_test = selector.transform(test_set) # 轉換測試集 selector.best_sol # 返回最優特征的索引 selector.best_loss; # 返回最優特征子集對應的損失分類問題演示
import sys sys.path.append("..") import numpy as np import random from GA import Genetic_Algorithm # 導入我們撰寫的模塊from sklearn.datasets import load_iris # 利用iris數據作為演示數據集# 載入數據集 iris = load_iris() X, y = iris.data, iris.target# iris 數據集使用前需要被打亂順序 np.random.seed(1234) idx = np.random.permutation(len(X)) X = X[idx] y = y[idx]# 選擇前100個觀測點作為訓練集 # 剩下的前20個觀測點作為驗證集,剩下的30個觀測作為測試集 train_set = X[0:100,:] val_set = X[100:120,:] test_set = X[120:,:]train_y = y[0:100] val_y = y[100:120] test_y = y[120:]# 重制隨機種子 # 隨機方法需要隨機性的存在 random.seed() np.random.seed()# 選擇用于衡量子集表現的有監督的機器學習模型 from sklearn.ensemble import ExtraTreesClassifier # we use extratree as predictive model# 選擇模擬退火中評價特征子集的的損失函數 from sklearn.metrics import log_loss # 回歸問題中,我們使用交叉熵損失函數clf = ExtraTreesClassifier(n_estimators=25) selector = Genetic_Algorithm(loss_func = log_loss, estimator = clf, n_gen = 15, n_pop = 10, predict_type = 'predict_proba') # 在訓練集中訓練 # GA.py中有具體每個參數的含義,此處不贅述selector.fit(X_train = train_set, y_train = train_y, X_val = val_set, y_val = val_y, stop_point = 15) # 此函數允許用戶導入自己定義的驗證集,此處嘗試一下transformed_train = selector.transform(train_set) # 轉換訓練集 transformed_test = selector.transform(test_set) # 轉換測試集 selector.best_sol # 返回最優特征的索引 selector.best_loss; # 返回最優特征子集對應的損失基于 Jupyter 的特征工程手冊:特征選擇:
專欄 | 基于 Jupyter 的特征工程手冊:特征選擇(一)
專欄 | 基于 Jupyter 的特征工程手冊:特征選擇(二)
專欄 | 基于 Jupyter 的特征工程手冊:特征選擇(三)
中文版 Jupyter 地址:
https://github.com/YC-Coder-Chen/feature-engineering-handbook/tree/master/%E4%B8%AD%E6%96%87%E7%89%88
推薦閱讀
(點擊標題可跳轉閱讀)
干貨 | 公眾號歷史文章精選
我的深度學習入門路線
我的機器學習入門路線圖
算法工程師必備!
AI有道年度技術文章電子版PDF來啦!
掃描下方二維碼,添加?AI有道小助手微信,可申請入群,并獲得2020完整技術文章合集PDF(一定要備注:入群?+ 地點 + 學校/公司。例如:入群+上海+復旦。?
長按掃碼,申請入群
(添加人數較多,請耐心等待)
?
最新 AI 干貨,我在看?
總結
以上是生活随笔為你收集整理的专栏 | 基于 Jupyter 的特征工程手册:特征选择(四)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: VC+ADO+Access2000数据库
- 下一篇: 专栏 | 基于 Jupyter 的特征工