Feature Tools:可自动构造机器学习特征的Python库
選自Towards data science,作者:William Koehrsen,機器之心編譯。
目前,很多機器學習項目的模型選擇開始轉向自動化,而特征工程仍然主要以人工為主。這個過程的重要性可能比模型選擇更重要,人工得到的特征總帶有一定的局限性。在本文中作者將為我們介紹如何使用 Feature Tools Python 庫實現(xiàn)特征工程自動化,項目已開源。- 項目地址:https://docs.featuretools.com/
- 代碼地址:https://github.com/WillKoehrsen/automated-feature-engineering/blob/master/walk_through/Automated_Feature_Engineering.ipynb
機器學習越來越多地從人工設計模型轉向使用 H20、TPOT 和 auto-sklearn 等工具自動優(yōu)化的工具。這些庫以及隨機搜索(參見《Random Search for Hyper-Parameter Optimization》)等方法旨在通過尋找匹配數(shù)據(jù)集的最優(yōu)模型來簡化模型選擇和機器學習調優(yōu)過程,而幾乎不需要任何人工干預。然而,特征工程作為機器學習流程中可能最有價值的一個方面,幾乎完全是人工的。
特征工程也被稱為特征構造,是從現(xiàn)有數(shù)據(jù)中構造新的特征從而訓練機器學習模型的過程。這一步可能比實際上使用的模型更重要,因為一個機器學習算法只能從我們給定的數(shù)據(jù)中學習,所以構造一個和任務相關的特征是至關重要的,參見優(yōu)質論文《A Few Useful Things to Know about Machine Learning》。
通常,特征工程是一個冗長的人工過程,依賴于領域知識、直覺和數(shù)據(jù)操作。這個過程可能是極其枯燥的,同時最終得到的特征將會受到人的主觀性和時間的限制。特征工程自動化旨在通過從數(shù)據(jù)集中自動構造候選特征,并從中選擇最優(yōu)特征用于訓練來幫助數(shù)據(jù)科學家。
在本文中,我們將介紹一個使用 Feature Tools Python 庫實現(xiàn)特征工程自動化的例子。我們將使用一個示例數(shù)據(jù)集來說明基本概念(繼續(xù)關注之后使用真實世界數(shù)據(jù)的例子)。本文完整代碼可在 Github 上找到。
特征工程基本概念
特征工程意味著從現(xiàn)有的數(shù)據(jù)中構造額外特征,這些特征通常分布在多張相關的表中。特征工程需要從數(shù)據(jù)中提取相關信息并將其存入單張表格中,然后被用來訓練機器學習模型。
構造特征是一個非常耗時的過程,因為每個新的特征通常需要幾步才能構造,特別是當使用多張表的信息時。我們可以將特征構造的操作分為兩類:「轉換」和「聚合」。以下通過幾個例子來看看這些概念的實際應用。
通過從一或多列中構造新的特征,「轉換」作用于單張表(在 Python 中,表是一個 Pandas DataFrame)。舉個例子,若有如下的客戶表:
我們可以通過查找 joined 列中的月份或是自然對數(shù)化 income 列的數(shù)據(jù)來構造新的特征。這些都是轉換操作,因為它們只用到了一張表的信息。
另一方面,「聚合」是跨表實現(xiàn)的,并使用一對多的關聯(lián)來對觀測值分組,然后計算統(tǒng)計量。例如,若我們有另外一張包含客戶貸款信息的表格,其中每個客戶可能有多項貸款,我們便可以計算每個客戶貸款的平均值、最大值和最小值等統(tǒng)計量。
這個過程包括根據(jù)不同客戶對貸款表進行分組并計算聚合后的統(tǒng)計量,然后將結果整合到客戶數(shù)據(jù)中。以下是我們在 Python 中使用 Pandas 庫執(zhí)行此操作。
import pandas as pd# Group loans by client id and calculate mean, max, min of loans stats = loans.groupby('client_id')['loan_amount'].agg(['mean', 'max', 'min']) stats.columns = ['mean_loan_amount', 'max_loan_amount', 'min_loan_amount']# Merge with the clients dataframe stats = clients.merge(stats, left_on = 'client_id', right_index=True, how = 'left')stats.head(10)這些操作本身并不困難,但是如果有數(shù)百個變量分布在數(shù)十張表中,這個過程將無法通過人工完成。理想情況下,我們希望有一個解決方案能夠在不同表間自動執(zhí)行轉換和聚合操作,并將結果整合到一張表中。盡管 Pandas 是一個很好的資源,但是仍然有許多數(shù)據(jù)操作需要我們人工完成!有關人工特征工程的更多信息,請查閱《Python Data Science Handbook》。
特征工具
幸運的是,Feature Tools 正是我們正在找尋的解決方案。這個開源的 Python 庫可以從一組相關的表中自動構造特征。特征工具基于名為「深度特征合成」的方法(參見《Deep Feature Synthesis: Towards Automating Data Science Endeavors》),這個方法的名字聽起來比其本身更高大上(這個名字源于疊加了多重特征,而不是因為使用了深度學習方法!)。
深度特征合成疊加多個轉換和聚合操作,這在特征工具的詞庫中被稱為特征基元,以便通過分布在多張表內的數(shù)據(jù)來構造新的特征。與機器學習中的大多數(shù)方法一樣,這是建立在簡單概念基礎之上的復雜方法。通過一次學習一個構造塊,我們可以很好地理解這個強大的方法。
首先,讓我們看一下示例數(shù)據(jù)。我們已經(jīng)看到了上面的一些數(shù)據(jù)集,并且完整的表組如下所示:
- clients: 關于信用社客戶的基本信息。每個客戶只對應數(shù)據(jù)框中的一行。
- loans: 向用戶提供的貸款。每項貸款只對應數(shù)據(jù)框中的一行,但是客戶可能有多項貸款。
- payments:貸款還本的支付。每筆支付只對應一行,但是每項貸款可以有多筆支付。
如果我們有一個機器學習任務,例如預測客戶未來是否會償還一項貸款,我們希望將所有關于客戶的信息整合到一張表中。這些表是相關的(通過 client_id 和 loan_id 變量),并且我們可以通過一系列轉換和聚合操作來人工實現(xiàn)這個過程。然而,我們很快就可以使用特征工具來自動實現(xiàn)這個過程。
實體和實體集
特征工具的前兩個概念的是「實體」和「實體集」。一個實體就是一張表(或是 Pandas 中的一個 DataFrame(數(shù)據(jù)框))。一個實體集是一組表以及它們之間的關聯(lián)。將一個實體集看成另一種 Python 數(shù)據(jù)結構,并帶有自己的方法和屬性。
我們可以通過以下操作在特征工具中創(chuàng)建一個空的實體集:
import featuretools as ft # Create new entityset es = ft.EntitySet(id = 'clients')現(xiàn)在我們需要整合兩個實體。每個實體都必須帶有一個索引,它是一個包含所有唯一元素的列。就是說,索引中的每個值只能在表中出現(xiàn)一次。在 clients 數(shù)據(jù)框中的索引是 client_id,因為每個客戶在該數(shù)據(jù)框中只對應一行。我們使用以下語法將一個帶有索引的實體添加一個實體集中:
# 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 數(shù)據(jù)框還有另外一個唯一的索引,loan_id,同時將其添加到實體集的語法與 clients 一樣。然而,payments 數(shù)據(jù)框不存在唯一索引。當我們把 payments 數(shù)據(jù)框添加到實體集中時,我們需要傳入?yún)?shù) make_index = True,同時指定索引的名字。另外,盡管特征工具能自動推斷實體中每列的數(shù)據(jù)類型,但是我們可以通過將列數(shù)據(jù)類型的字典傳遞給參數(shù) 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')對于此數(shù)據(jù)框,盡管 missed 是一個整數(shù),但是它不是一個數(shù)值變量,因為它只能取 2 個離散的數(shù)值,所以在特征工具中,將其看成一個分類變量。在將該數(shù)據(jù)框添加到實體集中后,我們檢查整個實體集:
列的數(shù)據(jù)類型已根據(jù)我們指定的修正方案被正確推斷出來。接下來,我們需要指定實體集中表是如何關聯(lián)的。
表的關聯(lián)
考慮兩張表之間「關聯(lián)」的最好方法是類比父子之間的關聯(lián)。這是一種一對多的關聯(lián):每個父親可以有多個兒子。對表來說,每個父親對應一張父表中的一行,但是子表中可能有多行對應于同一張父表中的多個兒子。
例如,在我們的數(shù)據(jù)集中,clients 數(shù)據(jù)框是 loans 數(shù)據(jù)框的一張父表。每個客戶只對應 clients 表中的一行,但是可能對應 loans 表中的多行。同樣,loans 表是 payments 表的一張父表,因為每項貸款可以有多項支付。父親通過共享變量與兒子相關聯(lián)。當我們執(zhí)行聚合操作的時候,我們根據(jù)父變量對子表進行分組,并計算每個父親的兒子的統(tǒng)計量。
為了形式化特征工具中的關聯(lián)規(guī)則,我們僅需指定連接兩張表的變量。clients 表和 loans 表通過 client_id 變量連接,同時 loans 表和 payments 表通過 loan_id 變量連接。創(chuàng)建關聯(lián)并將其添加到實體集中的語法如下所示:
# 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該實體集現(xiàn)在包含三個實體(表),以及將這些表連接在一起的關聯(lián)規(guī)則。在添加實體和形式化關聯(lián)規(guī)則之后,實體集就完整了并準備好從中構造新的特征。
特征基元
在我們深入了解深度特征合成之前,我們需要了解特征基元的概念。我們其實早就知道是什么了,只是我們剛剛用不同的名字來稱呼它們!它們只是我們用來構造新特征的操作:
- 聚合:根據(jù)父與子(一對多)的關聯(lián)完成的操作,也就是根據(jù)父親分組并計算兒子的統(tǒng)計量。一個例子就是根據(jù) client_id 對 loan 表分組并找到每個客戶的最大貸款額。
- 轉換:對一張表中一或多列完成的操作。一個例子就是取一張表中兩列之間的差值或者取一列的絕對值。
在特征工具中單獨使用這些基元或者疊加使用這些基元可以構造新的特征。以下是特征工具中一些特征基元的列表,也可以自定義特征基元。
特征基元這些基元可以單獨使用或是組合使用以構造新的特征。為了使用特定的基元構造新的特征,我們使用 ft.dfs 函數(shù)(代表深度特征合成)。我們傳入 entityset 和 target_entity,這是我們想要在其中添加特征的表,被選參數(shù) trans_primitives(轉換)和 agg_primitives(聚合)。
public class MyActivity extends AppCompatActivity { @Override //override the functionprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);try {OkhttpManager.getInstance().setTrustrCertificates(getAssets().open("mycer.cer");OkHttpClient mOkhttpClient= OkhttpManager.getInstance().build();} catch (IOException e) {e.printStackTrace();} }返回的是包含每個客戶新特征的數(shù)據(jù)框(因為我們定義客戶為 target_entity)。比如我們有每個客戶加入的月份,這是一個轉換操作的特征基元:
我們也有許多聚合操作的基元,比如每個客戶的平均支付總額:
盡管我們僅指定了一些特征基元,但是特征工具可以通過組合和疊加這些基元來構造新的特征。
完整的數(shù)據(jù)框包含 793 列的新特征!
深度特征合成
我們現(xiàn)在具備理解深度特征合成(dfs)的一切條件。事實上,我們已經(jīng)在前面的函數(shù)調用中執(zhí)行了 dfs!深度特征只是疊加多個基元構造的一個特征,而 dfs 只是構造這些特征的過程的名稱。深度特征的深度是構造這個特征所需的基元數(shù)量。
例如,MEAN(payments.payment_amount)列是深度為 1 的特征,因為它是使用單個聚合操作構造的。LAST(loans(MEAN(payments.payment_amount))是一個深度為 2 的特征,它是由兩個疊加的聚合操作構造的:MEAN 列之上的 LAST(最近的)列。這表示每個客戶最近的貸款平均支付額。
我們可以疊加任意深度的特征,但在實踐中,我從沒有使用超過 2 個深度的特征。此外,這些特征很難解釋,但是我鼓勵任何對「深入」感興趣的人。
我們不必人工指定特征基元,但可以讓特征工具自動為我們選取特征。為此,我們使用相同的 ft.dfs 函數(shù)調用,但是不傳入任何特征基元。
# Perform deep feature synthesis without specifying primitives features, feature_names = ft.dfs(entityset=es, target_entity='clients', max_depth = 2)features.head()特征工具構造了很多特征供我們使用。盡管這個過程確實能自動構造新的特征,但是它不會取代數(shù)據(jù)科學家,因為我們仍然需要弄清楚如何處理這些特征。例如,我們的目的是預測一位客戶是否會償還貸款,我們可以尋找與特定結果最相關的特征。此外,如果我們具有領域知識,我們可以用這些知識來選擇指定的特征基元或候選特征的種子深度特征合成。
下一步
特征工程自動化解決了一個問題,但是帶來了另一個問題:特征太多了。盡管在擬合一個模型之前很難說哪些特征是重要的,但很可能不是所有這些特征都與我們想要訓練的模型的任務相關。此外,擁有太多特征(參見《Irrelevant Features and the Subset Selection Problem》)可能會導致模型性能不佳,因為較無益的特征會淹沒那些更重要的特征。
特征過多問題以維度災難著稱。隨著特征數(shù)量的上升(數(shù)據(jù)維度增長),模型越來越難以學習特征與目標之間的映射關系。事實上,讓模型表現(xiàn)良好所需的數(shù)據(jù)量與特征數(shù)量成指數(shù)關系。
維度災難與特征降維(也叫特征選擇,去除不相關特征的過程)相對。這可以采用多種形式:主成分分析(PCA)、SelectKBest、使用模型中特征的重要性或使用深度神經(jīng)網(wǎng)絡進行自編碼。但是,特征降維是另一篇文章的不同主題。到目前為止,我們知道我們可以使用特征工具以最小的努力從許多表中構造大量的特征!
結論
與機器學習中的許多主題一樣,使用特征工具進行特征工程自動化是一個基于簡單想法的復雜概念。使用實體集、實體和關聯(lián)的概念,特征工具可以執(zhí)行深度特征合成操作來構造新的特征。深度特征合成可以依次疊加特征基元:「聚合」,它們在多張表間的一對多關聯(lián)中起作用,以及「轉換」,是應用于單張表中一或多列以從多張表中構造新的特征的函數(shù)。
在之后的文章中,我將介紹如何在現(xiàn)實世界的問題上使用這項技術,即在 Kaggle 上舉辦的房屋信用違約風險競賽(https://www.kaggle.com/c/home-credit-default-risk)。請繼續(xù)關注那則帖子,與此同時,閱讀這則說明以開始競賽(https://towardsdatascience.com/machine-learning-kaggle-competition-part-one-getting-started-32fb9ff47426)! 我希望你們可以使用特征工程自動化作為數(shù)據(jù)科學工作中的輔助工具。我們的模型與我們提供的數(shù)據(jù)一樣好,并且特征工程自動化可以使特征構造的過程更高效。
有關特征工具更多的信息,包括高級用法,請查看在線文檔(https://docs.featuretools.com/)。要了解在實踐中如何使用特征工具,請閱讀開源庫的開發(fā)公司 Feature Labs 的工作(https://www.featurelabs.com/)。
原文鏈接:https://towardsdatascience.com/automated-feature-engineering-in-python-99baf11cc219
總結
以上是生活随笔為你收集整理的Feature Tools:可自动构造机器学习特征的Python库的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Elasticsearch的Scroll
- 下一篇: spring几种获取 HttpServl