专栏 | 基于 Jupyter 的特征工程手册:特征选择(五)
作者:陳穎祥、楊子晗
編譯:AI有道
數(shù)據(jù)預(yù)處理后,我們生成了大量的新變量(比如獨熱編碼生成了大量僅包含0或1的變量)。但實際上,部分新生成的變量可能是多余:一方面它們本身不一定包含有用的信息,故無法提高模型性能;另一方面過這些多余變量在構(gòu)建模型時會消耗大量內(nèi)存和計算能力。因此,我們應(yīng)該進(jìn)行特征選擇并選擇特征子集進(jìn)行建模。
項目地址:
https://github.com/YC-Coder-Chen/feature-engineering-handbook/blob/master/%E4%B8%AD%E6%96%87%E7%89%88.md
本文將介紹特征工程中的 Embedded Methods 嵌入方法。
目錄:
過濾法的特征選擇過程與后續(xù)的機(jī)器學(xué)習(xí)模型無關(guān),因此過濾法可能導(dǎo)致較差的模型性能。
封裝方法利用預(yù)定義的有監(jiān)督的機(jī)器學(xué)習(xí)模型來選擇最佳功能。但是,由于它們需要在大量可能的特征子集上多次訓(xùn)練模型,因此盡管它們通常會導(dǎo)致更好的性能,但它們同時也需要較長的處理時間。
嵌入式方法將特征選擇過程嵌入到機(jī)器學(xué)習(xí)模型中,即利用機(jī)器學(xué)習(xí)來為每一個特征打分。嵌入式方法在創(chuàng)建模型時即完成了對特征子集的選擇。因此,與過濾法相比,它們往往具有更好的性能。與封裝方法相比,它們節(jié)省了大量的處理時間和計算能力。
三種方法的一個簡單對比.
1.3.1?基于正則化模型的方法
許多機(jī)器學(xué)習(xí)模型在其損失函數(shù)中引入了正則項(L1正則或L2正則),以防止過擬合問題。線性模型(例如線性向量支持機(jī),邏輯回歸,線性回歸)中的L1正則項能夠有效地將某些特征的特征系數(shù)縮小為零,從而實現(xiàn)解的稀疏。因此,基于帶正則項線性模型的特征系數(shù),我們可以為特征打分。系數(shù)越高,往往該特征在線性模型中越重要。?
我們可以使用sklearn SelectFromModel函數(shù)刪除特征系數(shù)低或為零的特征。
1.3.1.1?Lasso Regression (Linear Regression with L1 Norm) 套索回歸
import numpy as np from sklearn.feature_selection import SelectFromModel from sklearn.linear_model import Lasso # 我們也可以使用帶L2正則項的嶺回歸# 直接載入數(shù)據(jù)集 from sklearn.datasets import fetch_california_housing dataset = fetch_california_housing() X, y = dataset.data, dataset.target # 利用 california_housing 數(shù)據(jù)集來演示# 選擇前15000個觀測點作為訓(xùn)練集 # 剩下的作為測試集 train_set = X[0:15000,:] test_set = X[15000:,] train_y = y[0:15000]clf = Lasso(normalize=True, alpha = 0.001) # 在進(jìn)行線性回歸前,我們需要先對變量進(jìn)行縮放操作,否則回歸系數(shù)大小無法比較 # alpha控制正則效果的大小,alpha越大,正則效果越強(qiáng)clf.fit(train_set, train_y) # 在訓(xùn)練集上訓(xùn)練 np.round(clf.coef_ ,3) array([ 0.346, 0.003, -0. , -0. , -0. , -0. , -0.033, 0. ])selector = SelectFromModel(clf, prefit=True, threshold=1e-5) # 閾值被設(shè)置為1e-5,因此絕對系數(shù)低于1e-5的特征將被刪除 # 我們還可以設(shè)置max_features參數(shù)以選擇最重要的前幾個特征transformed_train = selector.transform(train_set) # 轉(zhuǎn)換訓(xùn)練集 transformed_test = selector.transform(test_set) #轉(zhuǎn)換測試集assert np.array_equal(transformed_train, train_set[:,[0,1,6]]) # 選擇第一個,第二個及第七個變量 assert np.array_equal(transformed_test, test_set[:,[0,1,6]])1.3.1.2?Logistic Regression (with L1 Norm) 邏輯回歸
import numpy as np from sklearn.feature_selection import SelectFromModel from sklearn.linear_model import LogisticRegression from sklearn.datasets import load_iris # 利用iris數(shù)據(jù)作為演示數(shù)據(jù)集# 載入數(shù)據(jù)集 iris = load_iris() X, y = iris.data, iris.target# iris 數(shù)據(jù)集使用前需要被打亂順序 np.random.seed(1234) idx = np.random.permutation(len(X)) X = X[idx] y = y[idx]# 選擇前100個觀測點作為訓(xùn)練集 # 剩下的50個觀測點作為測試集 train_set = X[0:100,:] test_set = X[100:,] train_y = y[0:100]# 在進(jìn)行邏輯回歸前,我們需要先對變量進(jìn)行縮放操作,否則回歸系數(shù)大小無法比較 from sklearn.preprocessing import StandardScaler model = StandardScaler() model.fit(train_set) standardized_train = model.transform(train_set) standardized_test = model.transform(test_set)clf = LogisticRegression(penalty='l1', C = 0.7, random_state=1234, solver='liblinear') # 我們也可以將正則項設(shè)置為 'l2' # C控制正則效果的大小,C越大,正則效果越弱clf.fit(standardized_train, train_y) np.round(clf.coef_,3) array([[ 0. , 1. , -3.452, -0.159],[ 0. , -1.201, 0.053, 0. ],[ 0. , 0. , 1.331, 3.27 ]])selector = SelectFromModel(clf, prefit=True, threshold=1e-5) # 閾值被設(shè)置為1e-5,因此絕對系數(shù)低于1e-5的特征將被刪除 # 我們還可以設(shè)置max_features參數(shù)以選擇最重要的前幾個特征transformed_train = selector.transform(train_set) # 轉(zhuǎn)換訓(xùn)練集 transformed_test = selector.transform(test_set) #轉(zhuǎn)換測試集assert np.array_equal(transformed_train, train_set[:,[1,2,3]]) # 選擇第2個, 第3個及第4個變量 assert np.array_equal(transformed_test, test_set[:,[1,2,3]])1.3.1.3?LinearSVR/ LinearSVC 線性向量支持機(jī)
# LinearSVC 用于分類問題 # LinearSVR 用于回歸問題 # 這里以LinearSVR為例import numpy as np from sklearn.feature_selection import SelectFromModel from sklearn.svm import LinearSVR# 直接載入數(shù)據(jù)集 from sklearn.datasets import fetch_california_housing dataset = fetch_california_housing() X, y = dataset.data, dataset.target # 利用 california_housing 數(shù)據(jù)集來演示# 選擇前15000個觀測點作為訓(xùn)練集 # 剩下的作為測試集 train_set = X[0:15000,:] test_set = X[15000:,] train_y = y[0:15000]# 在進(jìn)行邏輯回歸前,我們需要先對變量進(jìn)行縮放操作,否則回歸系數(shù)大小無法比較 from sklearn.preprocessing import StandardScaler model = StandardScaler() model.fit(train_set) standardized_train = model.transform(train_set) standardized_test = model.transform(test_set)clf = LinearSVR(C = 0.0001, random_state = 123) # C控制正則效果的大小,C越大,正則效果越弱clf.fit(standardized_train, train_y) np.round(clf.coef_,3) array([ 0.254, 0.026, 0.026, -0.017, 0.032, -0.01 , -0.1 , -0.037])selector = SelectFromModel(clf, prefit=True, threshold=1e-2) # 閾值被設(shè)置為1e-2,因此絕對系數(shù)低于1e-2的特征將被刪除 # 我們還可以設(shè)置max_features參數(shù)以選擇最重要的前幾個特征transformed_train = selector.transform(train_set) # 轉(zhuǎn)換訓(xùn)練集 transformed_test = selector.transform(test_set) #轉(zhuǎn)換測試集assert np.array_equal(transformed_train, train_set[:,[0,1,2,3,4,6,7]]) # 僅第6個變量被刪去 assert np.array_equal(transformed_test, test_set[:,[0,1,2,3,4,6,7]])1.3.2?Tree Based Methods 基于樹模型的方法
機(jī)器學(xué)習(xí)的一大分支便是基于樹的機(jī)器學(xué)習(xí)模型,例如隨機(jī)森林,AdaBoost,Xgboost等。您可以在我的朋友和我撰寫的一系列博客中找到有關(guān)這些基于樹的機(jī)器學(xué)習(xí)模型的更多介紹此處:
https://github.com/YC-Coder-Chen/Tree-Math
這些非參的樹狀模型在建立的過程中記錄了每一個變量如何在樹節(jié)點的分叉中逐步降低模型損失,并可以根據(jù)上述記錄分析每個特征的特征重要性。而我們可以基于這特征重要性刪去一些不重要的變量。
# 我們以隨機(jī)森林為例 import numpy as np from sklearn.feature_selection import SelectFromModel from sklearn.ensemble import RandomForestRegressor# 直接載入數(shù)據(jù)集 from sklearn.datasets import fetch_california_housing dataset = fetch_california_housing() X, y = dataset.data, dataset.target # 利用 california_housing 數(shù)據(jù)集來演示# 選擇前15000個觀測點作為訓(xùn)練集 # 剩下的作為測試集 train_set = X[0:15000,:] test_set = X[15000:,] train_y = y[0:15000]# 在樹類機(jī)器學(xué)習(xí)模型中,我們無需縮放變量操作clf = RandomForestRegressor(n_estimators = 50, random_state = 123)clf.fit(train_set, train_y) np.round(clf.feature_importances_, 3) array([0.52 , 0.045, 0.031, 0.026, 0.027, 0.139, 0.106, 0.107])# 可視化特征重要性 import matplotlib.pyplot as plt plt.rcParams['font.sans-serif']=['SimHei'] %matplotlib inline importances = clf.feature_importances_ indices = np.argsort(importances) plt.figure(figsize=(12,12)) plt.title('特征重要性') plt.barh(range(len(indices)), importances[indices], color='seagreen', align='center') plt.yticks(range(len(indices)),np.array(dataset.feature_names)[indices]) plt.xlabel('特征相對重要性'); selector = SelectFromModel(clf, prefit=True, threshold='median') # 閾值被設(shè)定為'median', 即以特征重要性的中位數(shù)作為閾值,大約為0.076 # 我們還可以設(shè)置max_features參數(shù)以選擇最重要的前幾個特征transformed_train = selector.transform(train_set) transformed_test = selector.transform(test_set) assert np.array_equal(transformed_train, train_set[:,[0,5,6,7]]) # 選擇來第1個,第6個, 第7個及第8個特征 assert np.array_equal(transformed_test, test_set[:,[0,5,6,7]])基于 Jupyter 的特征工程手冊 -?特征選擇系列歷史文章:
專欄 | 基于 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
推薦閱讀
(點擊標(biāo)題可跳轉(zhuǎn)閱讀)
干貨 | 公眾號歷史文章精選
我的深度學(xué)習(xí)入門路線
我的機(jī)器學(xué)習(xí)入門路線圖
算法工程師必備!
AI有道年度技術(shù)文章電子版PDF來啦!
掃描下方二維碼,添加?AI有道小助手微信,可申請入群,并獲得2020完整技術(shù)文章合集PDF(一定要備注:入群?+ 地點 + 學(xué)校/公司。例如:入群+上海+復(fù)旦。?
長按掃碼,申請入群
(添加人數(shù)較多,請耐心等待)
?
最新 AI 干貨,我在看?
總結(jié)
以上是生活随笔為你收集整理的专栏 | 基于 Jupyter 的特征工程手册:特征选择(五)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 专栏 | 基于 Jupyter 的特征工
- 下一篇: 程序员,这600单词你知道吗?