隨機森林過擬合問題

原文鏈接:https://mljar.com/blog/random-forest-overfitting/

任何機器學習算法都會有一個很常見的問題,就是過擬合問題(overfitting),經常都能看到很多人在問隨機森林會不會出現過擬合問題,在外國的網站看到了這篇文章,覺得寫的很好,所以翻譯轉載在這裏。

提出問題:隨機森林是否會過擬合?

當我第一次看到這個問題時,我有點驚訝,第一個想法是,當然!任何複雜的機器學習算法都會過擬合。我已經訓練了數百個隨機森林(RF)模型,並且多次觀察到它們過擬合。第二個想法是,爲什麼人們會問這樣的問題?我們多做一些研究,在Google了一下之後,我在Leo Breiman(隨機森林算法的創建者)網站上找到了以下段落:

Random forests does not overfit. You can run as many trees as you want.

Breiman原文(在他的文章裏面聲明瞭一點,文章中的RF的模型是通過800Hz的處理器運行的),大意就是說隨機森林不會過擬合,你想跑多少樹就跑多少樹。

聽到這裏,可能大家都覺得不可思議,爲啥隨機森林不會過擬合?我想該算法的開創者是最瞭解的,他比我聰明多了,他肯定是對的。但是,之前我確實已經看到很多次RF過擬合,這就不得不讓我很困惑,所以可以一點點的揭開隨機森林的面紗。

什麼是隨機森林?

隨機森林就是很多棵樹,單科決策樹對數據的變化很敏感,很容易對一些噪聲進行過擬合,所以說只有一棵樹的隨機森林也會出現過擬合,和決策樹是一樣的道理,當我們逐個添加決策樹到隨機森林中時,過擬合的趨勢會減少(由於袋裝(Bagging)和隨機特徵選擇),但是,通常錯誤不會變爲零,加上更多的樹之後,誤差方差將接近零,但偏差不會!這是一個有用的特性,它告訴我們RF中的樹越多越好,也許這就是Breiman在寫關於RF和過擬合的文章時的想法。

更多瞭解隨機森林可以參考:https://www.cnblogs.com/maybe2030/p/4585705.html (寫的很好)

一個隨機森林過擬合的例子(Python)

爲了展示一個隨機森林過擬合的例子,在這裏將使用以下公式生成一個非常簡單的數據:

y = 10 * x + noise

這裏使用從0到1均勻分佈的x,噪聲是平均值和單位方差爲零的正態分佈,加起來得到變量y,下面是我們的數據示例圖。

使用以下代碼可以生成以上的數據並將其拆分爲一個序列和測試子集:

data = np.random.uniform(0, 1,(1000, 1))
noise = np.random.normal(size=(1000,))
X = data[:,:1]
y = 10.0*(data[:,0]) + noise
# split to train and test
X_train, X_test, y_train, y_test = sklearn.model_selection.train_test_split(X, y, test_size=0.4, random_state=2019)

這個RF模型中只有一個輸入變量x和一個輸出變量y,爲了訓練這個模型我使用python中的scikit-learn庫,這裏我會訓練兩個模型,一個是滿樹模型,另一個是由min_samples_leaf超參數控制的修剪模型。訓練滿樹隨機森林的代碼:

rf = RandomForestRegressor(n_estimators=50)
rf.fit(X_train, y_train)
y_train_predicted = rf.predict(X_train)
y_test_predicted_full_trees = rf.predict(X_test)
mse_train = mean_squared_error(y_train, y_train_predicted)
mse_test = mean_squared_error(y_test, y_test_predicted_full_trees)
print("RF with full trees, Train MSE: {} Test MSE: {}".format(mse_train, mse_test))

誤差採用均方誤差,越低越好,結果:

可以看到滿樹的RF模型在訓練數據上得到MSE(均方差):0.20,在測試數據上得到MSE:1.41。

接下來我們用修剪過的樹檢驗一下RF:

rf = RandomForestRegressor(n_estimators=50, min_samples_leaf=25)
rf.fit(X_train, y_train)
y_train_predicted = rf.predict(X_train)
y_test_predicted_pruned_trees = rf.predict(X_test)
mse_train = mean_squared_error(y_train, y_train_predicted)
mse_test = mean_squared_error(y_test, y_test_predicted_pruned_trees)
print("RF with pruned trees, Train MSE: {} Test MSE: {}".format(mse_train, mse_test))

結果:

可以看到,對於修剪過的樹,訓練數據集的MSE結果爲0.91,測試數據集上的MSE爲1.04。

到這裏其實就有明顯的過擬合的證據!滿樹的RF在訓練數據集上的誤差比具有修剪樹的RF小得多,但測試數據上的誤差會比修剪樹的更高——出現了過擬合。我們可以在散點圖上想象一下,左邊是過擬合RF的結果,右邊是修剪後隨機林的結果。

我們看到滿樹的RF過擬合了,可以預測在訓練過程中它學習到的噪聲,修剪過的樹對RF的結果要平滑得多,因此,它的泛化能力更好。

擬合和樹的增長

我們可以檢驗一下隨機森林模型在增加樹的數量時的行爲,我們從1棵樹開始訓練RF模型,並在每個循環迭代中添加1棵樹,在每一步中,我們都會測試訓練數據集和測試數據集上的MSE。

rf = RandomForestRegressor(n_estimators=1)
for iter in range(50):
  rf.fit(X_train, y_train)
  y_train_predicted = rf.predict(X_train)
  y_test_predicted = rf.predict(X_test)
  mse_train = mean_squared_error(y_train, y_train_predicted)
  mse_test = mean_squared_error(y_test, y_test_predicted)
  print("Iteration: {} Train mse: {} Test mse: {}".format(iter, mse_train, mse_test))
  rf.n_estimators += 1

plot繪製結果圖:

顯而易見,可以看到我們在使用滿樹RF的時候,出現了過擬合,但是可以從上面散點圖中看到,過擬合不會根據RF模型中的樹的增加而增加,它隨着更多的樹而趨於穩定。

結論

  • RF算法確實會過擬合。
  • 當算法中加入更多的樹時,隨機林中的泛化誤差方差將減小到零,然而,泛化的偏差並沒有改變。
  • 爲了避免在RF中過擬合,應調整算法的超參數(hyper-parameters),例如,葉子節點中的樣本數。

上文中所有的代碼鏈接:Google Colab

原文地址:https://mljar.com/blog/random-forest-overfitting/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章