任何參與過機器學習比賽的人,都能深深體會特征工程在構建機器學習模型中的重要性,它決定了你在比賽排行榜中的位置。
特征工程具有強大的潛力,但是手動操作是個緩慢且艱巨的過程。Prateek Joshi,是一名數據科學家,花了不少時間研究多種特征,並從不同角度分析其可行性。
現在,整個特征工程過程可實現自動化,他將通過這篇文章進行詳細介紹。
下面會使用Python特征工程庫Featuretools來實現這個任務。在討論之前,我們先介紹特征工程的基本組成,再用直觀例子來理解它們,最后把自動特征工程應用到BigMart Sales數據集中驗證實際效果。
本文目錄
1. 特征是什么
2. 特征工程
3. 特征工程必要性
4. 自動特征工程
5. Featuretools簡介
6. Featuretools實現
7. Featuretools可解釋性
1 特征
在機器學習中,特征可以描述為解釋現象發生的一組特點。當這些特點轉換為一些可測量的形式時,它們就稱作特征。
例如,在一個學生列表中,包含每個學生的姓名name、學習小時數study_hours、智商IQ和先前考試的總分數marks。現在給你一個新學生,他的信息只有學習小時數和智商,他的總分數缺失,你需要來估計他可能的分數值。
在這里,你要使用智商值和學習小時數構建預測模型來估計這些缺失值。因此,智商值和學習小時數稱作這個模型的特征。
2 特征工程
特征工程可以簡單定義為從數據集的已有特征創建新特征的過程。
下面是一個樣本數據,包括每個項目的詳細信息,如它們的重量Item_Weight和價格Item_Price。
現在,我們可以使用重量和價格創建新特征,於是創建了一個名為Price_per_Weight的特征,它指的是物品的單位質量價格。這個過程叫做特征工程。
這只是利用已有特征創建新特征的一個簡單示例,而在實際應用中,當特征數量較多時,特征工程可能會變得相當復雜和繁瑣。
下面是另一個例子。在經典的Titanic數據集中,有個特征為乘客姓名,下面是這個數據集中的一些名字:
Montvila, Rev. Juozas
Graham, Miss. Margaret Edith
Johnston, Miss. Catherine Helen “Carrie”
Behr, Mr. Karl Howell
Dooley, Mr. Patrick
實際上,這些姓名可以分解為其他有意義的特征。比如,我們把相似稱號提取並分到單個類別。下面是乘客姓名中各個稱號的對應頻率。
事實上,有些稱號,如’Dona’, ‘Lady’, ‘Countess’, ‘Capt’, ‘Col’, ‘Don’, ‘Dr’, ‘Major’, ‘Rev’, ‘Sir’和’Jonkheer ‘,出現頻率很低,可以划為同一類,作為rare_title類。此外,稱號’Mlle’和’Ms’可以放在’Miss’中,’Mme’可以用’Mrs’替換。
新的稱號特征只有5個唯一值,如下所示:
因此,這就是我們借助特征工程來提取有用信息的過程,甚至能從最初看起來毫無意義的乘客名稱中提取特征。
3 特征工程必要性
一個預測模型的性能很大程度上取決於訓練該模型的數據集的特征質量。
如果能創建新特征來幫助向模型提供有關目標變量的更多信息,那么它的性能將會提升。因此,當數據集中沒有足夠有用特征時,我們必須依靠特征工程。
在Kaggle競賽“自行車共享需求預測(Bike Sharing Demand Prediction)”中,參與者被要求根據歷史模式(包括使用情況,及對應的天氣、時間和其他數據)來預測華盛頓地區的租賃需求。
在一篇獲勝者分享中也提到,智能特征工程有助於提高模型性能。他創建的一些特征如下:
1. Hour Bins:利用決策樹分箱小時級別特征來創建新特征;
2. Hour Bins:類似地,溫度變量的分箱特征;
3. Year Bins:為持續2年的數據創建了8個季度分箱;
4. Day Type:當天類型,分為工作日、周末和假日。
分享全文見:https://www.analyticsvidhya.com/blog/2015/06/solution-kaggle-competition-bike-sharing-demand/
創建這樣特征並非一件容易的事,它需要大量的頭腦風暴和廣泛的數據探索。但是,並非所有人都擅長特征工程,因為無法通過閱讀書籍或觀看教程學到這些東西。這就是特征工程也被稱為藝術的原因。如果你擅長它,那么你在競賽中占據較大優勢。
4 自動特征工程
分析上面的兩張圖片,左圖展示了20世紀初一群人在組裝汽車,右圖展示了如今機器人在做着同樣工作。自動化任何流程都有可能使其更加高效且節約成本。同樣地,特征工程可以並且已經在機器學習中實現自動化。
構建機器學習模型通常是一個艱苦且乏味的過程。它涉及多個步驟,因此如果我們能夠自動執行一定比例的特征工程任務,那么數據科學家或工程師可以專注於模型的其他方面。
我們已經了解自動特征工程十分有用,那你可能會問,該如何把它應用到模型中?別擔心,已經有一個很好的Python工具庫解決了這個問題,那就是Featuretools。
5 Featuretools簡介
Featuretools是一個用於執行自動特征工程的開源庫,旨在快速推進特征生成過程,從而有更多時間專注於機器學習模型構建的其他方面。
在使用Featuretools之前,我們要了解這個庫的三個主要組件:
-
實體Entities
-
深度特征合成Deep Feature Synthesis
-
特征基元Feature primitives
實體可看作是Pandas中數據幀的表征,多個實體的集合稱為實體集Entityset。
深度特征合成(DFS)與深度學習無關。作為一種特征工程方法,它實際上是Featuretools庫的核心。它支持從單個數據幀和多個數據幀中創建新特征。
DFS通過把特征基元應用於實體集中的實體關系來創建特征。這些基元經常被用來手動生成特征,比如,基元“mean”可在聚合級別找到變量均值。
千看不如一練,熟悉Featuretools的最佳方法是多在數據集中嘗試。因此,我們會在下部分使用BigMart Sales數據集來鞏固概念。
6 Featuretools實現
BigMart Sales數據集面臨的挑戰是建立一個預測模型來估算某個商店中每種產品的銷售額。這將有助於BigMart決策者尋找每個產品或商店的特性,這對提高整體銷售額起着關鍵作用。在給定數據集中,包括10個商店中的1559種產品。
下表給出了數據中提供的特征:
數據集下載地址:
https://datahack.analyticsvidhya.com/contest/practice-problem-big-mart-sales-iii/
6.1 安裝
Featuretools適用於Python 2.7、3.5和3.6,可使用pip命令快速安裝Featuretools。
pip install featurePython
6.2 加載外部庫和數據
import featuretools as ft
import numpy as np
import pandas as pd
train = pd.read_csv("Train_UWu5bXk.csv")
test = pd.read_csv("Test_u94Q5KV.csv")
6.3 准備數據
首先,我們把目標Item_Outlet_Sales存儲到sales變量,把test_Item_Identifier和test_Outlet_Identifier存儲到id變量。
# saving identifiers
test_Item_Identifier = test['Item_Identifier'] test_Outlet_Identifier = test['Outlet_Identifier']
sales = train['Item_Outlet_Sales']
train.drop(['Item_Outlet_Sales'], axis=1, inplace=True)
然后,組合訓練集和測試集,這樣省去兩次執行相同步驟的麻煩。
combi = train.append(test, ignore_index=True)
接着,檢查數據集中的缺失值。
combi.isnull().sum()
變量Item_Weight和Outlet_size中有相當多缺失值,用下面方法快速處理:
# imputing missing data
combi['Item_Weight'].fillna(combi['Item_Weight'].mean(),
inplace = True)
combi['Outlet_Size'].fillna("missing", inplace = True)
6.4 數據預處理
這里不會涉及過多預處理操作,因為本文的主要目的是介紹Featuretools。
combi['Item_Fat_Content'].value_counts()
Item_Fat_Content似乎只包含兩個類別,即“低脂”和“常規”,未涉及到“冗余”類別,所以我們把它轉換成二進制變量。
# dictionary to replace the categories
fat_content_dict = {'Low Fat':0, 'Regular':1, 'LF':0, 'reg':1,
'low fat':0}
combi['Item_Fat_Content'] = combi['Item_Fat_Content'].replace(
fat_content_dict, regex=True)
6.5 使用Featuretools執行特征工程
在這節,我們要使用Featuretools來執行自動特征工程。
對於數據集,必須具有唯一標識符特征,但是我們的數據集目前還沒有。因此,我們要為這個組合數據集創建唯一ID。你可能會注意到,數據集中有兩個ID,一個用於item,另一個用於outlet。因此,對這兩者簡單相加會得到一個唯一ID。
combi['id'] = combi['Item_Identifier'] + combi['Outlet_Identifier']
combi.drop(['Item_Identifier'], axis=1, inplace=True)
要注意,由於不再需要,我刪除了特征Item_Identifier。但是,我保留了特征Outlet_Identifier,因為我稍后還要用到它。
接着,我們要創建一個實體集EntitySet。實體集是一種包含多個數據幀及其之間關系的結構。那么,我們創建一個EntitySet並添加數據幀組合。
# creating and entity set 'es'
es = ft.EntitySet(id = 'sales')
# adding a dataframe
es.entity_from_dataframe(entity_id = 'bigmart',
dataframe = combi,
index = 'id')
我們數據中包含兩個級別的信息,即 item級別和 outlet級別。Featuretools能把一個數據集拆分成多個表格。我們根據outlet ID Outlet_Identifier從BigMart表中創建一個新表“outlet”。
es.normalize_entity(base_entity_id='bigmart',
new_entity_id='outlet',
index = 'Outlet_Identifier',
additional_variables =
['Outlet_Establishment_Year', 'Outlet_Size',
'Outlet_Location_Type', 'Outlet_Type'])
下面打印出實體集EntitySet的組成。
print(es)
如上所示,它包含兩個實體,為bigmart和outlet。這兩個表之間也形成了一種關系,用Outlet_Identifier連接。這種關系將在生成新特征中發揮關鍵作用。
現在我們要使用DFS來自動創建新特征。上面提到,DFS使用特征基元和實體集中給出的多個表來創建特征。
feature_matrix, feature_names = ft.dfs(entityset=es,
target_entity = 'bigmart',
max_depth = 2,
verbose = 1,
n_jobs = 3)
target_entity只是創建新特征的實體ID,這種情況下為實體“bigmart”。參數max_depth控制着通過堆疊基元生成的要素復雜性。參數n_jobs通過使用多個內核來輔助並行特征計算。
這就是使用Featuretools的過程,它已經產生了許多新特征。
來看下這些新創建的特征。
feature_matrix.columns
DFS在這么短的時間內創建了29個新特征,而手動操作需要更長時間。如果數據集包含多個相互關聯的表,Featuretools仍然有效。在這種情況下,你不必對表進行標准化,因為多個表已經可用。
下面打印出feature_matrix的前幾行。
feature_matrix.head()
這個數據幀存在一個問題,即未正確排序。我們必須根據combi數據幀中的id變量對其進行排序。
feature_matrix = feature_matrix.reindex(index=combi['id']) feature_matrix = feature_matrix.reset_index()
現在,數據幀feature_matrix已正確排序。
6.6 構建模型
現在該驗證這些生成特征的效果了。我們將使用它們來構建模型並預測Item_Outlet_Sales值。由於最終數據feature_matrix具有多個分類特征,因此我決定使用CatBoost算法。它可以直接使用分類特征,並且本質上是可擴展的。有關CatBoost的更多內容可閱讀這篇文章:
https://www.analyticsvidhya.com/blog/2017/08/catboost-automated-categorical-data/。
from catboost import CatBoostRegressor
CatBoost要求所有分類變量都使用字符串格式。因此,我們首先將數據中的分類變量轉換為字符串:
categorical_features = np.where(feature_matrix.dtypes =='object')[0]
for i in categorical_features:
feature_matrix.iloc[:,i]=feature_matrix.iloc[:,i].astype('str')
接着把feature_matrix分解為訓練集和測試集。
feature_matrix.drop(['id'], axis=1, inplace=True)
train = feature_matrix[:8523]
test = feature_matrix[8523:]
# removing uneccesary variables
train.drop(['Outlet_Identifier'], axis=1, inplace=True) test.drop(['Outlet_Identifier'], axis=1, inplace=True)
# identifying categorical features categorical_features = np.where(train.dtypes == 'object')[0]
然后把訓練數據拆分為訓練和驗證集,並本地驗證模型性能。
from sklearn.model_selection import train_test_split
# splitting train data into training and validation set
xtrain, xvalid, ytrain, yvalid = train_test_split(train, sales,
test_size=0.25,
random_state=11)
最后,訓練模型時,我們使用的評估指標是RMSE(均方根誤差)。
model_cat = CatBoostRegressor(iterations=100, learning_rate=0.3,
depth=6, eval_metric='RMSE',
random_seed=7)
# training model
model_cat.fit(xtrain, ytrain, cat_features=categorical_features,
use_best_model=True)
# validation score
model_cat.score(xvalid, yvalid)
訓練完成后,模型在驗證集上的RMSE值大約為1092.24。
這個模型在公共排行榜上的得分為1155.12。在沒有任何特征工程的情況下,在驗證集和公共排行榜上的得分大約分別為1103和1183。因此,Featuretools創建的特征不只是隨機特征,它們非常有價值和有效果。最重要的是,它在特征工程中節省的時間是令人難以置信的。
7 Featuretools可解釋性
讓數據科學模型具有可解釋性是執行機器學習中一個很重要的方面。Featuretools生成的特征甚至能很容易地解釋給非技術人員,因為它們是基於容易理解的基元構建的。
例如,特征outlet.SUM(bigmart.Item_Weight)和outlet.STD(bigmart.Item_MRP)分別表示items中權重的outlet級總和和items中成本的標准偏差。
這使得那些不是機器學習專家的使用者能夠在他們的專業領域中理解和應用這個方法。
總結
Featuretools庫真正地改變了機器學習的游戲規則。雖然它在工業領域的應用還十分有限,但是它在機器學習競賽中很快地受到大家的歡迎。它能在構建機器學習模型中節省很多時間,且產生的特征很有效果,這也是我想把Featuretools介紹給大家的原因。
歡迎大家在處理數據集時嘗試下這種方法!
原文:
https://medium.com/analytics-vidhya/a-hands-on-guide-to-automated-feature-engineering-in-python-13260eae9270
— 完 —
加入社群
量子位AI社群19群開始招募啦,歡迎對AI感興趣的同學,在量子位公眾號(QbitAI)對話界面回復關鍵字“交流群”,獲取入群方式;
此外,量子位專業細分群(自動駕駛、CV、NLP、機器學習等)正在招募,面向正在從事相關領域的工程師及研究人員。
進專業群請在量子位公眾號(QbitAI)對話界面回復關鍵字“專業群”,獲取入群方式。(專業群審核較嚴,敬請諒解)
誠摯招聘
量子位正在招募編輯/記者,工作地點在北京中關村。期待有才氣、有熱情的同學加入我們!相關細節,請在量子位公眾號(QbitAI)對話界面,回復“招聘”兩個字。