初始R語言——決策樹

初始R語言——決策樹

決策樹是機器學習裏很重要的分類算法, 網上也有很多博客進行細緻地講解,這裏就不再敘述原理,而是直接運用 R 語言的程序包來進行數據處理。

數據描述

本文使用的數據是對乳腺癌腫瘤良性還是惡性的分類,使用 Breast Cancer Wisconsin (Original) Data Set 數據集。簡單描述一下,數據集共有 699 個樣本, 根據乳腺癌腫瘤的厚度,細胞大小,細胞形狀,附着能力,上皮組織細胞特性,細胞核,染色質以及有絲分裂的特性,來對細胞的良性與惡性進行分類。其中 label 是最後的 class 列(2 代表良性,4 代表惡性),而其他特徵值都處於 1-10 之間。

函數包介紹

R 語言中有兩個不同的函數包可以進行決策樹的生成, 分別是 rpart 和 party。 兩者的不同在“R語言中的tree和rpart有什麼區別”中有詳細的解釋,比較重要的一點在於,rpart 包通過rpart.control 有不同的方式來決定何時結束分裂,比如 minsplit,代表最小分支節點數,也就是需要劃分的樣本數小於一定數值後,就不再進行分裂。rpart 包是可以通過剪枝(prune)來改善過擬合的。而 party 是不需要進行剪枝的。

party包代碼

# 導入數據
dat <- read.csv("breast-cancer-wisconsin.data")
# 定義列名
names(dat) <- c("id", "clump_thickness", "uniformity_of_cell_size", "uniformity_of_cell_shape",
"marginal_adhesion", "single_epithelial_cell_size", "bare_nuclei", "bland_chromatin",
"normal_necleoli", "mitoses", "class")
# 將class作爲分類變量
dat$class <- as.factor(dat$class)
head(dat)


# 拆分訓練集和測試集 
# 按照 7:3 的比例劃分數據
ind <- sample(2, nrow(dat), replace=TRUE, prob=c(0.7,0.3))
trainData <- dat[ind==1,]
testData <- dat[ind==2,]

library(party)
myFormula <- class ~ clump_thickness + uniformity_of_cell_size + uniformity_of_cell_shape + marginal_adhesion + single_epithelial_cell_size + bare_nuclei + bland_chromatin + normal_necleoli + mitoses
dat_tree <- ctree(myFormula, data=trainData)

plot(dat_tree,type="simple")

trainPredict = predict(dat_tree,trainData)
# 使用 table 來簡單直觀的評估效果
table(trainPredict,trainData$class)
testPredict <- predict(dat_tree,testData)
table(testPredict,testData$class)

我們可以來看一下這個決策樹的樣子:


這裏寫圖片描述

我們同樣可以用文字來對這個樹進行描述:


這裏寫圖片描述

rpart函數包

# 使用 rpart 程序包來生成樹
library(rpart)
myFormula <- class ~ clump_thickness + uniformity_of_cell_size + uniformity_of_cell_shape + marginal_adhesion + single_epithelial_cell_size + bare_nuclei + bland_chromatin + normal_necleoli + mitoses
# 使用rpart來生成決策樹,minsplit=10 說明小於10不再分類
dat_rpart <- rpart(myFormula, data=trainData, control = rpart.control(minsplit = 10))

# 使用得到的決策樹進行測試
trainPredict <- predict(dat_rpart,trainData,type="class")
table(trainPredict,trainData$class)
testPredict <- predict(dat_rpart,testData,type="class")
table(testPredict,testData$class)

# 畫圖
plot(dat_rpart,branch=0, margin=0.1,uniform=TRUE);text(dat_rpart,use.n=T,all=TRUE)

# 剪枝
opt <- which.min(dat_rpart$cptable[,"xerror"])
cp <- dat_rpart$cptable[opt,"CP"]
dat_prune <- prune(dat_rpart, cp=cp)

trainPrunePredict <- predict(dat_prune,trainData,type="class")
table(trainPrunePredict,trainData$class)
testPrunePredict <- predict(dat_prune,testData,type="class")
table(testPrunePredict,testData$class)

這裏對剪枝進行下解釋,我們知道當一個決策樹很複雜,會出現過擬合現象。複雜性是由這個 cp(complexity parameter)參數來衡量,其中 xerror 參數體現的就是過擬合。複雜度越高,cp值就越小。過擬合程度越高,xerror值也越小。而這裏剪去的 cp 是 xerror 參數最小的那一個,即對過擬合影響最大的那一個。但是我們又要儘量保證複雜度不要太低,以保證準確性。

看一下這個樹的樣子:


這裏寫圖片描述

以及代碼描述:


這裏寫圖片描述

隨機森林

R 語言中隨機森林是使用 randomForest 程序包進行實現的:

library(randomForest)
# 因爲隨機森林不像決策樹一樣固定,所以class~後面不是固定的
# ntree 的數量是 100
rf <- randomForest(class~., data=trainData,ntree=100,proximity=TRUE)
rfTrainPredict <- predict(rf,trainData,type="class")
table(rfTrainPredict,trainData$class)
rfTestPredict <- predict(rf,testData,type="class")
table(rfTestPredict,testData$class)

結果分析

因爲使用的是隨機劃分數據集和訓練集並且沒有使用seed,所以每次結果會有所出入。
這裏使用 table 來觀察結果,顯示分錯與分對的個數。


這裏寫圖片描述
party包得到結果


這裏寫圖片描述
rpart包未剪枝結果

未剪枝情況下 rpart 不如 party 準確。

這裏寫圖片描述
rpart剪枝後結果

對比下剪枝前後效果,訓練集的誤差會有所增大,測試集總數沒有發生變化但是誤差更加平均。
但是很多時候剪枝前後結果是完全一樣的,這是不是說明該數據本身已經有很強的可分性了呢?

最後是隨機森林,按照經驗來說肯定會優於前兩個。


這裏寫圖片描述

果然,孤木難支,森林的力量還是令人畏懼的。

總結

最近在學習R語言,練習運用已有的程序包來實現一些最基本的機器學習算法。很多函數也是看了很多博客論壇慢慢實踐摸索出來的,可能會有所紕漏也會有理解錯誤的地方,還望指正。

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