The Practical Guide to the Random Forests - Random Forests Model Part I
(Using Kaggle’s Titanic Data with R code)
Photo
Source: http://www.greenpeace.org/canada/Global/canada/image/2010/4/teaser/boreal/BOREAL%20FOREST%204.jpg
Previously in this series:
這篇Post是此系列的最後一篇, 我們終於能開始進入Random
Forest這個強大的Ensemble技術領域。在所參考程式碼的Trevor Stephens文章中,尚有多出一篇討論Feature Engineering的post在Random
Forest模型介紹之前, 由於這系列Posts重點在於模型架構的闡釋,
所以, 雖然Feature Engineering在Data
Science分析流程中是一個重要的關鍵 - Feature Engineering的好壞對於模型績效有顯著的影響(feature
engineering has been described as “the most important factor” in determining
the success or failure of the predictive model), 我還是決定將Feature Engineering這一塊用重點條列的型式先行帶過。各位若有興趣,
可以自行參考Trevor Stephens的original post (http://trevorstephens.com/post/73461351896/titanic-getting-started-with-r-part-4-feature)。
Feature Engineering這個Topic, 將另行撰寫Posts討論。Feature Engineering
由於Trevor Stephens原文中Feature Engineering的結果數據,將會被應用於後續的Random Forest模型中,
我仍會將Trevor Stephens完整feature
engineering的Sample code附帶於文章中,並挑選程式碼中相對重要的部份,
進行解說。
test$Survived <- NA
combi <- rbind(train, test)
第二步, 建立3個feature engineering 欄位變數 –
Title, FamilySize 和 Surnamecombi$Title <- sapply(combi$Name, FUN=function(x) {strsplit(x, split='[,.]')[[1]][2]})
…(中間省略)…
table(combi$Title)
combi$FamilySize <<- combi$SibSp + combi$Parch + 1
combi$Surname <- sapply(combi$Name, FUN=function(x) {strsplit(x, split='[,.]')[[1]][1]})
FamilySize 和 Surname 兩個變數是為了產生FamilyID這個新欄位變數; Trevor Stephens想利用Surname和FamilySize兩個欄位,將不同Name的人組成一個Family. 他假定只要Surname和FamilySize都是相同的,應該是同一個Family, 所以給定一個FamilyID 數值.
combi$FamilyID <- paste(as.character(combi$FamilySize), combi$Surname, sep="")
Trevor Stephens設定了一個假設, FamilySize的大小會影響存活率, 因此他檢視了一些資料特性, 並將相關同樣邏輯特性的資料,其FamilyID一律指定成Small
combi$FamilyID[combi$FamilySize <= 2] <- 'Small'
…(中間省略)…
combi$FamilyID[combi$FamilyID %in% famIDs$Var1] <- 'Small'
完成上述處理之後, 我們將切割資料數據回到原本的train和test兩個資料集;完整的程式碼post於下方。train <- read.csv("D:/IDE/R/Titan/train.csv")
test <- read.csv("D:/IDE/R/Titan/test.csv")
test$Survived <- NA
combi <- rbind(train, test)
combi$Name <- as.character(combi$Name)
combi$Title <- sapply(combi$Name, FUN=function(x) {strsplit(x, split='[,.]')[[1]][2]})
combi$Title <- sub(' ', '', combi$Title)
combi$Title[combi$Title %in% c('Mme', 'Mlle')] <- 'Mlle'
combi$Title[combi$Title %in% c('Capt', 'Don', 'Major', 'Sir')] <- 'Sir'
combi$Title[combi$Title %in% c('Dona', 'Lady', 'the Countess', 'Jonkheer')] <- 'Lady'
combi$Title <- factor(combi$Title)
combi$FamilySize <- combi$SibSp + combi$Parch + 1
combi$Surname <- sapply(combi$Name, FUN=function(x) {strsplit(x, split='[,.]')[[1]][1]})
combi$FamilyID <- paste(as.character(combi$FamilySize), combi$Surname, sep="")
combi[combi$Surname=='Johnson',c('Surname','FamilySize','FamilyID','Name')]
combi[combi$Surname=='Appleton',c('Surname','FamilySize','FamilyID','Name')]
combi$FamilyID[combi$FamilySize <= 2] <- 'Small'
table(combi$FamilyID)
famIDs <- data.frame(table(combi$FamilyID))
famIDs <- famIDs[famIDs$Freq <= 2,]
combi$FamilyID[combi$FamilyID %in% famIDs$Var1] <- 'Small'
combi$FamilyID <- factor(combi$FamilyID)
train <- combi[1:891,]
test <- combi[892:1309,]
將資料集合併處理最關鍵的一點是建立R的完整參數factor數據。以FamilyID為例, 在train資料集中, 存在3筆FamilyID =‘3Johnson’的數據, 但是test資料集中完全沒有此項數據。若將兩個資料集分開處理建立FamilyID, test資料集的FamilyID參數的factor將不會有‘3Johnson’這個數值。這樣的狀況會造成在進行數據預測時, R系統會丟出錯誤(throw errors), 因為machine learning的訓練模型和預測的數據其factors不一致。
我們使用新建立的數據來建立CART model:
library(rpart)
fit <- rpart(Survived ~ Pclass + Sex + Age + SibSp + Parch + Fare + Embarked + Title + FamilySize + FamilyID,
data=train, method="class")
library(rattle)
library(rpart.plot)
library(RColorBrewer)
fancyRpartPlot(fit)
從上圖可以發現,新建立的變數基本上主宰(govern)了整個決策樹的分析 – Title和FamilyID兩個欄位分別居於第一和第二個Node位置。從上圖中亦可以發現在上一篇Post中, 所提到Tree Model的selection bias現象: CART模型偏好選擇那些” factors with many levels ”的欄位變數。其中Title變數有11 levels的factor, 而FamliyID高達61 levels。
Bootstrap Aggregation and Bagged Trees
Tree-based模型是一個high variance的演算法;以Titanic data set為例子, 如果我們隨機將將訓練數據(train data set)切分成兩部份, 然後分別訓練建構兩個CART模型, 此兩個CART模型所預測的test data set結果會相當不一樣。這類因為不同的訓練數據(training data set)所造成模型預測結果的差異, 稱之為”variance”. Decision trees為high variance模型, 相對的, 若模型的預測結果, 不會因為不同的訓練數據而大幅度地變化, 則為low variance模型; 線性迴歸(Regression Model)即為一種low variance模型。Bootstrap aggregation, 或簡稱 Bagging,是一種降低vairance的統計學習演算法, 此演算法雖能運用在所有的Machine Learning模型, 但一般是與Tree-based模型結合使用。Bootstrap是一種Resampling技術。一般Resampling技術是用來建立更多的樣本(samples) for模型的建構與測試, 在之後另外一篇文章, 將會介紹其他Resampling技術, 以及如何使用Resampling技術, 進行模型的建立與調效(tuning).
我們可以圖示化Bootstrap技術如下:
Bootstrap Sample是從資料集中隨機抽取的樣本資料集, 此抽樣方法的特點整理如下:
ü 隨機抽取的樣本資料是with replacement, 也就是抽取出來的資料會再放回資料集中, 供下一次的隨機抽取
ü
樣本的數據大小(sample size)與原始資料集是一樣的
ü
有些樣本資料會被選取很多次; 相對地,
有些數據則完全不會被選到
ü
那些沒有被選到的樣本資料集, 我們稱之為”out-of-bag”
samples. 從上圖可以看出, 每一次的Bootstrap Resampling, 演算法會依據所選取出來的samples建立模型,
然後用”out-of-bag” samples進行模型預測(predict)
ü
平均來說, 原始資料中,
約63.2%的數據至少會被選取到一次。如果訓練資料集數據太小, Bootstrap技術將會產生high
bias的問題; 此問題將可以隨著訓練數據的增加而降低。
大約在90年代中期, Ensemble techniques, 這種合併多項預測模型的技術開始出現。Bootstrap aggregation(簡稱Bagging)為這項技術的濫觴之一; Bagging由Leo Breiman所提出, 是最早開發出來的Ensemble techniques (Breiman
ü
For
regression: 將m個預測數值平均
ü
For
classification: 使用投票(votes)的比率決定預測類別
Bagging模型擁有3項優勢:
1.
首先, Bagging 可以非常有效率地透過” aggregation
process”, 降低預測結果的變異性(the variance of a prediction)。因此對於Decision Trees這類會產生不穩定預測數據的模型, 彙聚多種版本訓練資料建立的模型所產生的預測結果, 能夠確實地降低預測的變化波動,
產生更為穩定的預測數值。
2.
由於Bagging的預測數值為平均多個獨立Decision Trees模型的預測數據,此方法不僅擁有low
variance的預測結果, 相對地也增進了模型的預測績效(predictive performance)。
3.
第3項Bagging優勢為,
此模型提供了”內部估算預測績效”(internal estimate of
predictive performance)。此預測績效數據可以讓我們”推測” cross-validation
estimates或是test set預估績效。[內部估算預測績效]的來源是上文提過的”out-of-bag”
samples. Out-of-bag樣本是在該次bootstrap訓練模型時,
沒有被取樣的數據, 因此針對Out-of-bag樣本,就可以計算出該次模型對於未知資料的預測績效值, 我們稱此數值為”out-of-bag estimate”; 彙整並平均每次bootstrap的模型的預測績效,
我們就能量測出整個ensemble模型的預測能力。這是因為通常,
out-of-bag estimate 和cross-validation estimates或test
set estimates具有一定的相關聯性。
除了上述優點, Bagging模型同樣具有下列2項缺點:
1.
隨著bootstrap樣本數量增加,
電腦運算成本與記憶體需求也同步地向上增加。然而, 此系統效能問題可以藉由平行運算(parallel computing)架構改善,
因為Bagging流程能很容易地進行平行處理。讓我們回想一下Bagging的架構:
每一個bootstrap樣本數據各自對應其模型訓練; 也就是說,
每一個model是完全獨立, 可以分開建構的;
我們所有做的是在最後一個流程階段, 將所有模型預測進行彙整即可。
2.
Bagged
model另外一個劣勢, 在於其模型的解釋程度下降(less interpretable)。 然而我們依然可以透過合併多個單一模型的變數評測數據, 建立數據的變數重要性數值(measures of variable
importance)。
Random Forests模型 Part I 先在此做一個結束; 下一個Part將會解說Random Forests Model, 並運用此演算法對Titanic 資料集進行分類預測。
by J.D.
7/24/2016
|
標籤:
Kaggle,
Machine Learning,
R
|