【導(dǎo)讀】如今機(jī)器學(xué)習(xí)正在從人工設(shè)計(jì)模型更多地轉(zhuǎn)移到自動(dòng)優(yōu)化工作流中,如 H20、TPOT 和 auto-sklearn 等工具已被廣泛使用。這些庫(kù)以及隨機(jī)搜索等方法都致力于尋找最適合數(shù)據(jù)集的模型,以此簡(jiǎn)化模型篩選與調(diào)優(yōu)過(guò)程,而不需要任何人工干預(yù)。然而,特征工程作為機(jī)器學(xué)習(xí)過(guò)程中最有價(jià)值的一個(gè)環(huán)節(jié),卻幾乎一直由人工來(lái)完成。
在本文中,我們通過(guò)引用一個(gè)數(shù)據(jù)集作為例子來(lái)給大家介紹基礎(chǔ)知識(shí),并給大家介紹一個(gè)基于 Featuretools Python 庫(kù)來(lái)實(shí)現(xiàn)特征工程自動(dòng)化的實(shí)例。
前言
特征工程也可以稱作特征構(gòu)造,是基于現(xiàn)有數(shù)據(jù)構(gòu)造新特征來(lái)訓(xùn)練機(jī)器學(xué)習(xí)模型的過(guò)程??梢哉f(shuō)這個(gè)環(huán)節(jié)比我們具體使用什么模型更重要,因?yàn)闄C(jī)器學(xué)習(xí)算法只會(huì)基于我們提供給它的數(shù)據(jù)進(jìn)行學(xué)習(xí),所以構(gòu)造與目標(biāo)任務(wù)相關(guān)的特征是極其重要的(詳見(jiàn)論文「A Few Useful Things to Know about Machine Learning」)。
論文鏈接:
https://homes.cs.washington.edu/~pedrod/papers/cacm12.pdf
一般來(lái)說(shuō),特征工程是一個(gè)漫長(zhǎng)的人工過(guò)程,依賴于領(lǐng)域知識(shí)、直覺(jué)及數(shù)據(jù)操作。這一過(guò)程是極其單調(diào)的,而且最終的特征結(jié)果會(huì)受人的主觀性和時(shí)間所限制。自動(dòng)特征工程旨在幫助數(shù)據(jù)科學(xué)家基于數(shù)據(jù)集自動(dòng)地構(gòu)造候選特征,并從中挑選出最適合于訓(xùn)練的特征。
特征工程基礎(chǔ)知識(shí)
特征工程意味著基于現(xiàn)有數(shù)據(jù)構(gòu)造額外的特征,這些待分析的數(shù)據(jù)往往分布在多張相關(guān)聯(lián)的表中。特征工程需要從數(shù)據(jù)中提取信息,然后將其整合成一張單獨(dú)的表用來(lái)訓(xùn)練機(jī)器學(xué)習(xí)模型。
特征構(gòu)造是一個(gè)非常耗時(shí)的過(guò)程,因?yàn)槊總€(gè)新特征都需要經(jīng)過(guò)幾個(gè)步驟去構(gòu)造,特別是那些需要用到多張表信息的特征。我們可以把這些特征構(gòu)造的操作合起來(lái),分成兩個(gè)類:“轉(zhuǎn)換(transformation)”和“聚合(aggregation)”。下面我們通過(guò)幾個(gè)例子來(lái)理解一下這些概念。
“轉(zhuǎn)換”適用于單張表格,這個(gè)環(huán)節(jié)基于一個(gè)或多個(gè)現(xiàn)有數(shù)據(jù)列構(gòu)造新的特征。例如,現(xiàn)在我們有下面這張客戶數(shù)據(jù)表:

我們可以通過(guò)查找 joined 列的月份或?qū)?income 列取自然對(duì)數(shù)來(lái)構(gòu)造新特征。這些都屬于“轉(zhuǎn)換”操作,因?yàn)樗鼈兌贾挥昧藖?lái)自一張表的信息。

另一方面,“聚合”是需要進(jìn)行跨表操作的,并且要基于一對(duì)多的關(guān)系來(lái)把觀測(cè)值分組,然后進(jìn)行數(shù)據(jù)統(tǒng)計(jì)。例如,如果我們有另一張關(guān)于客戶貸款信息的表格,其中每位客戶可能有多筆貸款,那么我們就可以計(jì)算每位客戶貸款額的平均值、最大值和最小值等統(tǒng)計(jì)量了。
這一過(guò)程包括根據(jù)不同用戶對(duì)貸款數(shù)據(jù)表進(jìn)行分組,計(jì)算聚合后的統(tǒng)計(jì)量,然后把結(jié)果整合到客戶數(shù)據(jù)中。以下是我們?cè)?Python 中用 Pandas 執(zhí)行此過(guò)程的代碼:
importpandasaspd#Grouploansbyclientidandcalculatemean,max,minofloansstats=loans.groupby('client_id')['loan_amount'].agg(['mean','max','min'])stats.columns=['mean_loan_amount','max_loan_amount','min_loan_amount']#Mergewiththeclientsdataframestats=clients.merge(stats,left_on='client_id',right_index=True,how='left')stats.head(10)

這些操作本身并不難,但如果我們有上百個(gè)變量,它們分布在幾十張表中,若要手動(dòng)完成這一過(guò)程就比較困難了。理想情況下,我們想找到一個(gè)解決方案,可以自動(dòng)執(zhí)行多個(gè)表的轉(zhuǎn)換和聚合,并將結(jié)果數(shù)據(jù)整合到一張表中。雖然 Pandas 是非常棒的資源,但需要我們手動(dòng)完成的數(shù)據(jù)操作工作量仍非常巨大!
▌特征工具(Featuretools)
幸運(yùn)的是,特征工具正是我們?cè)谡业慕鉀Q方案。這個(gè)開(kāi)源的 Python 庫(kù)可以基于一組相關(guān)的表自動(dòng)創(chuàng)建特征。特征工具以“深度特征合成(Deep Feature Synthesis,簡(jiǎn)稱 DFS)”為基礎(chǔ),這個(gè)方法聽(tīng)起來(lái)比它本身要高級(jí)很多(之所以叫“深度特征合成”,不是因?yàn)槭褂昧?a href="http://www.makelele.cn/v/tag/448/" target="_blank">深度學(xué)習(xí),而是疊加了多重特征)。
深度特征合成疊加了多重轉(zhuǎn)換和聚合操作,這在特征工具詞庫(kù)中被稱作特征基元 (feature primitives),用于通過(guò)多張表的數(shù)據(jù)來(lái)構(gòu)造特征。和機(jī)器學(xué)習(xí)中的大多數(shù)方法一樣,這是一個(gè)以簡(jiǎn)單概念為基礎(chǔ)的復(fù)雜方法。通過(guò)每次學(xué)習(xí)一個(gè)構(gòu)造塊,我們就可以很好地理解這個(gè)強(qiáng)大的方法。
首先,我們來(lái)看一下例子中的數(shù)據(jù)。我們已經(jīng)看到上面提到的部分?jǐn)?shù)據(jù)集,全部的表如下所示:
clients:關(guān)于一家信用社客戶的基本信息。每位客戶只對(duì)應(yīng)表中的一行數(shù)據(jù)。
loans:客戶名下的貸款。每筆貸款只對(duì)應(yīng)表中的一行數(shù)據(jù),但每位客戶名下可能有多筆貸款。
payments:還貸金額。每筆支付只對(duì)應(yīng)一行數(shù)據(jù),但每項(xiàng)貸款可能分多次支付。
如果我們有一個(gè)機(jī)器學(xué)習(xí)任務(wù),比如預(yù)測(cè)某位客戶是否會(huì)還清未來(lái)的一筆貸款,我們需要把有關(guān)客戶的所有信息都整合到一張表中。這些表通過(guò)變量 client_id 和 loan_id 相互關(guān)聯(lián),我們可以用一系列轉(zhuǎn)換和聚合來(lái)手動(dòng)完成這一過(guò)程。然而我們很快就會(huì)發(fā)現(xiàn),我們可以使用特征工具來(lái)將這個(gè)過(guò)程自動(dòng)化。
▌實(shí)體與實(shí)體集
首先要介紹特征工具的兩個(gè)概念:實(shí)體 (entity) 和實(shí)體集 (entityset)。簡(jiǎn)單來(lái)說(shuō),一個(gè)實(shí)體就是一張表(即 Pandas 中的一個(gè) DataFrame)。一個(gè)實(shí)體集是指多個(gè)表的集合以及它們之間的相互關(guān)系。我們可以把實(shí)體集看作一種 Python 的數(shù)據(jù)結(jié)構(gòu),且有其專屬的方法和屬性。
我們可以在特征工具中創(chuàng)建一個(gè)空的實(shí)體集,如下所示:
importfeaturetoolsasft#Createnewentitysetes=ft.EntitySet(id='clients')
現(xiàn)在我們要把多個(gè)實(shí)體進(jìn)行合并。每個(gè)實(shí)體必須帶有一個(gè)索引,即所有元素都唯一的數(shù)據(jù)列。也就是說(shuō),索引列中的每個(gè)值在表中只能出現(xiàn)一次。
clients 數(shù)據(jù)框(dataframe)的索引是 client_id,因?yàn)槊课豢蛻舳贾粚?duì)應(yīng)表中的一行數(shù)據(jù)。我們可以通過(guò)如下語(yǔ)法把一個(gè)帶有索引的實(shí)體加入一個(gè)實(shí)體集:
#Createanentityfromtheclientdataframe#Thisdataframealreadyhasanindexandatimeindexes=es.entity_from_dataframe(entity_id='clients',dataframe=clients,index='client_id',time_index='joined')
loans 數(shù)據(jù)框也有唯一索引 loan_id,將其加入實(shí)體集的語(yǔ)法和處理 clients 的語(yǔ)法相同。然而,payments 數(shù)據(jù)框中沒(méi)有唯一的索引。若我們想把這個(gè)實(shí)體加入實(shí)體集,則需要讓 make_index = True,并指定一個(gè)索引名。雖然特征工具可以自動(dòng)推斷實(shí)體中每一列的數(shù)據(jù)類型,但我們也可以通過(guò)把數(shù)據(jù)類型字典傳入?yún)?shù) variable_types 來(lái)將其覆蓋。
#Createanentityfromthepaymentsdataframe#Thisdoesnotyethaveauniqueindexes=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')
對(duì)于這個(gè)數(shù)據(jù)框,雖然 missed 是整數(shù),但并不是數(shù)值變量,因?yàn)樗荒苋蓚€(gè)離散值,所以我們讓特征工具將其當(dāng)作一個(gè)類別變量處理。將數(shù)據(jù)框全部加入實(shí)體集后,我們看到:
根據(jù)我們指定的修正方案,這些列的類型都被正確識(shí)別了。下一步,我們需要指定實(shí)體集中各個(gè)表之間的關(guān)聯(lián)。
▌表之間的關(guān)聯(lián)
研究?jī)杀碇g關(guān)系的最好方法是與父子關(guān)系進(jìn)行類比。這是一種一對(duì)多的關(guān)系:每位父親可能有多個(gè)孩子。從表的角度來(lái)看,父表中的每一行對(duì)應(yīng)一位父親,但子表可能有多行數(shù)據(jù),就像同一位父親的多個(gè)孩子。
例如,在我們的數(shù)據(jù)集中,clients 是 loans 的父表。每位客戶只對(duì)應(yīng) clients 表中的一行數(shù)據(jù),但可能對(duì)應(yīng) loans 表中的多行數(shù)據(jù)。同樣,loans 是 payments 的父表,因?yàn)槊抗P貸款可能包含多筆支付。父表通過(guò)共有的變量與子表相連接。當(dāng)執(zhí)行聚合操作時(shí),我們根據(jù)父表的變量對(duì)子表進(jìn)行歸類,并計(jì)算每個(gè)子表的統(tǒng)計(jì)量。
若要標(biāo)明特征工具中的關(guān)聯(lián),我們只需指定連接兩張表的變量。表 clients 和表 loans 是通過(guò)變量 client_id 相關(guān)聯(lián)的,表 loans 和表 payments 通過(guò) loan_id 相關(guān)聯(lián)??赏ㄟ^(guò)如下語(yǔ)法創(chuàng)建關(guān)聯(lián)并將其加入實(shí)體集:
#Relationshipbetweenclientsandpreviousloansr_client_previous=ft.Relationship(es['clients']['client_id'],es['loans']['client_id'])#Addtherelationshiptotheentitysetes=es.add_relationship(r_client_previous)#Relationshipbetweenpreviousloansandpreviouspaymentsr_payments=ft.Relationship(es['loans']['loan_id'],es['payments']['loan_id'])#Addtherelationshiptotheentitysetes=es.add_relationship(r_payments)es
該實(shí)體集現(xiàn)在包括三個(gè)實(shí)體以及連接這些實(shí)體之間的關(guān)系。加入實(shí)體并標(biāo)明關(guān)聯(lián)后,我們的實(shí)體集就完整了,并做好了構(gòu)造新特征的準(zhǔn)備。
▌特征基元
在正式進(jìn)行深度特征合成之前,我們需要理解特征基元這個(gè)概念。我們已經(jīng)知道了特征基元是什么,但也只是了解用什么名字來(lái)稱呼它們。下面是我們構(gòu)造新特征時(shí)的基本操作:
聚合:基于父表與子表的關(guān)聯(lián)(一對(duì)多)完成的系列操作,即根據(jù)父表對(duì)子表進(jìn)行分組并計(jì)算其統(tǒng)計(jì)量。例如,根據(jù) client_id 對(duì) loan 表進(jìn)行分組,并找到每位客戶最大的貸款數(shù)額。
轉(zhuǎn)換:對(duì)一張表中一列或多列進(jìn)行的操作。例如,計(jì)算一張表中兩列的差值或計(jì)算一列的絕對(duì)值。
在特征工具中,我們可以通過(guò)單個(gè)基元或者疊加多個(gè)基元來(lái)構(gòu)造新特征。下面是特征工具中一些特征基元的列表(我們也可以自定義基元):
▌特征基元
這些基元可以拿來(lái)單獨(dú)使用或者結(jié)合起來(lái)構(gòu)造新的特征。根據(jù)特定的基元,我們可以使用 ft.dfs 函數(shù)(即深度特征合成)來(lái)構(gòu)造特征。我們將所選的 trans_primitives(轉(zhuǎn)換)和 agg_primitives(聚合)傳入 entityset(實(shí)體集)和 target_entity(目標(biāo)實(shí)體),即我們想要添加特征的表:
#Createnewfeaturesusingspecifiedprimitivesfeatures,feature_names=ft.dfs(entityset=es,target_entity='clients',agg_primitives=['mean','max','percent_true','last'],trans_primitives=['years','month','subtract','divide'])
得到的結(jié)果是一個(gè)含有新特征的客戶數(shù)據(jù)框(因?yàn)槲覀儼延脩舢?dāng)作了 target_entity)。例如,若我們知道每位用戶加入的月份,這可以作為一個(gè)轉(zhuǎn)換特征基元:

我們也有許多聚合基元,如每位客戶的平均支付額:

雖然我們只列舉了一部分特征基元,但實(shí)際上特征工具通過(guò)結(jié)合與疊加這些基元構(gòu)造了許多新的特征。

完整的數(shù)據(jù)框包含了793個(gè)新特征!
▌深度特征合成
現(xiàn)在我們已經(jīng)做好理解深度特征合成的全部準(zhǔn)備了。實(shí)際上,我們?cè)谥皥?zhí)行函數(shù)時(shí)已經(jīng)使用過(guò)深度特征合成了!深度特征是指通過(guò)疊加多個(gè)基元得到的特征,深度特征合成是指構(gòu)造這些特征的過(guò)程。一個(gè)深度特征的深度是為構(gòu)造這個(gè)特征所使用的基元數(shù)目。
例如,MEAN(payments.payment_amount)列是一個(gè)深度為 1 的深度特征,因?yàn)樗跇?gòu)造過(guò)程中只使用了一個(gè)聚合基元。LAST(loans(MEAN(payments.payment_amount)) 是一個(gè)深度為 2 的特征,它由兩個(gè)聚合基元疊加構(gòu)成:將 LAST 疊加在了 MEAN 上。這個(gè)特征代表客戶最近一筆支付額的平均值。

我們可以疊加特征到任何想達(dá)到的深度,但事實(shí)上,我從來(lái)沒(méi)有用過(guò)深度超過(guò) 2 的特征。關(guān)于這一點(diǎn)很難解釋清楚,但我鼓勵(lì)感興趣的人嘗試更進(jìn)一步的探索。
我們無(wú)需手動(dòng)指定特征基元,特征工具可以幫助我們自動(dòng)選擇特征。為此,我們同樣使用 ft.dfs 函數(shù)來(lái)調(diào)用但無(wú)需傳入任何特征基元:
#Performdeepfeaturesynthesiswithoutspecifyingprimitivesfeatures,feature_names=ft.dfs(entityset=es,target_entity='clients',max_depth=2)features.head()
特征工具構(gòu)造了許多供我們使用的新特征。雖然這一過(guò)程可以自動(dòng)構(gòu)造新特征,但它不會(huì)取代數(shù)據(jù)科學(xué)家的位置,因?yàn)槲覀冞€要清楚如何使用這些特征。例如,如果我們的目標(biāo)是預(yù)測(cè)某位客戶是否會(huì)償還貸款,那么我們要找出與指定結(jié)果相關(guān)度最高的特征。此外,如果我們有領(lǐng)域知識(shí),則可以利用領(lǐng)域知識(shí)來(lái)選出特定的特征基元,或通過(guò)深度特征合成從候選特征中得到種子特征。
▌下一步
自動(dòng)特征工程解決了一個(gè)問(wèn)題,但也制造了另一個(gè)問(wèn)題:特征過(guò)多。雖然在擬合模型前我們很難說(shuō)哪些特征是重要的,但肯定不是所有特征都與目標(biāo)任務(wù)相關(guān)。而且,特征過(guò)多可能會(huì)導(dǎo)致模型性能很差,因?yàn)椴荒敲粗匾奶卣鲿?huì)影響到那些更重要的特征。
由特征過(guò)多導(dǎo)致的問(wèn)題又被公認(rèn)為“維度的詛咒”。對(duì)于模型來(lái)說(shuō),特征數(shù)量上升了(即數(shù)據(jù)維度增加了),學(xué)習(xí)特征和目標(biāo)之間的映射規(guī)則也會(huì)變得更加困難。實(shí)際上,使模型有良好表現(xiàn)所需的數(shù)據(jù)量與特征數(shù)目呈指數(shù)關(guān)系。
“維度的詛咒”可以通過(guò)特征降維(也被稱為特征選擇)來(lái)減輕:這是一個(gè)剔除不相關(guān)特征的過(guò)程。我們可以通過(guò)多種途徑實(shí)現(xiàn):主成分分析 (PCA)、SelectKBest、使用模型的特征重要性或使用深度神經(jīng)網(wǎng)絡(luò)來(lái)自動(dòng)編碼。和今天要探討的內(nèi)容相比,特征降維應(yīng)該另起一篇文章來(lái)單獨(dú)討論更合適。到現(xiàn)在為止,我們已經(jīng)知道如何使用特征工具,從諸多數(shù)據(jù)表中輕松構(gòu)造大量的特征了!
總結(jié)
同機(jī)器學(xué)習(xí)中的許多主題一樣,基于特征工具的自動(dòng)特征工程是一個(gè)以簡(jiǎn)單概念為基礎(chǔ)的復(fù)雜方法?;趯?shí)體集、實(shí)體和關(guān)聯(lián)等概念,特征工具可以通過(guò)深度特征合成來(lái)構(gòu)造新的特征。深度特征合成將包含了表間一對(duì)多關(guān)聯(lián)的“聚合”特征基元依次疊加,“轉(zhuǎn)換”函數(shù)被用于單張表中的一列或多列數(shù)據(jù),以此來(lái)從多張表中構(gòu)造新的特征。
在之后的文章中,AI科技大本營(yíng)也會(huì)介紹在實(shí)際應(yīng)用(如 Kaggle 競(jìng)賽)中如何使用這項(xiàng)技術(shù)。模型的好壞取決于我們?yōu)樗峁┑臄?shù)據(jù),而自動(dòng)特征工程有助于使特征構(gòu)造過(guò)程的效率更高。希望本文介紹的自動(dòng)特征工程可以幫到大家。
關(guān)于特征工具的更多信息,包括更高級(jí)的應(yīng)用方法,可以查看在線文檔。
-
自動(dòng)化
+關(guān)注
關(guān)注
31文章
5947瀏覽量
90356 -
機(jī)器學(xué)習(xí)
+關(guān)注
關(guān)注
66文章
8556瀏覽量
137049 -
python
+關(guān)注
關(guān)注
58文章
4877瀏覽量
90127
原文標(biāo)題:基于Python的自動(dòng)特征工程——教你如何自動(dòng)創(chuàng)建機(jī)器學(xué)習(xí)特征
文章出處:【微信號(hào):rgznai100,微信公眾號(hào):rgznai100】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
10個(gè)殺手級(jí)的Python自動(dòng)化腳本
招聘自動(dòng)化、電氣自動(dòng)化、自動(dòng)化控制工程師
【上?!揩C頭推薦職位-自動(dòng)化測(cè)試工程師(java/python)
python自動(dòng)化控制設(shè)備 精選資料分享
電子設(shè)計(jì)自動(dòng)化(EDA)是什么
Python成為軟件工程師的最愛(ài)
python控制CANoe實(shí)現(xiàn)自動(dòng)化測(cè)試的方法
自動(dòng)化立體庫(kù)結(jié)構(gòu)是如何組成的
自動(dòng)化立體庫(kù)的工作原理
分享10個(gè)實(shí)用的Python自動(dòng)化腳本
使用Python腳本實(shí)現(xiàn)自動(dòng)化運(yùn)維任務(wù)
使用Python實(shí)現(xiàn)功能測(cè)試自動(dòng)化
Facebook群組自動(dòng)化python – 網(wǎng)絡(luò)自動(dòng)化
Python 模擬鍵盤鼠標(biāo)的方式實(shí)現(xiàn)自動(dòng)化
基于Featuretools Python庫(kù)來(lái)實(shí)現(xiàn)特征工程自動(dòng)化的實(shí)例
評(píng)論