本文將系統(tǒng)全面的介紹自動(dòng)機(jī)器學(xué)習(xí)的其中一個(gè)常用框架 : TPOT,一起研習(xí)如何在 Python 中將 TPOT 用于 AutoML 和 Scikit-Learn 機(jī)器學(xué)習(xí)算法。 分類和回歸小案例,以及一些用戶手冊(cè)的介紹??靵砗托『镒右黄鹧辛?xí)吧!
如果你在機(jī)器學(xué)習(xí)建模期間花費(fèi)數(shù)小時(shí)甚至數(shù)天時(shí)間來,一直嘗試挑選最佳管道和參數(shù)的過程,那么我建議你仔細(xì)閱讀本文。
自動(dòng)機(jī)器學(xué)習(xí) (AutoML) 是指需要極少人工參與的情況下自動(dòng)發(fā)現(xiàn)性能良好的模型用于預(yù)測(cè)建模任務(wù)的技術(shù)。
本文核心內(nèi)容:
- TPOT 是一個(gè)用于 AutoML 的開源庫,具有 scikit-learn 數(shù)據(jù)準(zhǔn)備和機(jī)器學(xué)習(xí)模型。
- 如何使用 TPOT 自動(dòng)發(fā)現(xiàn)分類任務(wù)的最佳模型。
- 如何使用 TPOT 自動(dòng)發(fā)現(xiàn)回歸任務(wù)的最佳模型。
TPOT簡介
Tree-based Pipeline Optimization Tool [1] , 基于樹的管道優(yōu)化工具,簡稱 TPOT,是一個(gè)用于在 Python 中執(zhí)行 AutoML 的開源庫。
TPOT 使用基于樹的結(jié)構(gòu)來表示預(yù)測(cè)建模問題的模型管道,包括數(shù)據(jù)準(zhǔn)備和建模算法以及模型超參數(shù)。它利用流行的 Scikit-Learn 機(jī)器學(xué)習(xí)庫進(jìn)行數(shù)據(jù)轉(zhuǎn)換和機(jī)器學(xué)習(xí)算法,并使用遺傳編程隨機(jī)全局搜索過程來有效地發(fā)現(xiàn)給定數(shù)據(jù)集的性能最佳的模型管道。
… an evolutionary algorithm called the Tree-based Pipeline Optimization Tool (TPOT) that automatically designs and optimizes machine learning pipelines.
… 一種稱為基于樹的管道優(yōu)化工具 (TPOT) 的進(jìn)化算法,可自動(dòng)設(shè)計(jì)和優(yōu)化機(jī)器學(xué)習(xí)管道。
然后執(zhí)行優(yōu)化過程以找到對(duì)給定數(shù)據(jù)集執(zhí)行最佳的樹結(jié)構(gòu)。具體來說,一種遺傳編程算法,旨在對(duì)表示為樹的程序執(zhí)行隨機(jī)全局優(yōu)化。
TPOT uses a version of genetic programming to automatically design and optimize a series of data transformations and machine learning models that attempt to maximize the classification accuracy for a given supervised learning data set.
TPOT 使用遺傳編程的一個(gè)版本來自動(dòng)設(shè)計(jì)和優(yōu)化一系列數(shù)據(jù)轉(zhuǎn)換和機(jī)器學(xué)習(xí)模型,這些模型試圖最大限度地提高給定監(jiān)督學(xué)習(xí)數(shù)據(jù)集的分類精度。
下圖取自 TPOT 論文,展示了管道搜索所涉及的元素,包括數(shù)據(jù)清洗、特征選擇、特征處理、特征構(gòu)建、模型選擇和超參數(shù)優(yōu)化。
TPOT 將通過智能探索數(shù)千條可能的管道來為你的數(shù)據(jù)找到最佳管道,從而自動(dòng)化機(jī)器學(xué)習(xí)中最繁瑣的部分。
機(jī)器學(xué)習(xí)管道示例
接下來我們一起看看如何安裝和使用 TPOT 來找到一個(gè)有效的模型管道。
安裝和使用 TPOT
第一步安裝TPOT庫
pip install tpot
安裝后,導(dǎo)入庫并打印版本號(hào)以確認(rèn)它已成功安裝:
# check tpot versionimport tpotprint(‘tpot: %s’ % tpot.__version__)
使用 TPOT 庫很簡單
需要?jiǎng)?chuàng)建 TPOTRegressor 或 TPOTClassifier 類 [2] 的實(shí)例,并做好配置后進(jìn)行搜索,然后導(dǎo)出在數(shù)據(jù)集上找到的最佳性能的模型管道。
配置類涉及兩個(gè)主要元素。
首先是如何評(píng)估模型,例如交叉驗(yàn)證方案和性能指標(biāo)選擇。建議使用選擇的配置和要使用的性能指標(biāo)明確指定交叉驗(yàn)證類。
例如要使用 neg_mean_absolute_error 作為回歸度量,則選用 RepeatedKFold [3] 用于回歸交叉驗(yàn)證。
# 定義了評(píng)價(jià)步驟cv = RepeatedKFold(n_splits=10, n_repeats=3, random_state=1)# 定義搜索model = TPOTRegressor(… scoring=’neg_mean_absolute_error’, cv=cv)
或者使用 accuracy 作為分類模型的評(píng)價(jià)指標(biāo),則選用 RepeatedStratifiedKFold [4] 用于分類交叉驗(yàn)證。
# 定義了評(píng)價(jià)步驟cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)# 定義搜索model = TPOTClassifier(… scoring=’accuracy’, cv=cv)
作為一種進(jìn)化算法,涉及到較為復(fù)雜的配置的設(shè)置,例如種群規(guī)模、要運(yùn)行的代數(shù)以及潛在的交叉和突變率。前者重要地控制著搜索的范圍;如果你對(duì)進(jìn)化搜索算法不熟悉,可以將后者保留設(shè)置為默認(rèn)值。
例如,100 代和 5 或 10 代的適度種群規(guī)模是一個(gè)很好的起點(diǎn)。
# define 搜索model = TPOTClassifier(generations=5, population_size=50, …)
在搜索結(jié)束時(shí),會(huì)找到性能最佳的管道。
此輸出最佳模型的管道可以導(dǎo)出為py文件,后期可以將其復(fù)制并粘貼到你自己的項(xiàng)目中。
# 輸出最佳模型model.export(‘tpot_model.py’)
TPOT 分類
這里使用 TPOT 來發(fā)現(xiàn)聲納數(shù)據(jù)集的最佳模型。
聲納數(shù)據(jù)集 [5] 是一個(gè)標(biāo)準(zhǔn)的機(jī)器學(xué)習(xí)數(shù)據(jù)集,由 208 行數(shù)據(jù)和 60 個(gè)數(shù)字輸入變量和一個(gè)具有兩個(gè)類值的目標(biāo)變量組成,例如二進(jìn)制分類。
使用具有三個(gè)重復(fù)分層 10 折交叉驗(yàn)證的測(cè)試工具,樸素模型可以達(dá)到約 53% 的準(zhǔn)確度。性能最佳的模型可以在相同的測(cè)試工具上實(shí)現(xiàn)大約 88% 的準(zhǔn)確度。這達(dá)到了該數(shù)據(jù)集的預(yù)期性能界限。
該數(shù)據(jù)集涉及預(yù)測(cè)聲納返回是否指示巖石或礦井。
# summarize the sonar datasetfrom pandas import read_csv# load datasetdataframe = read_csv(data, header=None)# split into input and output elementsdata = dataframe.valuesX, y = data[:, :-1], data[:, -1]print(X.shape, y.shape)
導(dǎo)入數(shù)據(jù)集并將其拆分為輸入和輸出數(shù)據(jù)集??梢钥吹接?60 個(gè)輸入變量的 208 行數(shù)據(jù)。
首先,我們可以定義評(píng)估模型的方法,使用 RepeatedStratifiedKFold交叉驗(yàn)證 。
# 定義模型評(píng)估器cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
將使用 50 個(gè)人口大小進(jìn)行五折搜索,并設(shè)置 n_jobs = -1 來使用系統(tǒng)上的所有核心。
# 定義搜索model = TPOTClassifier(generations=5, population_size=50, cv=cv, scoring=’accuracy’, verbosity=2, random_state=1, n_jobs=-1)
最后,開始搜索并確保在運(yùn)行結(jié)束時(shí)保存性能最佳的模型。
# 執(zhí)行搜索model.fit(X, y)# 輸出最佳模型model.export(‘tpot_sonar_best_model.py’)
這里可能需要運(yùn)行幾分鐘,這里比較人性化的設(shè)置就是可以在命令行上看到一個(gè)進(jìn)度條。
注意:你的結(jié)果可能會(huì)因算法或評(píng)估程序的隨機(jī)性或數(shù)值精度的差異而有所不同。在現(xiàn)實(shí)案例中,可以多運(yùn)行幾次并比較平均結(jié)果。
將在此過程中將會(huì)輸出報(bào)告性能最佳模型的準(zhǔn)確性。
Generation 1 – Current best internal CV score: 0.8650793650793651Generation 2 – Current best internal CV score: 0.8650793650793651Generation 3 – Current best internal CV score: 0.8650793650793651Generation 4 – Current best internal CV score: 0.8650793650793651Generation 5 – Current best internal CV score: 0.8667460317460318Best pipeline: GradientBoostingClassifier(GaussianNB(input_matrix),learning_rate=0.1, max_depth=7, max_features=0.7000000000000001,min_samples_leaf=15, min_samples_split=10, n_estimators=100, subsample=0.9000000000000001)
這里可以看到表現(xiàn)最好的管道達(dá)到了大約 86.6% 的平均準(zhǔn)確率。這里接近該數(shù)據(jù)集上表現(xiàn)最好的模型了。
最后將性能最佳的管道保存到名為 “ tpot_sonar_best_model.py ” 的文件中。
加載數(shù)據(jù)集和擬合管道的通用代碼
# 在聲納數(shù)據(jù)集上擬合最終模型并做出預(yù)測(cè)的例子from pandas import read_csvfrom sklearn.preprocessing import LabelEncoderfrom sklearn.model_selection import RepeatedStratifiedKFoldfrom sklearn.ensemble import GradientBoostingClassifierfrom sklearn.naive_bayes import GaussianNBfrom sklearn.pipeline import make_pipelinefrom tpot.builtins import StackingEstimatorfrom tpot.export_utils import set_param_recursive# 導(dǎo)入數(shù)據(jù)集dataframe = read_csv(data, header=None)# 拆分為輸入變量和輸出變量data = dataframe.valuesX, y = data[:, :-1], data[:, -1]# 以盡量小的內(nèi)存使用數(shù)據(jù)集X = X.astype(‘float32’)y = LabelEncoder().fit_transform(y.astype(‘str’))# 訓(xùn)練集上的交叉驗(yàn)證平均分?jǐn)?shù)為: 0.8667exported_pipeline = make_pipeline( StackingEstimator(estimator=GaussianNB()), GradientBoostingClassifier(learning_rate=0.1, max_depth=7, max_features=0.7000000000000001, min_samples_leaf=15, min_samples_split=10, n_estimators=100, subsample=0.9000000000000001))# 修正了導(dǎo)出管道中所有步驟的隨機(jī)狀態(tài)set_param_recursive(exported_pipeline.steps, ‘random_state’, 1)# 訓(xùn)練模型exported_pipeline.fit(X, y)# 對(duì)新數(shù)據(jù)行進(jìn)行預(yù)測(cè)row = [0.0200,0.0371,0.0428,0.0207,0.0954,0.0986]yhat = exported_pipeline.predict([row])print(‘Predicted: %.3f’ % yhat[0])
TPOT 回歸
本節(jié)使用 TPOT 來發(fā)現(xiàn)汽車保險(xiǎn)數(shù)據(jù)集的最佳模型。
汽車保險(xiǎn)數(shù)據(jù)集 [6] 是一個(gè)標(biāo)準(zhǔn)的機(jī)器學(xué)習(xí)數(shù)據(jù)集,由 63 行數(shù)據(jù)組成,一個(gè)數(shù)字輸入變量和一個(gè)數(shù)字目標(biāo)變量。
使用具有3 次重復(fù)的分層 10 折交叉驗(yàn)證的測(cè)試工具,樸素模型可以實(shí)現(xiàn)約 66 的平均絕對(duì)誤差 (MAE)。性能最佳的模型可以在相同的測(cè)試工具上實(shí)現(xiàn)MAE約 28。這達(dá)到了該數(shù)據(jù)集的預(yù)期性能界限。
過程類似于分類。
加載數(shù)據(jù)集和擬合管道的通用代碼
# 擬合最終模型并在保險(xiǎn)數(shù)據(jù)集上做出預(yù)測(cè)的例子from pandas import read_csvfrom sklearn.model_selection import train_test_splitfrom sklearn.svm import LinearSVR# 導(dǎo)入數(shù)據(jù)集dataframe = read_csv(data, header=None)# 拆分為輸入變量和輸出變量data = dataframe.values# 以盡量小的內(nèi)存使用數(shù)據(jù)集data = data.astype(‘float32’)X, y = data[:, :-1], data[:, -1]# 訓(xùn)練集上的交叉驗(yàn)證平均分?jǐn)?shù)為: -29.1476exported_pipeline = LinearSVR(C=1.0, dual=False, epsilon=0.0001, loss=”squared_epsilon_insensitive”, tol=0.001)# 修正了導(dǎo)出估計(jì)器中的隨機(jī)狀態(tài)if hasattr(exported_pipeline, ‘random_state’): setattr(exported_pipeline, ‘random_state’, 1)# 模型訓(xùn)練exported_pipeline.fit(X, y)# 對(duì)新數(shù)據(jù)行進(jìn)行預(yù)測(cè)row = [108]yhat = exported_pipeline.predict([row])print(‘Predicted: %.3f’ % yhat[0])
實(shí)戰(zhàn)案例
Pima Indians Diabetes 數(shù)據(jù)集
這里有一個(gè) 案例研究 [7] ,使用 Pima Indians Diabetes 數(shù)據(jù)集預(yù)測(cè) 5 年內(nèi)糖尿病的患病率。根據(jù)這項(xiàng)研究,作者指出在這個(gè)問題上達(dá)到的最大準(zhǔn)確率為 77.47% 。
在同一場(chǎng)景中進(jìn)行自動(dòng)化機(jī)器學(xué)習(xí),看看它是如何使用 TPOT AutoML 工作的。
# import the AutoMLpackage after installing tpot.import tpot# 導(dǎo)入其他必要的包。from pandas import read_csvfrom sklearn.preprocessing import LabelEncoderfrom sklearn.model_selection import StratifiedKFoldfrom tpot import TPOTClassifierimport os# 導(dǎo)入數(shù)據(jù)file_path = ‘./pima-indians-diabetes.data.csv’df = pd.read_csv(file_path,header=None) #可以用你自己的數(shù)據(jù)集.csv文件名替換df.dtypesdf.info()# 將數(shù)據(jù)幀的值拆分為輸入和輸出特征data = df.values X, y = data[:, :-1], data[:, -1] print(X.shape, y.shape) #(768, 8 ) (768,) X = X.astype(‘float32’) y = LabelEncoder().fit_transform(y.astype(‘str’)) #模型評(píng)估定義,這里使用10倍StratifiedKFold cv = StratifiedKFold(n_splits=10) # 定義 TPOTClassifier model = TPOTClassifier(generations=5, population_size=50, cv=cv, score=’accuracy’, verbosity=2, random_state=1, n_jobs=-1) # 執(zhí)行最佳擬合搜索model.fit(X , y) # 導(dǎo)出最佳模型model.export(‘tpot_data.py’)
cv=10 時(shí)的最佳管線選擇
我還用 cv=5 重復(fù)了上述實(shí)驗(yàn)。
# 模型評(píng)估定義,這里使用 5fold StratifiedKFold cv = StratifiedKFold(n_splits=5) # 定義 TPOTClassifier model = TPOTClassifier(generations=5, population_size=50, cv=cv, score=’accuracy’, verbosity=2, random_state=1, n_jobs=-1) # 搜索最佳擬合model.fit(X, y) # 導(dǎo)出最佳模型model.export(‘tpot_data.py’)
cv=5 時(shí)的最佳管線選擇
結(jié)果
使用 10 折交叉驗(yàn)證時(shí)選擇的最佳管道是:
LinearSVC(input_matrix, C=5.0, dual=False, loss=squared_hinge, penalty=l1, tol=0.01)# Accuracy: 77.47%
使用 5 折交叉驗(yàn)證時(shí)選擇的最佳管道是:
XGBClassifier(ExtraTreesClassifier(input_matrix, bootstrap=True, criterion=entropy, max_features=0.55, min_samples_leaf=1, min_samples_split=2, n_estimators=100), learning_rate=0.001, max_depth=10, min_child_weight=13, n_estimators=100, n_jobs=1, subsample=0.9000000000000001, verbosity=0)# Accuracy: 78.39%
TPOT和其他配置
為上述問題嘗試了 TPOT ,它僅使用默認(rèn)配置。其實(shí) AutoML TPOT 還有有許多內(nèi)置配置。下面列出了這些變體:
- TPOT light:如果你希望在管道中使用簡單的運(yùn)算符。此外,此配置確保這些運(yùn)算符也可以快速執(zhí)行。
- TPOT MDR:如果你的問題屬于生物信息學(xué)研究領(lǐng)域,并且此配置非常適合全基因組關(guān)聯(lián)研究。
- TPOT sparse:如果你需要適合稀疏矩陣的配置。
- TPOT NN:如果你想利用默認(rèn) TPOT 的神經(jīng)網(wǎng)絡(luò)估計(jì)器。此外,這些估計(jì)器是用 PyTorch 編寫的。
- TPOT cuML:如果你的數(shù)據(jù)集大小為中型或大型,并且利用 GPU 加速的估計(jì)器在有限的配置上搜索最佳管道。