如果我們有一個機器學習任務,比如預測某位客戶是否會還清未來的一筆貸款,我們需要把有關客戶的所有信息都整合到一張表中。這些表通過變數 client_id 和 loan_id 相互關聯,我們可以用一系列轉換和聚合來手動完成這一過程。然而我們很快就會發現,我們可以使用特徵工具來將這個過程自動化。
實體與實體集
首先要介紹特徵工具的兩個概念:實體 (entity) 和實體集 (entityset)。簡單來說,一個實體就是一張表(即 Pandas 中的一個 DataFrame)。一個實體集是指多個表的集合以及它們之間的相互關係。我們可以把實體集看作一種 Python 的數據結構,且有其專屬的方法和屬性。
我們可以在特徵工具中創建一個空的實體集,如下所示:
import featuretools as ft
# Create new entityset
es = ft.EntitySet(id = clients)
現在我們要把多個實體進行合併。每個實體必須帶有一個索引,即所有元素都唯一的數據列。也就是說,索引列中的每個值在表中只能出現一次。
clients 數據框(dataframe)的索引是 client_id,因為每位客戶都只對應表中的一行數據。我們可以通過如下語法把一個帶有索引的實體加入一個實體集:
# Create an entity from the client dataframe
# This dataframe already has an index and a time index
es = es.entity_from_dataframe(entity_id = clients, dataframe = clients,
index = client_id, time_index = joined)
loans 數據框也有唯一索引 loan_id,將其加入實體集的語法和處理 clients 的語法相同。然而,payments 數據框中沒有唯一的索引。若我們想把這個實體加入實體集,則需要讓 make_index = True,並指定一個索引名。雖然特徵工具可以自動推斷實體中每一列的數據類型,但我們也可以通過把數據類型字典傳入參數 variable_types 來將其覆蓋。
# Create an entity from the payments dataframe
# This does not yet have a unique index
es = es.entity_from_dataframe(entity_id = payments,
dataframe = payments,
variable_types = {missed: ft.variable_types.Categorical},
make_index = True,
index = payment_id,
time_index = payment_date)
對於這個數據框,雖然 missed 是整數,但並不是數值變數,因為它只能取兩個離散值,所以我們讓特徵工具將其當作一個類別變數處理。將數據框全部加入實體集後,我們看到:
根據我們指定的修正方案,這些列的類型都被正確識別了。下一步,我們需要指定實體集中各個表之間的關聯。
表之間的關聯
研究兩表之間關係的最好方法是與父子關係進行類比。這是一種一對多的關係:每位父親可能有多個孩子。從表的角度來看,父表中的每一行對應一位父親,但子表可能有多行數據,就像同一位父親的多個孩子。
例如,在我們的數據集中,clients 是 loans 的父表。每位客戶只對應 clients 表中的一行數據,但可能對應 loans 表中的多行數據。同樣,loans 是 payments 的父表,因為每筆貸款可能包含多筆支付。父表通過共有的變數與子表相連接。當執行聚合操作時,我們根據父表的變數對子表進行歸類,並計算每個子表的統計量。
若要標明特徵工具中的關聯,我們只需指定連接兩張表的變數。表 clients 和表 loans 是通過變數 client_id 相關聯的,表 loans 和表 payments 通過 loan_id 相關聯。可通過如下語法創建關聯並將其加入實體集:
# Relationship between clients and previous loans
r_client_previous = ft.Relationship(es[clients][client_id],
es[loans][client_id])
# Add the relationship to the entity set
es = es.add_relationship(r_client_previous)
# Relationship between previous loans and previous payments
r_payments = ft.Relationship(es[loans][loan_id],
es[payments][loan_id])
# Add the relationship to the entity set
es = es.add_relationship(r_payments)
es
該實體集現在包括三個實體以及連接這些實體之間的關係。加入實體並標明關聯後,我們的實體集就完整了,並做好了構造新特徵的準備。
特徵基元
在正式進行深度特徵合成之前,我們需要理解特徵基元這個概念。我們已經知道了特徵基元是什麼,但也只是瞭解用什麼名字來稱呼它們。下面是我們構造新特徵時的基本操作:
聚合:基於父表與子表的關聯(一對多)完成的系列操作,即根據父表對子表進行分組並計算其統計量。例如,根據 client_id 對 loan 表進行分組,並找到每位客戶最大的貸款數額。
轉換:對一張表中一列或多列進行的操作。例如,計算一張表中兩列的差值或計算一列的絕對值。
在特徵工具中,我們可以通過單個基元或者疊加多個基元來構造新特徵。下面是特徵工具中一些特徵基元的列表(我們也可以自定義基元):
特徵基元
這些基元可以拿來單獨使用或者結合起來構造新的特徵。根據特定的基元,我們可以使用 ft.dfs 函數(即深度特徵合成)來構造特徵。我們將所選的 trans_primitives(轉換)和 agg_primitives(聚合)傳入 entityset(實體集)和 target_entity(目標實體),即我們想要添加特徵的表:
# Create new features using specified primitives
features, feature_names = ft.dfs(entityset = es, target_entity = clients,
agg_primitives = [mean, max, percent_true, last],
trans_primitives = [years, month, subtract, divide])
得到的結果是一個含有新特徵的客戶數據框(因為我們把用戶當作了 target_entity)。例如,若我們知道每位用戶加入的月份,這可以作為一個轉換特徵基元:
我們也有許多聚合基元,如每位客戶的平均支付額:
雖然我們只列舉了一部分特徵基元,但實際上特徵工具通過結合與疊加這些基元構造了許多新的特徵。
完整的數據框包含了793個新特徵!
深度特徵合成
現在我們已經做好理解深度特徵合成的全部準備了。實際上,我們在之前執行函數時已經使用過深度特徵合成了!深度特徵是指通過疊加多個基元得到的特徵,深度特徵合成是指構造這些特徵的過程。一個深度特徵的深度是為構造這個特徵所使用的基元數目。
例如,MEAN(payments.payment_amount) 列是一個深度為 1 的深度特徵,因為它在構造過程中只使用了一個聚合基元。LAST(loans(MEAN(payments.payment_amount)) 是一個深度為 2 的特徵,它由兩個聚合基元疊加構成:將 LAST 疊加在了 MEAN 上。這個特徵代表客戶最近一筆支付額的平均值。
我們可以疊加特徵到任何想達到的深度,但事實上,我從來沒有用過深度超過 2 的特徵。關於這一點很難解釋清楚,但我鼓勵感興趣的人嘗試更進一步的探索。
我們無需手動指定特徵基元,特徵工具可以幫助我們自動選擇特徵。為此,我們同樣使用 ft.dfs 函數來調用但無需傳入任何特徵基元:
# Perform deep feature synthesis without specifying primitives
features, feature_names = ft.dfs(entityset=es, target_entity=clients,
max_depth = 2)
features.head()
特徵工具構造了許多供我們使用的新特徵。雖然這一過程可以自動構造新特徵,但它不會取代數據科學家的位置,因為我們還要清楚如何使用這些特徵。例如,如果我們的目標是預測某位客戶是否會償還貸款,那麼我們要找出與指定結果相關度最高的特徵。此外,如果我們有領域知識,則可以利用領域知識來選出特定的特徵基元,或通過深度特徵合成從候選特徵中得到種子特徵。
下一步
自動特徵工程解決了一個問題,但也製造了另一個問題:特徵過多。雖然在擬合模型前我們很難說哪些特徵是重要的,但肯定不是所有特徵都與目標任務相關。而且,特徵過多可能會導致模型性能很差,因為不那麼重要的特徵會影響到那些更重要的特徵。
由特徵過多導致的問題又被公認為「維度的詛咒」。對於模型來說,特徵數量上升了(即數據維度增加了),學習特徵和目標之間的映射規則也會變得更加困難。實際上,使模型有良好表現所需的數據量與特徵數目呈指數關係。
「維度的詛咒」可以通過特徵降維(也被稱為特徵選擇)來減輕:這是一個剔除不相關特徵的過程。我們可以通過多種途徑實現:主成分分析 (PCA)、SelectKBest、使用模型的特徵重要性或使用深度神經網路來自動編碼。和今天要探討的內容相比,特徵降維應該另起一篇文章來單獨討論更合適。到現在為止,我們已經知道如何使用特徵工具,從諸多數據表中輕鬆構造大量的特徵了!
總結
同機器學習中的許多主題一樣,基於特徵工具的自動特徵工程是一個以簡單概念為基礎的複雜方法。基於實體集、實體和關聯等概念,特徵工具可以通過深度特徵合成來構造新的特徵。深度特徵合成將包含了表間一對多關聯的「聚合」特徵基元依次疊加,「轉換」函數被用於單張表中的一列或多列數據,以此來從多張表中構造新的特徵。
在之後的文章中,AI科技大本營也會介紹在實際應用(如 Kaggle 競賽)中如何使用這項技術。模型的好壞取決於我們為它提供的數據,而自動特徵工程有助於使特徵構造過程的效率更高。希望本文介紹的自動特徵工程可以幫到大家。
關於特徵工具的更多信息,包括更高級的應用方法,可以查看在線文檔。
原文鏈接:
https:// towardsdatascience.com/ automated-feature-engineering-in-python-99baf11cc219 GitHub 鏈接:https:// github.com/WillKoehrsen /automated-feature-engineering/blob/master/walk_through/Automated_Feature_Engineering.ipynb 特徵工具在線文檔:https:// docs.featuretools.com/ Feature Labs 官網:https://www. featurelabs.com/
推薦閱讀: