禁止一切形式轉(zhuǎn)載
書接上文
在這個系列的筆記中骤铃,我們正在研究一種受監(jiān)督的回歸機(jī)器學(xué)習(xí)問題寒跳。 使用真實的紐約市建筑能源數(shù)據(jù),我們希望預(yù)測建筑物的能源之星得分并確定影響得分的因素。
機(jī)器學(xué)習(xí)的工作的一般流程
1.數(shù)據(jù)清理和格式化
2.探索性數(shù)據(jù)分析
3.特征工程和特征選擇
4.在性能指標(biāo)上比較幾種機(jī)器學(xué)習(xí)模型
5.對最佳模型執(zhí)行超參數(shù)調(diào)整
6.在測試集合中評估最佳模型
7.解釋模型結(jié)果
8.得出結(jié)論
在Part 1 我們進(jìn)行了1-3悔耘,在Part 2 我們 將進(jìn)行4-6查邢。重申一遍蔗崎,在本系列筆記中,我們更多地關(guān)注實現(xiàn)而不是細(xì)節(jié)扰藕,即機(jī)器學(xué)習(xí)項目的整個流程是什么缓苛,對于那些尋求更多機(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ù)保存到四個.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)練和評估幾種機(jī)器學(xué)習(xí)方法。 目標(biāo)是確定哪個模型最有希望進(jìn)一步開發(fā)(例如超參數(shù)調(diào)整)门躯。
我們使用平均絕對誤差比較模型淆党。 猜測得分中值的基線模型平均偏離25分。
4.1 輸入缺失值
標(biāo)準(zhǔn)機(jī)器學(xué)習(xí)模型無法處理缺失值讶凉,這意味著我們必須找到一種方法來填充這些缺失值或丟棄任何具有缺失值的特征染乌。 由于我們已經(jīng)刪除了第一部分中缺失值超過50%的要素,因此我們將重點關(guān)注這些缺失值懂讯,即稱為插補(bǔ) (imputation)的過程荷憋。 有許多插補(bǔ)方法,但在這里我們將使用相對簡單的方法用列的中位數(shù)替換缺失值褐望。(Here is a more thorough discussion on imputing missing values)
4.2 特征縮放
在我們構(gòu)建模型之前要采取的最后一步是特征縮放(scale the features)勒庄。這是必要的串前,因為要素具有不同的單位,我們希望對要素進(jìn)行標(biāo)準(zhǔn)化实蔽,以使單位不影響算法荡碾。線性回歸和隨機(jī)森林不需要特征縮放(Linear Regression and Random Forest do not require feature scaling),但其他方法(例如支持向量機(jī)和k-最近鄰)確實需要它局装,因為它們考慮了觀測之間的歐氏距離坛吁。因此,在比較多個算法時铐尚,最佳做法是特征縮放拨脉。
有兩種特征縮放的方法( normalization and standardization.):
- 對于每個值,減去特征的平均值并除以特征的標(biāo)準(zhǔn)偏差宣增。這稱為標(biāo)準(zhǔn)化玫膀,并且導(dǎo)致每個特征具有0的均值和1的標(biāo)準(zhǔn)偏差。
- 對于每個值爹脾,減去要素的最小值并除以最大值減去要素的最小值(范圍)帖旨。這可以確保要素的所有值都在0到1之間,并稱為縮放到范圍或標(biāo)準(zhǔn)化誉简。
這是一篇關(guān)于規(guī)范化和標(biāo)準(zhǔn)化的好文章碉就。
與插補(bǔ)一樣,當(dāng)我們訓(xùn)練縮放對象時闷串,我們只想使用訓(xùn)練集瓮钥。當(dāng)我們轉(zhuǎn)換特征時,我們將轉(zhuǎn)換訓(xùn)練集和測試集烹吵。
4.3 要評估的模型
我們將使用偉大的Scikit-Learn庫比較五種不同的機(jī)器學(xué)習(xí)模型:
- 線性回歸
- 支持向量機(jī)回歸
- 隨機(jī)森林回歸
- Gradient Boosting 回歸
- K-Nearest Neighbors回歸
同樣碉熄,在這里,我專注于實現(xiàn)肋拔,而不是解釋這些是如何工作的锈津。 除了Hands-On Machine Learning之外,另一個用于閱讀機(jī)器學(xué)習(xí)模型的優(yōu)秀資源 An Introduction to Statistical Learning
為了比較模型凉蜂,我們將主要使用Scikit-Learn默認(rèn)的模型超參數(shù)值琼梆。 通常這些將表現(xiàn)得很好,但應(yīng)該在實際使用模型之前進(jìn)行優(yōu)化窿吩。 首先茎杂,我們只想確定每個模型的baseline性能,然后我們可以選擇性能最佳的模型纫雁,以便使用超參數(shù)調(diào)整進(jìn)行進(jìn)一步優(yōu)化煌往。 請記住,默認(rèn)的超參數(shù)將啟動并運行模型轧邪,但幾乎總是應(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的最好的一點是所有模型都以相同的方式實現(xiàn):一旦你知道如何構(gòu)建一個模型羞海,你就可以實現(xiàn)一系列極其多樣化的模型。 在這里曲管,我們將在幾行代碼中實現(xiàn)許多模型的整個訓(xùn)練和測試程序却邓。
# 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);
根據(jù)運行情況(每次精確結(jié)果略有變化),梯度增強(qiáng)回歸量表現(xiàn)最佳翘地,其次是隨機(jī)森林申尤。 我不得不承認(rèn)這不是最公平的比較癌幕,因為我們主要使用默認(rèn)的超參數(shù)衙耕。 特別是對于支持向量回歸器,超參數(shù)對性能有重要影響勺远。 (隨機(jī)森林和梯度增強(qiáng)方法非常適合開始橙喘,因為性能較少依賴于模型設(shè)置)。 盡管如此胶逢,從這些結(jié)果中厅瞎,我們可以得出結(jié)論:機(jī)器學(xué)習(xí)是適用的,因為所有模型都明顯優(yōu)于基線初坠!
從這里開始和簸,我將專注于使用超參數(shù)調(diào)優(yōu)來優(yōu)化最佳模型。 鑒于此處的結(jié)果碟刺,我將專注于使用GradientBoostingRegressor锁保。 這是Gradient Boosted Trees的Scikit-Learn實現(xiàn),在過去的幾年中贏得了許多Kaggle competitions半沽。 Scikit-Learn版本通常比XGBoost版本慢爽柒,但在這里我們將堅持使用Scikit-Learn,因為語法更為熟悉者填。 這是在XGBoost包中使用實現(xiàn)的指南Here's a guide浩村。
5. 對最佳模型執(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ù)來控制模型史煎,這些選擇會對模型的最終性能產(chǎn)生顯著影響(盡管通常不會像獲取更多數(shù)據(jù)或工程特征那樣有效)谦屑。
調(diào)整模型超參數(shù)(Tuning the model hyperparameters)可以控制模型中欠擬合與過擬合的平衡驳糯。 我們可以嘗試通過制作更復(fù)雜的模型來校正欠擬合,例如在隨機(jī)森林中使用更多樹或在深度神經(jīng)網(wǎng)絡(luò)中使用更多層氢橙。 當(dāng)我們的模型沒有足夠的容量(自由度)來學(xué)習(xí)特征和目標(biāo)之間的關(guān)系時酝枢,模型會發(fā)生欠擬合并且具有高偏差。 我們可以通過限制模型的復(fù)雜性和應(yīng)用正則化來嘗試糾正過度擬合悍手。 這可能意味著降低多項式回歸的程度帘睦,或?qū)⑺ネ藢犹砑拥缴疃壬窠?jīng)網(wǎng)絡(luò)。 過擬合的模型具有高方差并且實際上記住了訓(xùn)練集坦康。 欠擬合和過擬合導(dǎo)致模型在測試集上的泛化性能變差*竣付。
選擇超參數(shù)的問題在于,沒有放之四海而皆準(zhǔn)的超參數(shù)滞欠。 因此古胆,對于每個新數(shù)據(jù)集,我們必須找到最佳設(shè)置筛璧。 這可能是一個耗時的過程逸绎,但幸運的是,在Scikit-Learn中執(zhí)行此過程有多種選擇夭谤。 更好的是棺牧,新的libraries,如epistasis實驗室的TPOT朗儒,旨在為您自動完成此過程颊乘! 目前,我們將堅持在Scikit-Learn中手動(有點)這樣做采蚀,但請繼續(xù)關(guān)注自動模型選擇的文章疲牵!
5.2 隨機(jī)搜索和交叉驗證的超參數(shù)調(diào)整
我們可以通過隨機(jī)搜索和交叉驗證為模型選擇最佳超參數(shù)。
隨機(jī)搜索是指我們選擇超參數(shù)來評估的方法:我們定義一系列選項榆鼠,然后隨機(jī)選擇要嘗試的組合纲爸。這與網(wǎng)格搜索形成對比,在網(wǎng)格搜索評估妆够,我們指定每個組合识啦。通常,當(dāng)我們對最佳模型超參數(shù)的知識有限時神妹,隨機(jī)搜索會更好颓哮,我們可以使用隨機(jī)搜索縮小選項范圍,然后使用更有限的選項范圍進(jìn)行網(wǎng)格搜索鸵荠。
交叉驗證是用于評估超參數(shù)性能的方法冕茅。我們使用K-Fold交叉驗證,而不是將訓(xùn)練設(shè)置拆分為單獨的訓(xùn)練和驗證集,以減少我們可以使用的訓(xùn)練數(shù)據(jù)量姨伤。這意味著將訓(xùn)練數(shù)據(jù)劃分為K個折疊哨坪,然后進(jìn)行迭代過程,我們首先在折疊的K-1上進(jìn)行訓(xùn)練乍楚,然后評估第K個折疊的性能当编。我們重復(fù)這個過程K次,所以最終我們將測試訓(xùn)練數(shù)據(jù)中的每個例子徒溪,關(guān)鍵是每次迭代我們都在測試我們之前沒有訓(xùn)練過的數(shù)據(jù)忿偷。在K-Fold交叉驗證結(jié)束時,我們將每個K次迭代的平均誤差作為最終性能度量臊泌,然后立即在所有訓(xùn)練數(shù)據(jù)上訓(xùn)練模型鲤桥。然后,我們記錄的性能用于比較超參數(shù)的不同組合缺虐。
A picture of k-fold cross validation using k = 5 is shown below:
在這里芜壁,我們將使用交叉驗證實現(xiàn)隨機(jī)搜索,以選擇gradient boosting regressor的最佳超參數(shù)高氮。 我們首先定義一個網(wǎng)格然后執(zhí)行迭代過程:從網(wǎng)格中隨機(jī)抽樣一組超參數(shù),使用4倍交叉驗證評估超參數(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個不同的超參數(shù)來調(diào)整梯度增強(qiáng)回歸量。 這些都將以不同的方式影響模型窟蓝,這些方法很難提前確定罪裹,找到特定問題的最佳組合的唯一方法是測試它們! 要了解超參數(shù)运挫,我建議您查看(Scikit-Learn documentation)文檔状共。 現(xiàn)在,只要知道我們正在努力尋找超參數(shù)的最佳組合谁帕,并且因為沒有理論告訴我們哪種方法效果最好峡继,我們只需要評估它們,就像運行實驗一樣匈挖!
這部分剩下的內(nèi)容可以去看jupyter notebook, 上面給出了詳細(xì)步驟
6. 在測試集合中評估最佳模型
我們將使用超參數(shù)調(diào)整中的最佳模型來對測試集進(jìn)行預(yù)測碾牌。 請記住,我們的模型之前從未見過測試集儡循,所以這個性能應(yīng)該是模型在現(xiàn)實世界中部署時的表現(xiàn)的一個很好的指標(biāo)舶吗。
最終的模型比基線模型的性能提高了大約10%,但代價是顯著增加了運行時間(在我的機(jī)器上慢了大約12倍)择膝。 機(jī)器學(xué)習(xí)通常是一個權(quán)衡領(lǐng)域:偏差與方差誓琼,準(zhǔn)確性與可解釋性,準(zhǔn)確性與運行時間,以及使用哪種模型的最終決定取決于具體情況腹侣。 這里呵扛,運行時間的增加不是障礙,因為雖然相對差異很大筐带,但訓(xùn)練時間的絕對量值并不顯著今穿。 在不同的情況下,平衡可能不一樣伦籍,因此我們需要考慮我們正在優(yōu)化的內(nèi)容以及我們必須使用的限制蓝晒。
總結(jié)
在個筆記中,我們介紹了機(jī)器學(xué)習(xí)流程中的關(guān)鍵概念:
- 輸入缺失值
- 評估和比較幾種機(jī)器學(xué)習(xí)方法
- 超參數(shù)使用隨機(jī)搜索和交叉驗證來調(diào)整機(jī)器學(xué)習(xí)模型
- 評估測試集上的最佳模型
結(jié)果表明帖鸦,機(jī)器學(xué)習(xí)適用于我們的問題芝薇,最終模型能夠?qū)⒔ㄖ锏哪茉粗堑梅诸A(yù)測到9.1分以內(nèi)。我們還看到作儿,超級參數(shù)調(diào)整能夠改善模型的性能洛二,盡管在投入的時間方面成本相當(dāng)高。這是一個很好的提醒攻锰,正確的特征工程和收集更多數(shù)據(jù)(如果可能A浪弧)比微調(diào)模型有更大的回報。我們還觀察了運行時與精度之間的權(quán)衡娶吞,這是我們在設(shè)計機(jī)器學(xué)習(xí)模型時必須考慮的眾多因素之一垒迂。
我們知道我們的模型是準(zhǔn)確的,但我們知道為什么它能做出預(yù)測妒蛇?機(jī)器學(xué)習(xí)過程的下一步至關(guān)重要:嘗試?yán)斫饽P腿绾芜M(jìn)行預(yù)測机断。實現(xiàn)高精度是很好的,但如果我們能夠找出模型能夠準(zhǔn)確預(yù)測的原因绣夺,那么我們也可以使用這些信息來更好地理解問題吏奸。例如,模型依靠哪些功能來推斷能源之星得分陶耍?可以使用此模型進(jìn)行特征選擇奋蔚,并實現(xiàn)更易于解釋的更簡單模型嗎?
在下一個也是最后一個筆記中物臂,我們將嘗試回答這些問題并從項目中得出最終結(jié)論旺拉!