適合練手的完整機(jī)器學(xué)習(xí)項(xiàng)目-Part 2

禁止一切形式轉(zhuǎn)載

書接上文

在這個(gè)系列的筆記中,我們正在研究一種受監(jiān)督的回歸機(jī)器學(xué)習(xí)問題。 使用真實(shí)的紐約市建筑能源數(shù)據(jù),我們希望預(yù)測(cè)建筑物的能源之星得分并確定影響得分的因素。

機(jī)器學(xué)習(xí)的工作的一般流程

1.數(shù)據(jù)清理和格式化
2.探索性數(shù)據(jù)分析
3.特征工程和特征選擇
4.在性能指標(biāo)上比較幾種機(jī)器學(xué)習(xí)模型
5.對(duì)最佳模型執(zhí)行超參數(shù)調(diào)整
6.在測(cè)試集合中評(píng)估最佳模型
7.解釋模型結(jié)果
8.得出結(jié)論

在Part 1 我們進(jìn)行了1-3,在Part 2 我們 將進(jìn)行4-6。重申一遍,在本系列筆記中,我們更多地關(guān)注實(shí)現(xiàn)而不是細(xì)節(jié),即機(jī)器學(xué)習(xí)項(xiàng)目的整個(gè)流程是什么,對(duì)于那些尋求更多機(jī)器學(xué)習(xí)方法背景的人,我推薦 Hands-On Machine Learning with Scikit-Learn and Tensorflow by Aurelien Geron。 這是算法背后的基本理論以及如何在Python中有效使用它們的優(yōu)秀資源!

讀取數(shù)據(jù)

在Part 1 最后,我們已經(jīng)將處理好的數(shù)據(jù)保存到四個(gè).csv文件中:
training_features.csv
testing_features.csv
training_labels.csv
testing_labels.csv
使用如下代碼讀取數(shù)據(jù):

train_features = pd.read_csv('data/training_features.csv')
test_features = pd.read_csv('data/testing_features.csv')
train_labels = pd.read_csv('data/training_labels.csv')
test_labels = pd.read_csv('data/testing_labels.csv')
# Display sizes of data
print('Training Feature Size: ', train_features.shape)
print('Testing Feature Size:  ', test_features.shape)
print('Training Labels Size:  ', train_labels.shape)
print('Testing Labels Size:   ', test_labels.shape)

Training Feature Size: (6622, 64)
Testing Feature Size: (2839, 64)
Training Labels Size: (6622, 1)
Testing Labels Size: (2839, 1)

4. 在性能指標(biāo)上比較幾種機(jī)器學(xué)習(xí)模型

在本節(jié)中,我們將為我們的監(jiān)督回歸任務(wù)構(gòu)建,訓(xùn)練和評(píng)估幾種機(jī)器學(xué)習(xí)方法。 目標(biāo)是確定哪個(gè)模型最有希望進(jìn)一步開發(fā)(例如超參數(shù)調(diào)整)。
我們使用平均絕對(duì)誤差比較模型。 猜測(cè)得分中值的基線模型平均偏離25分。

4.1 輸入缺失值

標(biāo)準(zhǔn)機(jī)器學(xué)習(xí)模型無法處理缺失值,這意味著我們必須找到一種方法來填充這些缺失值或丟棄任何具有缺失值的特征。 由于我們已經(jīng)刪除了第一部分中缺失值超過50%的要素,因此我們將重點(diǎn)關(guān)注這些缺失值,即稱為插補(bǔ) (imputation)的過程。 有許多插補(bǔ)方法,但在這里我們將使用相對(duì)簡(jiǎn)單的方法用列的中位數(shù)替換缺失值。(Here is a more thorough discussion on imputing missing values)

4.2 特征縮放

在我們構(gòu)建模型之前要采取的最后一步是特征縮放(scale the features)。這是必要的,因?yàn)橐鼐哂胁煌膯挝?,我們希望?duì)要素進(jìn)行標(biāo)準(zhǔn)化,以使單位不影響算法。線性回歸和隨機(jī)森林不需要特征縮放(Linear Regression and Random Forest do not require feature scaling),但其他方法(例如支持向量機(jī)和k-最近鄰)確實(shí)需要它,因?yàn)樗鼈兛紤]了觀測(cè)之間的歐氏距離。因此,在比較多個(gè)算法時(shí),最佳做法是特征縮放。
有兩種特征縮放的方法( normalization and standardization.):

  • 對(duì)于每個(gè)值,減去特征的平均值并除以特征的標(biāo)準(zhǔn)偏差。這稱為標(biāo)準(zhǔn)化,并且導(dǎo)致每個(gè)特征具有0的均值和1的標(biāo)準(zhǔn)偏差。
  • 對(duì)于每個(gè)值,減去要素的最小值并除以最大值減去要素的最小值(范圍)。這可以確保要素的所有值都在0到1之間,并稱為縮放到范圍或標(biāo)準(zhǔn)化。
    這是一篇關(guān)于規(guī)范化和標(biāo)準(zhǔn)化的好文章。
    與插補(bǔ)一樣,當(dāng)我們訓(xùn)練縮放對(duì)象時(shí),我們只想使用訓(xùn)練集。當(dāng)我們轉(zhuǎn)換特征時(shí),我們將轉(zhuǎn)換訓(xùn)練集和測(cè)試集。
4.3 要評(píng)估的模型

我們將使用偉大的Scikit-Learn庫比較五種不同的機(jī)器學(xué)習(xí)模型:

  • 線性回歸
  • 支持向量機(jī)回歸
  • 隨機(jī)森林回歸
  • Gradient Boosting 回歸
  • K-Nearest Neighbors回歸

同樣,在這里,我專注于實(shí)現(xiàn),而不是解釋這些是如何工作的。 除了Hands-On Machine Learning之外,另一個(gè)用于閱讀機(jī)器學(xué)習(xí)模型的優(yōu)秀資源 An Introduction to Statistical Learning
為了比較模型,我們將主要使用Scikit-Learn默認(rèn)的模型超參數(shù)值。 通常這些將表現(xiàn)得很好,但應(yīng)該在實(shí)際使用模型之前進(jìn)行優(yōu)化。 首先,我們只想確定每個(gè)模型的baseline性能,然后我們可以選擇性能最佳的模型,以便使用超參數(shù)調(diào)整進(jìn)行進(jìn)一步優(yōu)化。 請(qǐng)記住,默認(rèn)的超參數(shù)將啟動(dòng)并運(yùn)行模型,但幾乎總是應(yīng)該使用某種搜索來調(diào)整以找到問題的最佳設(shè)置!

Here is what the Scikit-learn documentation says about the defaults:

__Sensible defaults__: Whenever an operation requires a user-defined parameter,
an appropriate default value is defined by the library. The default value
should cause the operation to be performed in a sensible way (giving a baseline
solution for the task at hand.)

關(guān)于scikit-learn的最好的一點(diǎn)是所有模型都以相同的方式實(shí)現(xiàn):一旦你知道如何構(gòu)建一個(gè)模型,你就可以實(shí)現(xiàn)一系列極其多樣化的模型。 在這里,我們將在幾行代碼中實(shí)現(xiàn)許多模型的整個(gè)訓(xùn)練和測(cè)試程序。

# Function to calculate mean absolute error
def mae(y_true, y_pred):
    return np.mean(abs(y_true - y_pred))
# Takes in a model, trains the model, and evaluates the model on the test set
def fit_and_evaluate(model):
    # Train the model
    model.fit(X, y)
    # Make predictions and evalute
    model_pred = model.predict(X_test)
    model_mae = mae(y_test, model_pred)
    # Return the performance metric
    return model_mae
4.3.1 線性回歸
lr = LinearRegression()
lr_mae = fit_and_evaluate(lr)

print('Linear Regression Performance on the test set: MAE = %0.4f' % lr_mae)
4.3.2 支持向量機(jī)
svm = SVR(C = 1000, gamma = 0.1)
svm_mae = fit_and_evaluate(svm)

print('Support Vector Machine Regression Performance on the test set: MAE = %0.4f' % svm_mae)
4.3.3 隨機(jī)森林
random_forest = RandomForestRegressor(random_state=60)
random_forest_mae = fit_and_evaluate(random_forest)

print('Random Forest Regression Performance on the test set: MAE = %0.4f' % random_forest_mae)
4.3.4 Gradient Boosting Regression
gradient_boosted = GradientBoostingRegressor(random_state=60)
gradient_boosted_mae = fit_and_evaluate(gradient_boosted)

print('Gradient Boosted Regression Performance on the test set: MAE = %0.4f' % gradient_boosted_mae)
4.3.5 K-Nearest Neighbors Regression
knn = KNeighborsRegressor(n_neighbors=10)
knn_mae = fit_and_evaluate(knn)

print('K-Nearest Neighbors Regression Performance on the test set: MAE = %0.4f' % knn_mae)
4.4 模型比較
plt.style.use('fivethirtyeight')
figsize(8, 6)

# Dataframe to hold the results
model_comparison = pd.DataFrame({'model': ['Linear Regression', 'Support Vector Machine',
                                           'Random Forest', 'Gradient Boosted',
                                            'K-Nearest Neighbors'],
                                 'mae': [lr_mae, svm_mae, random_forest_mae, 
                                         gradient_boosted_mae, knn_mae]})

# Horizontal bar chart of test mae
model_comparison.sort_values('mae', ascending = False).plot(x = 'model', y = 'mae', kind = 'barh',
                                                           color = 'red', edgecolor = 'black')

# Plot formatting
plt.ylabel(''); plt.yticks(size = 14); plt.xlabel('Mean Absolute Error'); plt.xticks(size = 14)
plt.title('Model Comparison on Test MAE', size = 20);

image.png

根據(jù)運(yùn)行情況(每次精確結(jié)果略有變化),梯度增強(qiáng)回歸量表現(xiàn)最佳,其次是隨機(jī)森林。 我不得不承認(rèn)這不是最公平的比較,因?yàn)槲覀冎饕褂媚J(rèn)的超參數(shù)。 特別是對(duì)于支持向量回歸器,超參數(shù)對(duì)性能有重要影響。 (隨機(jī)森林和梯度增強(qiáng)方法非常適合開始,因?yàn)樾阅茌^少依賴于模型設(shè)置)。 盡管如此,從這些結(jié)果中,我們可以得出結(jié)論:機(jī)器學(xué)習(xí)是適用的,因?yàn)樗心P投济黠@優(yōu)于基線!

從這里開始,我將專注于使用超參數(shù)調(diào)優(yōu)來優(yōu)化最佳模型。 鑒于此處的結(jié)果,我將專注于使用GradientBoostingRegressor。 這是Gradient Boosted Trees的Scikit-Learn實(shí)現(xiàn),在過去的幾年中贏得了許多Kaggle competitions。 Scikit-Learn版本通常比XGBoost版本慢,但在這里我們將堅(jiān)持使用Scikit-Learn,因?yàn)檎Z法更為熟悉。 這是在XGBoost包中使用實(shí)現(xiàn)的指南Here's a guide。

5. 對(duì)最佳模型執(zhí)行超參數(shù)調(diào)整--Model Optimization

在機(jī)器學(xué)習(xí)中,優(yōu)化模型意味著為特定問題找到最佳的超參數(shù)集

5.1 Hyperparameters

首先,我們需要了解與模型參數(shù)相比,模型超參數(shù)是如何定義的:

  • 模型超參數(shù)被認(rèn)為最好通過機(jī)器學(xué)習(xí)算法來進(jìn)行設(shè)置,在訓(xùn)練之前由數(shù)據(jù)科學(xué)家調(diào)整。 例如,隨機(jī)森林中的樹木數(shù)量,或者K-Nearest Neighbors Regression中使用的鄰居數(shù)量。
  • 模型參數(shù)是模型在訓(xùn)練期間學(xué)習(xí)的內(nèi)容,例如線性回歸中的權(quán)重。

我們作為數(shù)據(jù)科學(xué)家通過選擇超參數(shù)來控制模型,這些選擇會(huì)對(duì)模型的最終性能產(chǎn)生顯著影響(盡管通常不會(huì)像獲取更多數(shù)據(jù)或工程特征那樣有效)。

調(diào)整模型超參數(shù)(Tuning the model hyperparameters)可以控制模型中欠擬合與過擬合的平衡。 我們可以嘗試通過制作更復(fù)雜的模型來校正欠擬合,例如在隨機(jī)森林中使用更多樹或在深度神經(jīng)網(wǎng)絡(luò)中使用更多層。 當(dāng)我們的模型沒有足夠的容量(自由度)來學(xué)習(xí)特征和目標(biāo)之間的關(guān)系時(shí),模型會(huì)發(fā)生欠擬合并且具有高偏差。 我們可以通過限制模型的復(fù)雜性和應(yīng)用正則化來嘗試糾正過度擬合。 這可能意味著降低多項(xiàng)式回歸的程度,或?qū)⑺ネ藢犹砑拥缴疃壬窠?jīng)網(wǎng)絡(luò)。 過擬合的模型具有高方差并且實(shí)際上記住了訓(xùn)練集。 欠擬合和過擬合導(dǎo)致模型在測(cè)試集上的泛化性能變差*。

選擇超參數(shù)的問題在于,沒有放之四海而皆準(zhǔn)的超參數(shù)。 因此,對(duì)于每個(gè)新數(shù)據(jù)集,我們必須找到最佳設(shè)置。 這可能是一個(gè)耗時(shí)的過程,但幸運(yùn)的是,在Scikit-Learn中執(zhí)行此過程有多種選擇。 更好的是,新的libraries,如epistasis實(shí)驗(yàn)室的TPOT,旨在為您自動(dòng)完成此過程! 目前,我們將堅(jiān)持在Scikit-Learn中手動(dòng)(有點(diǎn))這樣做,但請(qǐng)繼續(xù)關(guān)注自動(dòng)模型選擇的文章!

5.2 隨機(jī)搜索和交叉驗(yàn)證的超參數(shù)調(diào)整

我們可以通過隨機(jī)搜索和交叉驗(yàn)證為模型選擇最佳超參數(shù)。

  • 隨機(jī)搜索是指我們選擇超參數(shù)來評(píng)估的方法:我們定義一系列選項(xiàng),然后隨機(jī)選擇要嘗試的組合。這與網(wǎng)格搜索形成對(duì)比,在網(wǎng)格搜索評(píng)估,我們指定每個(gè)組合。通常,當(dāng)我們對(duì)最佳模型超參數(shù)的知識(shí)有限時(shí),隨機(jī)搜索會(huì)更好,我們可以使用隨機(jī)搜索縮小選項(xiàng)范圍,然后使用更有限的選項(xiàng)范圍進(jìn)行網(wǎng)格搜索。

  • 交叉驗(yàn)證是用于評(píng)估超參數(shù)性能的方法。我們使用K-Fold交叉驗(yàn)證,而不是將訓(xùn)練設(shè)置拆分為單獨(dú)的訓(xùn)練和驗(yàn)證集,以減少我們可以使用的訓(xùn)練數(shù)據(jù)量。這意味著將訓(xùn)練數(shù)據(jù)劃分為K個(gè)折疊,然后進(jìn)行迭代過程,我們首先在折疊的K-1上進(jìn)行訓(xùn)練,然后評(píng)估第K個(gè)折疊的性能。我們重復(fù)這個(gè)過程K次,所以最終我們將測(cè)試訓(xùn)練數(shù)據(jù)中的每個(gè)例子,關(guān)鍵是每次迭代我們都在測(cè)試我們之前沒有訓(xùn)練過的數(shù)據(jù)。在K-Fold交叉驗(yàn)證結(jié)束時(shí),我們將每個(gè)K次迭代的平均誤差作為最終性能度量,然后立即在所有訓(xùn)練數(shù)據(jù)上訓(xùn)練模型。然后,我們記錄的性能用于比較超參數(shù)的不同組合。

A picture of k-fold cross validation using k = 5 is shown below:
image.png

在這里,我們將使用交叉驗(yàn)證實(shí)現(xiàn)隨機(jī)搜索,以選擇gradient boosting regressor的最佳超參數(shù)。 我們首先定義一個(gè)網(wǎng)格然后執(zhí)行迭代過程:從網(wǎng)格中隨機(jī)抽樣一組超參數(shù),使用4倍交叉驗(yàn)證評(píng)估超參數(shù),然后選擇具有最佳性能的超參數(shù)。
Loss function to be optimized
Number of trees used in the boosting process
Maximum depth of each tree
Minimum number of samples per leaf
Minimum number of samples to split a node
Maximum number of features to consider for making splits
我們選擇了6個(gè)不同的超參數(shù)來調(diào)整梯度增強(qiáng)回歸量。 這些都將以不同的方式影響模型,這些方法很難提前確定,找到特定問題的最佳組合的唯一方法是測(cè)試它們! 要了解超參數(shù),我建議您查看(Scikit-Learn documentation)文檔。 現(xiàn)在,只要知道我們正在努力尋找超參數(shù)的最佳組合,并且因?yàn)闆]有理論告訴我們哪種方法效果最好,我們只需要評(píng)估它們,就像運(yùn)行實(shí)驗(yàn)一樣!
這部分剩下的內(nèi)容可以去看jupyter notebook, 上面給出了詳細(xì)步驟

6. 在測(cè)試集合中評(píng)估最佳模型

我們將使用超參數(shù)調(diào)整中的最佳模型來對(duì)測(cè)試集進(jìn)行預(yù)測(cè)。 請(qǐng)記住,我們的模型之前從未見過測(cè)試集,所以這個(gè)性能應(yīng)該是模型在現(xiàn)實(shí)世界中部署時(shí)的表現(xiàn)的一個(gè)很好的指標(biāo)。

最終的模型比基線模型的性能提高了大約10%,但代價(jià)是顯著增加了運(yùn)行時(shí)間(在我的機(jī)器上慢了大約12倍)。 機(jī)器學(xué)習(xí)通常是一個(gè)權(quán)衡領(lǐng)域:偏差與方差,準(zhǔn)確性與可解釋性,準(zhǔn)確性與運(yùn)行時(shí)間,以及使用哪種模型的最終決定取決于具體情況。 這里,運(yùn)行時(shí)間的增加不是障礙,因?yàn)殡m然相對(duì)差異很大,但訓(xùn)練時(shí)間的絕對(duì)量值并不顯著。 在不同的情況下,平衡可能不一樣,因此我們需要考慮我們正在優(yōu)化的內(nèi)容以及我們必須使用的限制。

總結(jié)

在個(gè)筆記中,我們介紹了機(jī)器學(xué)習(xí)流程中的關(guān)鍵概念:

  • 輸入缺失值
  • 評(píng)估和比較幾種機(jī)器學(xué)習(xí)方法
  • 超參數(shù)使用隨機(jī)搜索和交叉驗(yàn)證來調(diào)整機(jī)器學(xué)習(xí)模型
  • 評(píng)估測(cè)試集上的最佳模型

結(jié)果表明,機(jī)器學(xué)習(xí)適用于我們的問題,最終模型能夠?qū)⒔ㄖ锏哪茉粗堑梅诸A(yù)測(cè)到9.1分以內(nèi)。我們還看到,超級(jí)參數(shù)調(diào)整能夠改善模型的性能,盡管在投入的時(shí)間方面成本相當(dāng)高。這是一個(gè)很好的提醒,正確的特征工程和收集更多數(shù)據(jù)(如果可能?。┍任⒄{(diào)模型有更大的回報(bào)。我們還觀察了運(yùn)行時(shí)與精度之間的權(quán)衡,這是我們?cè)谠O(shè)計(jì)機(jī)器學(xué)習(xí)模型時(shí)必須考慮的眾多因素之一。

我們知道我們的模型是準(zhǔn)確的,但我們知道為什么它能做出預(yù)測(cè)?機(jī)器學(xué)習(xí)過程的下一步至關(guān)重要:嘗試?yán)斫饽P腿绾芜M(jìn)行預(yù)測(cè)。實(shí)現(xiàn)高精度是很好的,但如果我們能夠找出模型能夠準(zhǔn)確預(yù)測(cè)的原因,那么我們也可以使用這些信息來更好地理解問題。例如,模型依靠哪些功能來推斷能源之星得分?可以使用此模型進(jìn)行特征選擇,并實(shí)現(xiàn)更易于解釋的更簡(jiǎn)單模型嗎?

在下一個(gè)也是最后一個(gè)筆記中,我們將嘗試回答這些問題并從項(xiàng)目中得出最終結(jié)論!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容