【R語言進行數據挖掘】決策樹和隨機森林


1、使用包party建立決策樹

這一節學習使用包party里面的函數ctree()為數據集iris建立一個決策樹。屬性Sepal.Length(萼片長度)、Sepal.Width(萼片寬度)、Petal.Length(花瓣長度)以及Petal.Width(花瓣寬度)被用來預測鳶尾花的Species(種類)。在這個包里面,函數ctree()建立了一個決策樹,predict()預測另外一個數據集。
在建立模型之前,iris(鳶尾花)數據集被分為兩個子集:訓練集(70%)和測試集(30%)。使用隨機種子設置固定的隨機數,可以使得隨機選取的數據是可重復利用的。

觀察鳶尾花數據集的結構

str(iris)

設置隨機數起點為1234

set.seed(1234)

使用sample函數抽取樣本,將數據集中觀測值分為兩個子集

ind <- sample(2, nrow(iris), replace=TRUE, prob=c(0.7, 0.3))

樣本的第一部分為訓練集

trainData <- iris[ind==1,]

樣本的第二部分為測試集

testData <- iris[ind==2,]
加載包party建立一個決策樹,並檢測預測見過。函數ctree()提供一些參數例如MinSplit, MinBusket, MaxSurrogate 和 MaxDepth用來控制決策樹的訓練。下面我們將會使用默認的參數設置去建立決策樹,至於具體的參數設置可以通過?party查看函數文檔。下面的代碼中,myFormula公式中的Species(種類)是目標變量,其他變量是獨立變量。
library(party)

符號'~'是連接方程或公式左右兩邊的符號

myFormula <- Species ~ Sepal.Length + Sepal.Width + Petal.Length + Petal.Width

建立決策樹

iris_ctree <- ctree(myFormula, data=trainData)

檢測預測值

table(predict(iris_ctree), trainData$Species)
顯示結果如下:

由上圖可知,setosa(山鳶尾)40觀測值全部正確預測,而versicolor(變色鳶尾)有一個觀測值被誤判為virginica(維吉尼亞鳶尾),virginica(維吉尼亞鳶尾)有3個觀測值被誤判為versicolor(變色鳶尾)。

打印決策樹

print(iris_ctree)
plot(iris_ctree)
plot(iris_ctree, type="simple")

在圖1中,每一個葉子的節點的條形圖都顯示了觀測值落入三個品種的概率。在圖2中,這些概率以每個葉子結點中的y值表示。例如:結點2里面的標簽是“n=40 y=(1,0,0)”,指的是這一類中一共有40個觀測值,並且所有的觀測值的類別都屬於第一類setosa(山鳶尾)。

接下來,需要使用測試集測試決策樹。

在測試集上測試決策樹

testPred <- predict(iris_ctree, newdata = testData)
table(testPred, testData$Species)
結果如下:

從上圖的結果可知,決策樹對變色鳶尾和維吉尼亞鳶尾的識別仍然有誤判。因此ctree()現在的版本並不能很好的處理部分屬性不明確的值,在實例中既有可能被判到左子樹,有時候也會被判到右子樹上。
2、使用包rpart建立決策樹
rpart這個包在本節中被用來在'bodyfat'這個數據集的基礎上建立決策樹。函數raprt()可以建立一個決策樹,並且可以選擇最小誤差的預測。然后利用該決策樹使用predict()預測另外一個數據集。
首先,加載bodyfat這個數據集,並查看它的一些屬性。

data("bodyfat", package = "TH.data")
dim(bodyfat)
attributes(bodyfat)
bodyfat[1:5,]
跟第1節一樣,將數據集分為訓練集和測試集,並根據訓練集建立決策樹。
set.seed(1234)
ind <- sample(2, nrow(bodyfat), replace=TRUE, prob=c(0.7, 0.3))
bodyfat.train <- bodyfat[ind1,]
bodyfat.test <- bodyfat[ind
2,]
library(rpart)

編寫公式myFormula

myFormula <- DEXfat ~ age + waistcirc + hipcirc + elbowbreadth + kneebreadth

訓練決策樹

bodyfat_rpart <- rpart(myFormula, data = bodyfat.train,

  • control = rpart.control(minsplit = 10))

畫決策樹

plot(bodyfat_rpart)

添加文本標簽

text(bodyfat_rpart, use.n=T)
結果如下圖所示:

選擇預測誤差最小值的預測樹,從而優化模型。

opt <- which.min(bodyfat_rpart$cptable[,"xerror"])
cp <- bodyfat_rpart$cptable[opt, "CP"]
bodyfat_prune <- prune(bodyfat_rpart, cp = cp)
plot(bodyfat_rpart)
text(bodyfat_rpart, use.n=T)
優化后的決策樹如下:

對比結果就會發現,優化模型后,就是將hipcirc<99.5這個分層給去掉了,也許是因為這個分層沒有必要,那么大家可以思考一下選擇預測誤差最小的結果的決策樹的分層反而沒有那么細。
之后,優化后的決策樹將會用來預測,預測的結果會與實際的值進行對比。下面的代碼中,使用函數abline()繪制一條斜線。一個好的模型的預測值應該是約接近真實值越好,也就是說大部分的點應該落在斜線上面或者在斜線附近。

根據測試集預測

DEXfat_pred <- predict(bodyfat_prune, newdata=bodyfat.test)

預測值的極值

xlim <- range(bodyfat$DEXfat)
plot(DEXfat_pred ~ DEXfat, data=bodyfat.test, xlab="Observed",

  • ylab="Predicted", ylim=xlim, xlim=xlim)

abline(a=0, b=1)
繪制結果如下:

3、隨機森林
我們使用包randomForest並利用鳶尾花數據建立一個預測模型。包里面的randomForest()函數有兩點不足:第一,它不能處理缺失值,使得用戶必須在使用該函數之前填補這些缺失值;第二,每個分類屬性的最大數量不能超過32個,如果屬性超過32個,那么在使用randomForest()之前那些屬性必須被轉化。
也可以通過另外一個包'cforest'建立隨機森林,並且這個包里面的函數並不受屬性的最大數量約束,盡管如此,高維的分類屬性會使得它在建立隨機森林的時候消耗大量的內存和時間。

ind <- sample(2, nrow(iris), replace=TRUE, prob=c(0.7, 0.3))
trainData <- iris[ind1,]
testData <- iris[ind
2,]
library(randomForest)

Species ~ .指的是Species與其他所有屬性之間的等式

rf <- randomForest(Species ~ ., data=trainData, ntree=100, proximity=TRUE)
table(predict(rf), trainData$Species)
結果如下:

由上圖的結果可知,即使在決策樹中,仍然有誤差,第二類和第三類話仍然會被誤判,可以通過輸入print(rf)知道誤判率為2.88%,也可以通過輸入plot(rf)繪制每一棵樹的誤判率的圖。
最后,在測試集上測試訓練集上建立的隨機森林,並使用table()和margin()函數檢測預測結果。

irisPred <- predict(rf, newdata=testData)
table(irisPred, testData$Species)

繪制每一個觀測值被判斷正確的概率圖

plot(margin(rf, testData$Species))
顯示結果如下:



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM