1. 程式人生 > >用Python實現自動特徵工程

用Python實現自動特徵工程

任何參與過機器學習比賽的人,都能深深體會特徵工程在構建機器學習模型中的重要性,它決定了你在比賽排行榜中的位置。

特徵工程具有強大的潛力,但是手動操作是個緩慢且艱鉅的過程。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