1. 程式人生 > 實用技巧 >【機器學習與R語言】13- 如何提高模型的效能?

【機器學習與R語言】13- 如何提高模型的效能?

目錄

1.調整模型引數來提高效能

  • 引數調整:調節模型合適的選項的過程,如股票C5.0決策樹模型中的trials引數,神經網路中的調節節點、隱層數目,SVM中的核函式等等。
  • caret包自動調整引數:train函式,為分類和迴歸的150種不同機器學習模型自動搜尋一個最優的模型。支援的模型及相關可調節引數的詳細資訊可參考:http://topepo.github.io/caret/modelList.html


    自動調整不會遍歷所有引數所有值,只選擇引數可能值的一些子集來構建網格。caret預設對每個引數最多搜尋3個可能值,假設共有p個引數,則有3^p個候選模型將被測試。

1.1 建立簡單的調整模型

最簡單的調整模型只需要通過mehod引數來指定模型的型別。這裡仍以採用決策樹C5.0對信用資料建模為例。

# load the credit dataset
credit <- read.csv("credit.csv")
library(caret)

## Creating a simple tuned model ----
# automated parameter tuning of C5.0 decision tree 
set.seed(300)
m <- train(default ~ ., data = credit, method = "C5.0")

# summary of tuning results
m

計算量比較大,R會重複地生成資料的隨機抽樣,建立決策樹模型,計算效能統計量,並且對結果進行評估。

結果分為4部分:

  • 一是輸入資料的情況;
  • 二是預處理和重抽樣的應用情況:25個自助法抽樣;
  • 三是候選模型評估列表:共12個模型被測試,基於3個引數(model\winno\trials)組合;
  • 四是最佳模型的選擇:圖中紅框內結果。

將最佳模型進行預測:

# apply the best C5.0 candidate model to make predictions
p <- predict(m, credit)
table(p, credit$default)

# obtain predicted classes
head(predict(m, credit, type = "raw"))

# obtain predicted probabilities
head(predict(m, credit, type = "prob"))

有2個被錯誤分類,這只是重新代入誤差,而不是對未來資料效能的度量。上圖中自助法估計的73%才是對未來效能的估計。

2.2 定製調整引數

  • trainControl函式可建立一系列配置選項(控制物件),與train函式一起使用。method引數設定重抽樣的方法。

  • 如使用Kappa優化決策樹的提升(boosting)引數的過程:

①建立配置選項

## Customizing the tuning process ----
# use trainControl() to alter resampling strategy
ctrl <- trainControl(method = "cv",  #重抽樣方法
                    number = 10, #折數目
                    selectionFunction = "oneSE") #oneSE選擇最好效能標準差之內的最簡單的候選者
#預設best,即選擇具有最好的某特定度量值的候選者

②建立組合資料框

#model和winnow保持不變,trials設定8個值
# use expand.grid() to create grid of tuning parameters
grid <- expand.grid(.model = "tree",
                    .trials = c(1, 5, 10, 15, 20, 25, 30, 35),
                    .winnow = FALSE)
# look at the result of expand.grid()
grid


③定製引數訓練

# customize train() with the control list and grid of parameters 
set.seed(300)
m <- train(default ~ ., data = credit, method = "C5.0",
           metric = "Kappa",
           trControl = ctrl,
           tuneGrid = grid)
m

  • 和之前自助法的結果相比需要注意的地方:
    -- 10折交叉驗證的樣本量為900;
    -- 自定義的8個候選模型;
    -- 8個候選模型中雖然trials為35的模型準確度最高,但結果推薦的是trials為5的模型,因為這裡使用了oneSE規則而非之前的best規則來選擇模型。簡單的模型更可取,一是具有更好的計算效能,二是減少過擬合的可能。

2.使用元學習來提高效能

  • 將多個模型合併成一個更強的組。模型互補,而非重疊。
  • 元學習適合對多個模型的預測和要求的結果之間的關係建模。

2.1 整合學習(元學習)概述

  • 元學習也稱整合學習:基於結合多個很弱的學習器來建立一個很強學習器的思路。
  • 整合學習示意圖:


分配函式決定每個模型接受完整的訓練集還是某個抽樣的樣本。
組合函式用來對預測中的不一致進行調節。
堆疊:使用多個模型的預測來訓練一個仲裁模型的過程。

整合學習的好處:

  • 便利性:能節省尋求單一最佳模型的時間,只需要訓練一批表現尚可的候選者,然後整合它們即可。
  • 普適性
  • 提升大量資料或少量資料的效能
  • 將不同領域資料合成
  • 對困難學習任務更細緻的理解

2.2 bagging

  • 自助匯聚法(bagging):最好的整合學習方法之一。bagging對原始訓練集使用自助法抽樣產生多個訓練集,再使用單一的機器學習演算法產生多個模型,然後使用投票(對於分類問題)或平均(對於數值預測)的方法來組合預測值。
  • bagging對不穩定的學習器(隨著資料傳送很小變化產生差別很大的模型),如決策樹具有很好的效果。
## Bagging ----
# Using the ipred bagged decision trees
library(ipred)
set.seed(300)
mybag <- bagging(default ~ ., 
                 data = credit, 
                 nbagg = 25) #用於投票的決策樹的數目,預設25
credit_pred <- predict(mybag, credit)
table(credit_pred, credit$default)


模型訓練得不錯,再通過catet::train函式的10折交叉驗證來建立bagging樹,來評估未來的效能表現。

# estimate performance of ipred bagged trees
library(caret)
set.seed(300)
ctrl <- trainControl(method = "cv", number = 10)
train(default ~ ., data = credit, 
      method = "treebag", #bagging樹函式
      trControl = ctrl)

  • 基於bagging的其他機器學習模型
    caret包中包含了支援向量機svmBag,樸素貝葉斯nbBag,決策樹ctreeBag,神經網路nnetBag等。
  • 以caret包中的svmBag物件為例,提供了fit,pred,aggregate三個函式來建立一個bagging控制物件:
# Using caret's more general bagging function
# create a bag control object using svmBag
str(svmBag)
svmBag$fit

bagctrl <- bagControl(fit = svmBag$fit,
                      predict = svmBag$pred,
                      aggregate = svmBag$aggregate)

# fit the bagged svm model
set.seed(300)
svmbag <- train(default ~ ., data = credit, "bag",
                trControl = ctrl, bagControl = bagctrl)

svmbag

2.3 boosting

  • boosting:另一種基於整合學習的方法,通過增加弱學習器的效能來獲得強學習器的效能。
  • 類似bagging,boosting也是使用不同的重抽樣資料中訓練模型的整合學習,通過投票來決定最終的預測值。不同的是boosting中的重抽樣資料集是專門構建用來產生互補的模型,而且選票不是同等重要,會根據效能進行加權。
  • boosting演算法稱為自適應boosting或AdaBoost,該演算法產生弱分類器來迭代地學習訓練集中很大比例的難以分類的樣本,對經常分錯的樣本進行更多的關注(即給予更大的權重)。
  • boosting原理可用於幾乎任何模型,但最常用於決策樹,詳見:【機器學習與R語言】4-決策樹
  • 程式碼示例:
## Boosting ----

## Using C5.0 Decision Tree (not shown in book)
library(C50)
m_c50_bst <- C5.0(default ~ ., data = credit, trials = 100)

## Using AdaBoost.M1
library(adabag)

# create a Adaboost.M1 model
set.seed(300)
m_adaboost <- boosting(default ~ ., data = credit)
p_adaboost <- predict(m_adaboost, credit)
head(p_adaboost$class)
p_adaboost$confusion

# create and evaluate an Adaboost.M1 model using 10-fold-CV
set.seed(300)
adaboost_cv <- boosting.cv(default ~ ., data = credit)
adaboost_cv$confusion

# calculate kappa
library(vcd)
Kappa(adaboost_cv$confusion)

2.4 隨機森林

  • 隨機森林(決策樹森林):只關注決策樹的整合學習。
  • 將bagging和隨機特徵選擇結合起來,對決策樹模型新增額外的多樣性。在樹的整合(森林)產生之後,該模型使用投票的方法來組合預測結果。
  • 隨機森林特點:

1)訓練隨機森林

演算法說明:

#建立分類器
m=randomForest(train,
          class, #因子變數,訓練集中的每一行的類別
          ntree=500, #指定樹的數目,預設500
          mtry=sqrt(p)) #每次劃分中隨機選擇的特徵數目(預設sqrt(p),p是總特徵數目)

#預測
p=predict(m,test,
        type="response") #response/prob/votes分別為預測類別/預測概率/投票數矩陣

仍然以包含16個特徵的信用資料為例:

## Random Forests ----
# random forest with default settings
library(randomForest)
set.seed(300)
rf <- randomForest(default ~ ., data = credit)
rf


注意這個混淆矩陣不是重代入誤差(前面提到的混淆矩陣),而是出包錯誤率(out-of-bag)(OOB估計錯誤率),它是對測試集合錯誤的一個無偏估計,表示對未來效能的一個合理估計。

在森林構建結束時,每個樣本每次的預測值會被記錄,通過投票來決定該樣本最終的預測值,這種預測的總錯誤率就是出包錯誤率。

2)評估隨機森林效能

randomForest函式得到了caret包的支援,允許在優化模型的同時計算出包錯誤率之外的效能度量指標。

①設定訓練控制選項

library(caret)
ctrl <- trainControl(method = "repeatedcv",
                     number = 10, repeats = 10)

②對隨機森林設定引數調整網格
mtry引數表每一次劃分中要隨機選擇多少特徵。預設sqrt(16)=4個特徵,這裡測試該數的一半,兩倍及所有特徵。

# auto-tune a random forest
grid_rf <- expand.grid(.mtry = c(2, 4, 8, 16))

當隨機森林在每一次劃分中用到所有特徵時,實際上它與bagging決策樹是一樣的。

③train模型

set.seed(300)
m_rf <- train(default ~ ., data = credit, method = "rf",
              metric = "Kappa", trControl = ctrl,
              tuneGrid = grid_rf)
m_rf

以上工作非常耗時!

我們將它的結果與使用10、20、30、40次迭代來與boosting樹進行比較。

# auto-tune a boosted C5.0 decision tree
grid_c50 <- expand.grid(.model = "tree",
                        .trials = c(10, 20, 30, 40),
                        .winnow = "FALSE")

set.seed(300)
m_c50 <- train(default ~ ., data = credit, method = "C5.0",
                metric = "Kappa", trControl = ctrl,
               tuneGrid = grid_c50)
m_c50


結果表明,最好的隨機森林模型比最好的C5.0決策樹模型略勝一籌。