专栏 | 基于 Jupyter 的特征工程手册:数据预处理(二)
作者:陳穎祥、楊子晗
編譯:AI有道
基于 Jupyter 的特征工程手冊:數據預處理的上一篇:
專欄 | 基于 Jupyter 的特征工程手冊:數據預處理(一)
項目地址:
https://github.com/YC-Coder-Chen/feature-engineering-handbook
本項目將探討數據預處理部分:介紹了如何利用 scikit-learn 處理靜態的連續變量,利用 Category Encoders 處理靜態的類別變量以及利用 Featuretools 處理常見的時間序列變量。
目錄
特征工程的數據預處理我們將分為三大部分來介紹:
靜態連續變量
靜態類別變量
時間序列變量
本文將介紹 1.2 靜態類別變量的數據預處理(上部分,即1.2.1-1.2.6)。下面將結合 Jupyter,使用 sklearn,進行詳解。
1.2?Static Categorical Variables 靜態類別變量
真實世界的數據集還往往包含類別特征。但是由于scikit-learn中的模型只能處理數值特征,因此我們需要將類別特征編碼為數值特征但是,很多新的模型開始直接提供類別變量支持,例如lightGBM和Catboost。這里我們使用category_encoders包,因為它涵蓋了更多的編碼方法。
1.2.1?Ordinal Encoding 序數編碼
序數編碼將類別變量轉化為一列序數變量,包含從1到類別數量之間的整數
import numpy as np import pandas as pd from category_encoders import OrdinalEncoder # category_encoders 直接支持dataframe# 隨機生成一些訓練集 train_set = pd.DataFrame(np.array([['male',10],['female', 20], ['male',10], ['female',20],['female',15]]),columns = ['Sex','Type']) train_y = np.array([False, True, True, False, False])# 隨機生成一些測試集, 并有意讓其包含未在訓練集出現過的類別與缺失值 test_set = pd.DataFrame(np.array([['female',20],['male', 20], ['others',15], ['male',20],['female',40], ['male', 25]]),columns = ['Sex','Type']) test_set.loc[4,'Type'] = np.nan train_set # 原始訓練集 test_set # 原始測試集 encoder = OrdinalEncoder(cols = ['Sex', 'Type'], handle_unknown = 'value', handle_missing = 'value').fit(train_set,train_y) # 在訓練集上訓練 # 將 handle_unknown設為‘value’,即測試集中的未知特征值將被標記為-1 # 將 handle_missing設為‘value’,即測試集中的缺失值將被標記為-2 # 其他的選擇為:‘error’:即報錯;‘return_nan’:即未知值/缺失之被標記為nan encoded_train = encoder.transform(train_set) # 轉換訓練集 encoded_test = encoder.transform(test_set) # 轉換測試集# 以測試集結果為例 encoded_test# 在序數編碼中:# 變量Sex中: 'male' => 1.0, 'female' => 2.0, 未知 => -1.0, 缺失值 => -2.0 # (事實上,測試集中完全有可能出現未知與缺失情況) # 在我們的例子中, Sex這一變量中的'other' 類別從未在訓練集中出現過# 變量 Type 中: 10 => 1.0, 20 => 2.0, 15 => 3.0, 未知 => -1.0, 缺失值 => -2.0 encoded_train.astype(float) # 訓練集結果1.2.2?One-hot Encoding 獨熱編碼
Scikit-learn中也提供來獨熱編碼函數,其可以將具有n_categories個可能值的一個分類特征轉換為n_categories個二進制特征,其中一個為1,所有其他為0在category_encoders中,它包含了附加功能,即指示缺失或未知的值。在這里,我們繼續使用category_encoders
import numpy as np import pandas as pd from category_encoders import OneHotEncoder # category_encoders 直接支持dataframe# 隨機生成一些訓練集 train_set = pd.DataFrame(np.array([['male',10],['female', 20], ['male',10], ['female',20],['female',15]]),columns = ['Sex','Type']) train_y = np.array([False, True, True, False, False])# 隨機生成一些測試集, 并有意讓其包含未在訓練集出現過的類別與缺失值 test_set = pd.DataFrame(np.array([['female',20],['male', 20], ['others',15], ['male',20],['female',40], ['male', 25]]),columns = ['Sex','Type']) test_set.loc[4,'Type'] = np.nan train_set # 原始訓練集 test_set # 原始測試集 encoder = OneHotEncoder(cols=['Sex', 'Type'], handle_unknown='indicator', handle_missing='indicator', use_cat_names=True).fit(train_set,train_y) # 在訓練集上訓練 encoded_train = encoder.transform(train_set) # 轉換訓練集 encoded_test = encoder.transform(test_set) # 轉換測試集 # 將 handle_unknown設為‘indicator’,即會新增一列指示未知特征值 # 將 handle_missing設為‘indicator’,即會新增一列指示缺失值 # 其他的handle_unknown/handle_missing 的選擇為: # ‘error’:即報錯; ‘return_nan’:即未知值/缺失之被標記為nan; ‘value’:即未知值/缺失之被標記為0# 以測試集結果為例 encoded_test# 在獨熱編碼中:# 變量 Sex => 變為了4個新變量: 'male' => [1 ,0 ,0, 0]; # 'female' => [0 ,1 ,0, 0]; # 未知 => [0 ,0 ,0, 1]; # 缺失 => [0, 0, 1, 0];# 變量 Type => 變為了5個新變量: 10 => [1, 0, 0, 0, 0]; # 20 => [0, 1, 0, 0, 0];, # 15 => [0, 0, 1, 0, 0]; # 未知 => [0, 0, 0, 0, 1]; # 缺失 => [0, 0, 0, 1, 0];1.2.3?Hashing Encoding 哈希編碼
哈希編碼基于特征哈希的方法。它將哈希函數應用于變量,將任意數量的變量以一定的規則映射到給定數量的變量。特征哈希可能會導致要素之間發生沖突。但哈希編碼的優點是它不需要制定和維護原變量與新變量之間的映射關系。因此,哈希編碼器的大小及復雜程度不隨數據類別的增多而增多。
import numpy as np import pandas as pd from category_encoders.hashing import HashingEncoder # category_encoders 直接支持dataframe# 隨機生成一些訓練集 train_set = pd.DataFrame(np.array([['male',10],['female', 20], ['male',10], ['female',20],['female',15]]),columns = ['Sex','Type']) train_y = np.array([False, True, True, False, False])# 隨機生成一些測試集, 并有意讓其包含未在訓練集出現過的類別與缺失值 test_set = pd.DataFrame(np.array([['female',20],['male', 20], ['others',15], ['male',20],['female',40], ['male', 25]]),columns = ['Sex','Type']) test_set.loc[4,'Type'] = np.nan train_set # 原始訓練集 test_set # 原始測試集 encoder = HashingEncoder(cols=['Sex', 'Type'], n_components = 5).fit(train_set,train_y) encoded_train = encoder.transform(train_set) # 轉換訓練集 encoded_test = encoder.transform(test_set) # 轉換測試集# 將兩列的數據集哈希編碼為5列 # 哈希編碼結果與訓練集/測試集中的內容無關 # 只要列名匹配,我們就可以在任何新數據集上使用哈希編碼方法 # 編碼結果僅由哈希函數確定# 通常哈希編碼應用于更高和更稀疏的維空間,這里以兩個變量作為哈希編碼的例子 # 以測試集結果為例 encoded_test encoded_train # 訓練集結果1.2.4?Helmert Encoding Helmert 編碼
Helmert編碼通常在計量經濟學中使用。在Helmert編碼(分類特征中的每個值對應于Helmert矩陣中的一行)之后,線性模型中編碼后的變量系數可以反映在給定該類別變量某一類別值的情形下因變量的平均值與給定該類別其他類別值的情形下因變量的平均值的差值。在category_encoders包中實現的Helmert編碼為反向Helmert編碼。更多信息:
https://www.statsmodels.org/devel/contrasts.html
import numpy as np import pandas as pd from category_encoders import HelmertEncoder # category_encoders 直接支持dataframe# 隨機生成一些訓練集 train_set = pd.DataFrame(np.array([['male',10],['female', 20], ['male',10], ['female',20],['female',15]]),columns = ['Sex','Type']) train_y = np.array([False, True, True, False, False])# 隨機生成一些測試集, 并有意讓其包含未在訓練集出現過的類別與缺失值 test_set = pd.DataFrame(np.array([['female',20],['male', 20], ['others',15], ['male',20],['female',40], ['male', 25]]),columns = ['Sex','Type']) test_set.loc[4,'Type'] = np.nan train_set # 原始訓練集 test_set # 原始測試集 encoder = HelmertEncoder(cols=['Sex', 'Type'], handle_unknown='indicator', handle_missing='indicator').fit(train_set,train_y) # 在訓練集上訓練 encoded_train = encoder.transform(train_set) # 轉換訓練集 encoded_test = encoder.transform(test_set) # 轉換測試集 # 將 handle_unknown設為‘indicator’,即會新增一列指示未知特征值 # 將 handle_missing設為‘indicator’,即會新增一列指示缺失值 # 其他的handle_unknown/handle_missing 的選擇為: # ‘error’:即報錯; ‘return_nan’:即未知值/缺失之被標記為nan; ‘value’:即未知值/缺失之被標記為0# 以測試集結果為例 encoded_test# 在Helmert編碼中:# 變量 Sex => 變為了4個新變量(包含常數項): 'male' => [ 1. -1. -1. -1.]; # 'female' => [ 1. 1. -1. -1.]; # 未知 => [ 1. 0. 0. 3.]; # 缺失 => [ 1. 0. 2. -1.];# 變量 Type => 變為了5個新變量(包含常數項): 10 => [ 1. -1. -1. -1. -1.]; # 20 => [ 1. 1. -1. -1. -1.];, # 15 => [ 1. 0. 2. -1. -1.]; # 未知 => [ 1. 0. 0. 0. 4.]; # 缺失 => [ 1. 0. 0. 3. -1.]; # 可以通過如下代碼計算變量Type的Helmert 矩陣from patsy.contrasts import Helmert levels = [1,2,3,4,5] # 3個變量值 + 1個未知值 + 1個缺失值 contrast = Helmert().code_with_intercept(levels) print(contrast.matrix) # 第一列為常數項 [[ 1. -1. -1. -1. -1.][ 1. 1. -1. -1. -1.][ 1. 0. 2. -1. -1.][ 1. 0. 0. 3. -1.][ 1. 0. 0. 0. 4.]]encoded_train # 訓練集結果1.2.5?Sum (Deviation) Encoding 偏差編碼
偏差編碼也通常在計量經濟學中被使用。偏差編碼后,線性模型的系數可以反映該給定該類別變量值的情況下因變量的平均值與全局因變量的平均值的差異。更多信息:
https://www.statsmodels.org/devel/contrasts.html
import numpy as np import pandas as pd from category_encoders.sum_coding import SumEncoder # category_encoders 直接支持dataframe# 隨機生成一些訓練集 train_set = pd.DataFrame(np.array([['male',10],['female', 20], ['male',10], ['female',20],['female',15]]),columns = ['Sex','Type']) train_y = np.array([False, True, True, False, False])# 隨機生成一些測試集, 并有意讓其包含未在訓練集出現過的類別與缺失值 test_set = pd.DataFrame(np.array([['female',20],['male', 20], ['others',15], ['male',20],['female',40], ['male', 25]]),columns = ['Sex','Type']) test_set.loc[4,'Type'] = np.nan train_set # 原始訓練集 test_set # 原始測試集 encoder = SumEncoder(cols=['Sex', 'Type'], handle_unknown='indicator', handle_missing='indicator').fit(train_set,train_y) # 在訓練集上訓練 encoded_train = encoder.transform(train_set) # 轉換訓練集 encoded_test = encoder.transform(test_set) # 轉換測試集 # 將 handle_unknown設為‘indicator’,即會新增一列指示未知特征值 # 將 handle_missing設為‘indicator’,即會新增一列指示缺失值 # 其他的handle_unknown/handle_missing 的選擇為: # ‘error’:即報錯; ‘return_nan’:即未知值/缺失之被標記為nan; ‘value’:即未知值/缺失之被標記為0# 以測試集結果為例 encoded_test# 在Helmert編碼中:# 變量 Sex => 變為了4個新變量(包含常數項): 'male' => [ 1. 1. 0. 0.]; # 'female' => [ 1. 0. 1. 0.]; # 未知 => [ 1. -1. -1. -1.]; # 缺失 => [ 1. 0. 0. 1.];# 變量 Type => 變為了5個新變量(包含常數項): 10 => [ 1. 1. 0. 0. 0.]; # 20 => [ 1. 0. 1. 0. 0.];, # 15 => [ 1. 0. 0. 1. 0.]; # 未知 => [ 1. -1. -1. -1. -1.]; # 缺失 => [ 1. 0. 0. 0. 1.]; # 可以通過如下代碼計算變量Type的Deviation 矩陣from patsy.contrasts import Sum levels = [1,2,3,4,5] # 3個變量值 + 1個未知值 + 1個缺失值 contrast = Sum().code_with_intercept(levels) print(contrast.matrix) # 第一列為常數項 [[ 1. 1. 0. 0. 0.][ 1. 0. 1. 0. 0.][ 1. 0. 0. 1. 0.][ 1. 0. 0. 0. 1.][ 1. -1. -1. -1. -1.]]encoded_train # 訓練集結果1.2.6?Target Encoding 目標編碼
目標編碼是一種不僅基于特征值本身,還基于相應因變量的類別變量編碼方法。對于分類問題:將類別特征替換為給定某一特定類別值的因變量后驗概率與所有訓練數據上因變量的先驗概率的組合。對于連續目標:將類別特征替換為給定某一特定類別值的因變量目標期望值與所有訓練數據上因變量的目標期望值的組合。該方法嚴重依賴于因變量的分布,但這大大減少了生成編碼后特征的數量。
公式:
????其中min_samples_leaf和smoothing是用戶定義的參數;
min_samples_leaf:計算類別平均值時的最小樣本數(即若該類別出現次數少,則將被忽略),用以控制過擬合;
smoothing:平衡分類平均值與先驗平均值的平滑系數。其值越高,則正則化越強;
????′????是類別特征X中類別為k的編碼值;
Prior Prob:目標變量的先驗概率/期望;
n:類別特征X中,類別為k的樣本數;
????+:不僅在類別特征X中具有類別k,而且具有正結果的樣本數(分類問題);????
參考文獻: Micci-Barreca, D. (2001). A preprocessing scheme for high-cardinality categorical attributes in classification and prediction problems. ACM SIGKDD Explorations Newsletter, 3(1), 27-32.
import numpy as np import pandas as pd from category_encoders.target_encoder import TargetEncoder # category_encoders 直接支持dataframe# 隨機生成一些訓練集 train_set = pd.DataFrame(np.array([['male',10],['female', 20], ['male',10], ['female',20],['female',15]]),columns = ['Sex','Type']) train_y = np.array([False, True, True, False, False])# 隨機生成一些測試集, 并有意讓其包含未在訓練集出現過的類別與缺失值 test_set = pd.DataFrame(np.array([['female',20],['male', 20], ['others',15], ['male',20],['female',40], ['male', 25]]),columns = ['Sex','Type']) test_set.loc[4,'Type'] = np.nan train_set # 原始訓練集 test_set # 原始測試集 encoder = TargetEncoder(cols=['Sex','Type'], handle_unknown='value', handle_missing='value').fit(train_set,train_y) # 在訓練集上訓練 encoded_train = encoder.transform(train_set) # 轉換訓練集 encoded_test = encoder.transform(test_set) # 轉換測試集# handle_unknown 和 handle_missing 被設定為 'value' # 在目標編碼中,handle_unknown 和 handle_missing 僅接受 ‘error’, ‘return_nan’ 及 ‘value’ 設定 # 兩者的默認值均為 ‘value’, 即對未知類別或缺失值填充訓練集的因變量平均值encoded_test # 編碼后的變量數與原類別變量數一致 # 驗證一下計算的結果,在測試集中,‘male’類別的編碼值為 0.473106 prior = train_y.mean() # 先驗概率 min_samples_leaf = 1.0 # 默認為1.0 smoothing = 1.0 # 默認為1.0 n = 2 # 訓練集中,兩個樣本包含‘male’這個標簽 n_positive = 1 # 在訓練集中,這兩個包含‘male’標簽的樣本中僅有一個有正的因變量標簽???????????????????????? = 1 / (1 + np.exp(-(n - min_samples_leaf) / smoothing)) male_encode = prior * (1-????????????????????????) + ???????????????????????? * n_positive/n male_encode # return 0.4731058578630005,與要驗證的值吻合 0.4731058578630005encoded_train # 訓練集結果好了,以上就是關于靜態類別變量(上部分)的數據預處理介紹。建議讀者結合代碼,在 Jupyter 中實操一遍。
目前該項目完整中文版正在制作中,請持續關注哦~
中文版 Jupyter 地址:
http://localhost:8888/notebooks/feature-engineering-handbook-master/%E4%B8%AD%E6%96%87%E7%89%88/1.%20%E6%95%B0%E6%8D%AE%E9%A2%84%E5%A4%84%E7%90%86.ipynb#Ordinal-Encoding-%E5%BA%8F%E6%95%B0%E7%BC%96%E7%A0%81
推薦閱讀
(點擊標題可跳轉閱讀)
干貨 | 公眾號歷史文章精選
我的深度學習入門路線
我的機器學習入門路線圖
重磅!
林軒田機器學習完整視頻和博主筆記來啦!
掃描下方二維碼,添加?AI有道小助手微信,可申請入群,并獲得林軒田機器學習完整視頻 + 博主紅色石頭的精煉筆記(一定要備注:入群?+ 地點 + 學校/公司。例如:入群+上海+復旦。?
長按掃碼,申請入群
(添加人數較多,請耐心等待)
?
最新 AI 干貨,我在看?
總結
以上是生活随笔為你收集整理的专栏 | 基于 Jupyter 的特征工程手册:数据预处理(二)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 谷歌放弃C++语言,Python将要一统
- 下一篇: 专栏 | 基于 Jupyter 的特征工