天天看點

專欄 | 基于 Jupyter 的特征工程手冊:特征選擇(五)

資料預處理後,我們生成了大量的新變量(比如獨熱編碼生成了大量僅包含0或1的變量)。但實際上,部分新生成的變量可能是多餘:一方面它們本身不一定包含有用的資訊,故無法提高模型性能;另一方面過這些多餘變量在構模組化型時會消耗大量記憶體和計算能力。是以,我們應該進行特征選擇并選擇特征子集進行模組化。

項目位址:

https://github.com/YC-Coder-Chen/feature-engineering-handbook/blob/master/%E4%B8%AD%E6%96%87%E7%89%88.md

本文将介紹特征工程中的 Embedded Methods 嵌入方法。

目錄:

專欄 | 基于 Jupyter 的特征工程手冊:特征選擇(五)

過濾法的特征選擇過程與後續的機器學習模型無關,是以過濾法可能導緻較差的模型性能。

封裝方法利用預定義的有監督的機器學習模型來選擇最佳功能。但是,由于它們需要在大量可能的特征子集上多次訓練模型,是以盡管它們通常會導緻更好的性能,但它們同時也需要較長的處理時間。

嵌入式方法将特征選擇過程嵌入到機器學習模型中,即利用機器學習來為每一個特征打分。嵌入式方法在建立模型時即完成了對特征子集的選擇。是以,與過濾法相比,它們往往具有更好的性能。與封裝方法相比,它們節省了大量的處理時間和計算能力。

三種方法的一個簡單對比.

專欄 | 基于 Jupyter 的特征工程手冊:特征選擇(五)

1.3.1 基于正則化模型的方法

許多機器學習模型在其損失函數中引入了正則項(L1正則或L2正則),以防止過拟合問題。線性模型(例如線性向量支援機,邏輯回歸,線性回歸)中的L1正則項能夠有效地将某些特征的特征系數縮小為零,進而實作解的稀疏。是以,基于帶正則項線性模型的特征系數,我們可以為特征打分。系數越高,往往該特征線上性模型中越重要。 

我們可以使用sklearn SelectFromModel函數删除特征系數低或為零的特征。

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正則項的嶺回歸

# 直接載入資料集
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]

clf = Lasso(normalize=True, alpha = 0.001)  
# 在進行線性回歸前,我們需要先對變量進行縮放操作,否則回歸系數大小無法比較
# alpha控制正則效果的大小,alpha越大,正則效果越強

clf.fit(train_set, train_y) # 在訓練集上訓練
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)
# 門檻值被設定為1e-5,是以絕對系數低于1e-5的特征将被删除
# 我們還可以設定max_features參數以選擇最重要的前幾個特征

transformed_train = selector.transform(train_set) # 轉換訓練集
transformed_test = selector.transform(test_set) #轉換測試集

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資料作為示範資料集

# 載入資料集
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個觀測點作為訓練集
# 剩下的50個觀測點作為測試集
train_set = X[0:100,:]
test_set = X[100:,]
train_y = y[0:100]

# 在進行邏輯回歸前,我們需要先對變量進行縮放操作,否則回歸系數大小無法比較
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') 
# 我們也可以将正則項設定為 '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)
# 門檻值被設定為1e-5,是以絕對系數低于1e-5的特征将被删除
# 我們還可以設定max_features參數以選擇最重要的前幾個特征

transformed_train = selector.transform(train_set) # 轉換訓練集
transformed_test = selector.transform(test_set) #轉換測試集

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 線性向量支援機

# LinearSVC 用于分類問題
# LinearSVR 用于回歸問題
# 這裡以LinearSVR為例

import numpy as np
from sklearn.feature_selection import SelectFromModel
from sklearn.svm import LinearSVR

# 直接載入資料集
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.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)
# 門檻值被設定為1e-2,是以絕對系數低于1e-2的特征将被删除
# 我們還可以設定max_features參數以選擇最重要的前幾個特征

transformed_train = selector.transform(train_set) # 轉換訓練集
transformed_test = selector.transform(test_set) #轉換測試集

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 基于樹模型的方法

機器學習的一大分支便是基于樹的機器學習模型,例如随機森林,AdaBoost,Xgboost等。您可以在我的朋友和我撰寫的一系列部落格中找到有關這些基于樹的機器學習模型的更多介紹此處:

https://github.com/YC-Coder-Chen/Tree-Math

這些非參的樹狀模型在建立的過程中記錄了每一個變量如何在樹節點的分叉中逐漸降低模型損失,并可以根據上述記錄分析每個特征的特征重要性。而我們可以基于這特征重要性删去一些不重要的變量。

# 我們以随機森林為例
import numpy as np
from sklearn.feature_selection import SelectFromModel
from sklearn.ensemble import RandomForestRegressor

# 直接載入資料集
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]

# 在樹類機器學習模型中,我們無需縮放變量操作

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('特征相對重要性');      
專欄 | 基于 Jupyter 的特征工程手冊:特征選擇(五)
selector = SelectFromModel(clf, prefit=True, threshold='median')
# 門檻值被設定為'median', 即以特征重要性的中位數作為門檻值,大約為0.076
# 我們還可以設定max_features參數以選擇最重要的前幾個特征

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
上一篇: linux安裝go
下一篇: Java 方法

繼續閱讀