天天看點

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

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

項目位址:

https://github.com/YC-Coder-Chen/feature-engineering-handbook

本文将介紹特征工程第一種算法:Filter Methods 過濾法(上)。

目錄:

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

1.1 Filter Methods 過濾法

過濾法通過使用一些統計量或假設檢驗結果為每個變量打分。得分較高的功能往往更加重要,是以應被包含在子集中。以下為一個簡單的基于過濾法的機器學習工作流(以最簡單的訓練-驗證-測試這種資料集劃分方法為例)。

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

1.1.1 Univariate Filter Methods 單變量特征過濾

單變量過濾方法依據單變量統計量或統計檢驗選擇最佳特征。其僅僅考慮單個變量與目标變量的關系(方差選擇法僅基于單個變量)。

1.1.1.1 Variance Threshold 方差選擇法

方差選擇法删除變量方差低于某個門檻值的所有特征。例如,我們應删除方差為零的特征(所有觀測點中具有相同值的特征),因為該特征無法解釋目标變量的任何變化。

import numpy as np
import pandas as pd
from sklearn.feature_selection import VarianceThreshold

# 合成一些資料集用于示範
train_set = np.array([[1,2,3],[1,4,7],[1,4,9]]) # 可見第一個變量方差為0
# array([[1, 2, 3],
#        [1, 4, 7],
#        [1, 4, 9]])

test_set = np.array([[3,2,3],[1,2,7]]) # 故意将第二個變量方差設為0
# array([[3, 2, 3],
#        [1, 2, 7]])

selector = VarianceThreshold()
selector.fit(train_set) # 在訓練集上訓練
transformed_train = selector.transform(train_set) # 轉換訓練集
# 下面為傳回結果,可見第一個變量已被删除
# array([[2, 3],
#        [4, 7],
#        [4, 9]])

transformed_test = selector.transform(test_set) # 轉換測試集
# 下面為傳回結果,可見第一個變量已被删除
# array([[2, 3],
#        [2, 7]])
# 雖然測試集中第二個變量的方差也為0
# 但是我們的選擇是基于訓練集,是以我們依然删除第一個變量      

1.1.1.2 Pearson Correlation (regression problem) 皮爾森相關系數 (回歸問題)

皮爾森相關系數一般用于衡量兩個連續變量之間的線性相關性,也可以用于衡量二進制變量與目标變量的相關性。故可以将類别變量利用獨熱編碼轉換為多個二進制變量之後利用皮爾森相關系數進行篩選。

公式:

專欄 | 基于 Jupyter 的特征工程手冊:特征選擇(一)
import numpy as np
from scipy.stats import pearsonr
from sklearn.feature_selection import SelectKBest

# 直接載入資料集
from sklearn.datasets import fetch_california_housing
dataset = fetch_california_housing()
X, y = dataset.data, dataset.target # 利用 california_housing 資料集來示範
# 此資料集中,X,y均為連續變量,故此滿足使用皮爾森相關系數的條件

# 選擇前15000個觀測點作為訓練集
# 剩下的作為測試集
train_set = X[0:15000,:]
test_set = X[15000:,]
train_y = y[0:15000]

# sklearn 中沒有直接的方程可以使用
# 此處将用 scipy.stats.pearsonr方程來實作基于皮爾森相關系數的特征過濾
# 注意 scipy.stats.pearsonr 計算的是兩個變量之間的相關系數
# 因sklearn SelectKBest需要,我們将基于scipy.stats.pearsonr 重寫允許多特征同時輸入的方程 udf_pearsonr

def udf_pearsonr(X, y):
    # 将會分别計算每一個變量與目标變量的關系
    result = np.array([pearsonr(x, y) for x in X.T]) # 包含(皮爾森相關系數, p值) 的清單
    return np.absolute(result[:,0]), result[:,1]

# SelectKBest 将會基于一個判别方程自動選擇得分高的變量
# 這裡的判别方程為皮爾森相關系數
selector = SelectKBest(udf_pearsonr, k=2) # k => 我們想要選擇的變量數
selector.fit(train_set, train_y) # 在訓練集上訓練
transformed_train = selector.transform(train_set) # 轉換訓練集
transformed_train.shape #(15000, 2), 其選擇了第一個及第七個變量 
assert np.array_equal(transformed_train, train_set[:,[0,6]])

transformed_test = selector.transform(test_set) # 轉換測試集
assert np.array_equal(transformed_test, test_set[:,[0,6]]);
# 可見對于測試集,其依然選擇了第一個及第七個變量      
# 驗算一下我們的結果
for idx in range(train_set.shape[1]):
    pea_score, p_value = pearsonr(train_set[:,idx], train_y)
    print(f"第{idx + 1}個變量和目标的皮爾森相關系數的絕對值為{round(np.abs(pea_score),2)}, p-值為{round(p_value,3)}")
# 應選擇第一個及第七個變量
      

第1個變量和目标的皮爾森相關系數的絕對值為0.7, p-值為0.0

第2個變量和目标的皮爾森相關系數的絕對值為0.07, p-值為0.0

第3個變量和目标的皮爾森相關系數的絕對值為0.14, p-值為0.0

第4個變量和目标的皮爾森相關系數的絕對值為0.04, p-值為0.0

第5個變量和目标的皮爾森相關系數的絕對值為0.02, p-值為0.011

第6個變量和目标的皮爾森相關系數的絕對值為0.05, p-值為0.0

第7個變量和目标的皮爾森相關系數的絕對值為0.23, p-值為0.0

第8個變量和目标的皮爾森相關系數的絕對值為0.08, p-值為0.0

1.1.1.3 Distance Correlation (regression problem) 距離相關系數 (回歸問題)

與皮爾森相關系數類似,距離相關系數也一般被用于衡量兩個連續變量之間的相關性。但與皮爾森相關系數不同的是,距離相關系數還衡量了兩個變量之間的非線性關聯。 

專欄 | 基于 Jupyter 的特征工程手冊:特征選擇(一)
import numpy as np
from dcor import distance_correlation
from dcor.independence import distance_covariance_test
from sklearn.feature_selection import SelectKBest

# 直接載入資料集
from sklearn.datasets import fetch_california_housing
dataset = fetch_california_housing()
X, y = dataset.data, dataset.target # 利用 california_housing 資料集來示範
# 此資料集中,X,y均為連續變量,故此滿足使用距離相關系數的條件

# 選擇前15000個觀測點作為訓練集
# 剩下的作為測試集
train_set = X[0:15000,:]
test_set = X[15000:,]
train_y = y[0:15000]

# sklearn 中沒有直接的方程可以使用
# 此處将用 dcor.distance_correlation方程來實作基于距離相關系數的特征過濾
# 注意 dcor.distance_correlation 計算的是兩個變量之間的相關系數
# 因sklearn SelectKBest需要,我們将基于dcor.distance_correlation 重寫允許多特征同時輸入的方程 udf_dcorr

def udf_dcorr(X, y):
    # 将會分别計算每一個變量與目标變量的關系
    result = np.array([[distance_correlation(x, y), 
                        distance_covariance_test(x,y)[0]]for x in X.T]) # 包含(距離相關系數, p值) 的清單
    return result[:,0], result[:,1]

# SelectKBest 将會基于一個判别方程自動選擇得分高的變量
# 這裡的判别方程為距離相關系數
selector = SelectKBest(udf_dcorr, k=2) # k => 我們想要選擇的變量數
selector.fit(train_set, train_y) # 在訓練集上訓練
transformed_train = selector.transform(train_set) # 轉換訓練集
transformed_train.shape #(15000, 2), 其選擇了第一個及第三個變量 
assert np.array_equal(transformed_train, train_set[:,[0,2]])

transformed_test = selector.transform(test_set) # 轉換測試集
assert np.array_equal(transformed_test, test_set[:,[0,2]]);
# 可見對于測試集,其依然選擇了第一個及第三個變量      
# 驗算一下我們的結果
for idx in range(train_set.shape[1]):
    d_score = distance_correlation(train_set[:,idx], train_y)
    p_value = distance_covariance_test(train_set[:,idx], train_y)[0]
    print(f"第{idx + 1}個變量和目标的距離相關系數為{round(d_score,2)}, p-值為{round(p_value,3)}")
# 應選擇第一個及第三個變量
      

第1個變量和目标的距離相關系數為0.66, p-值為1.0

第2個變量和目标的距離相關系數為0.07, p-值為1.0

第3個變量和目标的距離相關系數為0.31, p-值為1.0

第4個變量和目标的距離相關系數為0.12, p-值為1.0

第5個變量和目标的距離相關系數為0.08, p-值為1.0

第6個變量和目标的距離相關系數為0.29, p-值為1.0

第7個變量和目标的距離相關系數為0.25, p-值為1.0

第8個變量和目标的距離相關系數為0.19, p-值為1.0

1.1.1.4 F-Score (regression problem) F-統計量 (回歸問題)

F統計量(F-Score)用于檢驗線性回歸模型的整體顯著性。在sklearn中,其将對每一個變量分别建立一個一進制的線性回歸模型,然後分别報告每一個對應模型的F統計量。F-統計量的零假設是該線性模型系數不顯著,在一進制模型中,該統計量能夠反映各變量與目标變量之間的線性關系。是以,我們應該選擇具有較高F統計量的特征(更有可能拒絕原假設)。

專欄 | 基于 Jupyter 的特征工程手冊:特征選擇(一)
import numpy as np
from sklearn.feature_selection import f_regression
from sklearn.feature_selection import SelectKBest

# 直接載入資料集
from sklearn.datasets import fetch_california_housing
dataset = fetch_california_housing()
X, y = dataset.data, dataset.target # 利用 california_housing 資料集來示範
# 此資料集中,X,y均為連續變量,故此滿足使用F統計量的條件

# 選擇前15000個觀測點作為訓練集
# 剩下的作為測試集
train_set = X[0:15000,:]
test_set = X[15000:,]
train_y = y[0:15000]

# sklearn 中直接提供了方程用于計算F統計量
# SelectKBest 将會基于一個判别方程自動選擇得分高的變量
# 這裡的判别方程為F統計量
selector = SelectKBest(f_regression, k=2) # k => 我們想要選擇的變量數
selector.fit(train_set, train_y) # 在訓練集上訓練
transformed_train = selector.transform(train_set) # 轉換訓練集
transformed_train.shape #(15000, 2), 其選擇了第一個及第七個變量 
assert np.array_equal(transformed_train, train_set[:,[0,6]])

transformed_test = selector.transform(test_set) # 轉換測試集
assert np.array_equal(transformed_test, test_set[:,[0,6]]);
# 可見對于測試集,其依然選擇了第一個及第七個變量      
# 驗算一下我們的結果
for idx in range(train_set.shape[1]):
    score, p_value = f_regression(train_set[:,idx].reshape(-1,1), train_y)
    print(f"第{idx + 1}個變量的F統計量為{round(score[0],2)}, p-值為{round(p_value[0],3)}")
# 故應選擇第一個及第七個變量
      

第1個變量的F統計量為14111.79, p-值為0.0

第2個變量的F統計量為71.99, p-值為0.0

第3個變量的F統計量為317.04, p-值為0.0

第4個變量的F統計量為23.93, p-值為0.0

第5個變量的F統計量為6.54, p-值為0.011

第6個變量的F統計量為35.93, p-值為0.0

第7個變量的F統計量為846.61, p-值為0.0

第8個變量的F統計量為98.06, p-值為0.0

專欄系列:

專欄 | 基于 Jupyter 的特征工程手冊:資料預處理(一) 專欄 | 基于 Jupyter 的特征工程手冊: 資料預處理(二) 專欄 | 基于 Jupyter 的特征工程手冊:資料預處理(三) 專欄 | 基于 Jupyter 的特征工程手冊:資料預處理(四)

目前該項目完整中文版正在制作中,請持續關注哦~

中文版 Jupyter 位址:

https://github.com/YC-Coder-Chen/feature-engineering-handbook/blob/master/

中文版/2.%20特征選擇.ipynb

繼續閱讀