El Bosque aleatorio es un algoritmo de aprendizaje que combina el resultado de múltiples arboles de decision para llegar a un resultado optimo.
En esta base de datos tenemos los precios de mas de 13,000 casas de la ciudad de Melbourne:
#install.packages("rpart")
library(rpart)
#install.packages("rpart.plot")
library(rpart.plot)
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.4 ✔ readr 2.1.5
## ✔ forcats 1.0.0 ✔ stringr 1.5.1
## ✔ ggplot2 3.5.2 ✔ tibble 3.3.0
## ✔ lubridate 1.9.4 ✔ tidyr 1.3.1
## ✔ purrr 1.1.0
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(modelr)
library(randomForest)
## randomForest 4.7-1.2
## Type rfNews() to see new features/changes/bug fixes.
##
## Adjuntando el paquete: 'randomForest'
##
## The following object is masked from 'package:dplyr':
##
## combine
##
## The following object is masked from 'package:ggplot2':
##
## margin
library(caret)
## Cargando paquete requerido: lattice
##
## Adjuntando el paquete: 'caret'
##
## The following object is masked from 'package:purrr':
##
## lift
df <- read.csv("D:\\Anton V2\\Downloads\\melbourne.csv")
summary(df)
## Suburb Address Rooms Type
## Length:13580 Length:13580 Min. : 1.000 Length:13580
## Class :character Class :character 1st Qu.: 2.000 Class :character
## Mode :character Mode :character Median : 3.000 Mode :character
## Mean : 2.938
## 3rd Qu.: 3.000
## Max. :10.000
##
## Price Method SellerG Date
## Min. : 85000 Length:13580 Length:13580 Length:13580
## 1st Qu.: 650000 Class :character Class :character Class :character
## Median : 903000 Mode :character Mode :character Mode :character
## Mean :1075684
## 3rd Qu.:1330000
## Max. :9000000
##
## Distance Postcode Bedroom2 Bathroom
## Min. : 0.00 Min. :3000 Min. : 0.000 Min. :0.000
## 1st Qu.: 6.10 1st Qu.:3044 1st Qu.: 2.000 1st Qu.:1.000
## Median : 9.20 Median :3084 Median : 3.000 Median :1.000
## Mean :10.14 Mean :3105 Mean : 2.915 Mean :1.534
## 3rd Qu.:13.00 3rd Qu.:3148 3rd Qu.: 3.000 3rd Qu.:2.000
## Max. :48.10 Max. :3977 Max. :20.000 Max. :8.000
##
## Car Landsize BuildingArea YearBuilt
## Min. : 0.00 Min. : 0.0 Min. : 0 Min. :1196
## 1st Qu.: 1.00 1st Qu.: 177.0 1st Qu.: 93 1st Qu.:1940
## Median : 2.00 Median : 440.0 Median : 126 Median :1970
## Mean : 1.61 Mean : 558.4 Mean : 152 Mean :1965
## 3rd Qu.: 2.00 3rd Qu.: 651.0 3rd Qu.: 174 3rd Qu.:1999
## Max. :10.00 Max. :433014.0 Max. :44515 Max. :2018
## NA's :62 NA's :6450 NA's :5375
## CouncilArea Lattitude Longtitude Regionname
## Length:13580 Min. :-38.18 Min. :144.4 Length:13580
## Class :character 1st Qu.:-37.86 1st Qu.:144.9 Class :character
## Mode :character Median :-37.80 Median :145.0 Mode :character
## Mean :-37.81 Mean :145.0
## 3rd Qu.:-37.76 3rd Qu.:145.1
## Max. :-37.41 Max. :145.5
##
## Propertycount
## Min. : 249
## 1st Qu.: 4380
## Median : 6555
## Mean : 7454
## 3rd Qu.:10331
## Max. :21650
##
str(df)
## 'data.frame': 13580 obs. of 21 variables:
## $ Suburb : chr "Abbotsford" "Abbotsford" "Abbotsford" "Abbotsford" ...
## $ Address : chr "85 Turner St" "25 Bloomburg St" "5 Charles St" "40 Federation La" ...
## $ Rooms : int 2 2 3 3 4 2 3 2 1 2 ...
## $ Type : chr "h" "h" "h" "h" ...
## $ Price : num 1480000 1035000 1465000 850000 1600000 ...
## $ Method : chr "S" "S" "SP" "PI" ...
## $ SellerG : chr "Biggin" "Biggin" "Biggin" "Biggin" ...
## $ Date : chr "3/12/2016" "4/02/2016" "4/03/2017" "4/03/2017" ...
## $ Distance : num 2.5 2.5 2.5 2.5 2.5 2.5 2.5 2.5 2.5 2.5 ...
## $ Postcode : num 3067 3067 3067 3067 3067 ...
## $ Bedroom2 : num 2 2 3 3 3 2 4 2 1 3 ...
## $ Bathroom : num 1 1 2 2 1 1 2 1 1 1 ...
## $ Car : num 1 0 0 1 2 0 0 2 1 2 ...
## $ Landsize : num 202 156 134 94 120 181 245 256 0 220 ...
## $ BuildingArea : num NA 79 150 NA 142 NA 210 107 NA 75 ...
## $ YearBuilt : num NA 1900 1900 NA 2014 ...
## $ CouncilArea : chr "Yarra" "Yarra" "Yarra" "Yarra" ...
## $ Lattitude : num -37.8 -37.8 -37.8 -37.8 -37.8 ...
## $ Longtitude : num 145 145 145 145 145 ...
## $ Regionname : chr "Northern Metropolitan" "Northern Metropolitan" "Northern Metropolitan" "Northern Metropolitan" ...
## $ Propertycount: num 4019 4019 4019 4019 4019 ...
df <- na.omit(df)
arbol <- rpart(Price ~ Rooms + Distance + Bedroom2 + Bathroom + Car + Landsize + BuildingArea + YearBuilt + Propertycount, data=df)
plot(arbol, uniform=TRUE)
text(arbol, cex=.5)
predict(arbol,head(df))
## 2 3 5 7 8 10
## 1095996 1562641 1070605 2422140 1095996 1095996
head(df$Price)
## [1] 1035000 1465000 1600000 1876000 1636000 1097000
prueba_arbol <- head(df)
mae_arbol <- mae(arbol, prueba_arbol)
set.seed(123)
renglones_entrenamiento <- createDataPartition(df$Price, p=0.8, list=FALSE)
entrenamiento <- df[renglones_entrenamiento, ]
prueba <- df[-renglones_entrenamiento, ]
rf <- randomForest(Price ~ Rooms + Distance + Bedroom2 + Bathroom + Car + Landsize + BuildingArea + YearBuilt + Propertycount, data= entrenamiento, ntree=500, mtry=3, importance=TRUE)
resultado_entrenamiento <- predict(rf,entrenamiento)
resultado_prueba <- predict(rf,prueba)
mae_rf <- mae(rf,prueba)
resultados <- tibble(Modelo = c("Arbol de decision", "Bosque de aleatorio"), MAE=c(mae_arbol, mae_rf))
resultados
## # A tibble: 2 × 2
## Modelo MAE
## <chr> <dbl>
## 1 Arbol de decision 295863.
## 2 Bosque de aleatorio 213019.
df2 <- mtcars
glimpse(df2)
## Rows: 32
## Columns: 11
## $ mpg <dbl> 21.0, 21.0, 22.8, 21.4, 18.7, 18.1, 14.3, 24.4, 22.8, 19.2, 17.8,…
## $ cyl <dbl> 6, 6, 4, 6, 8, 6, 8, 4, 4, 6, 6, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 8,…
## $ disp <dbl> 160.0, 160.0, 108.0, 258.0, 360.0, 225.0, 360.0, 146.7, 140.8, 16…
## $ hp <dbl> 110, 110, 93, 110, 175, 105, 245, 62, 95, 123, 123, 180, 180, 180…
## $ drat <dbl> 3.90, 3.90, 3.85, 3.08, 3.15, 2.76, 3.21, 3.69, 3.92, 3.92, 3.92,…
## $ wt <dbl> 2.620, 2.875, 2.320, 3.215, 3.440, 3.460, 3.570, 3.190, 3.150, 3.…
## $ qsec <dbl> 16.46, 17.02, 18.61, 19.44, 17.02, 20.22, 15.84, 20.00, 22.90, 18…
## $ vs <dbl> 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,…
## $ am <dbl> 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0,…
## $ gear <dbl> 4, 4, 4, 3, 3, 3, 3, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 4, 4, 4, 3, 3,…
## $ carb <dbl> 4, 4, 1, 1, 2, 1, 4, 2, 2, 4, 4, 3, 3, 3, 4, 4, 4, 1, 2, 1, 1, 2,…
summary(df2)
## mpg cyl disp hp
## Min. :10.40 Min. :4.000 Min. : 71.1 Min. : 52.0
## 1st Qu.:15.43 1st Qu.:4.000 1st Qu.:120.8 1st Qu.: 96.5
## Median :19.20 Median :6.000 Median :196.3 Median :123.0
## Mean :20.09 Mean :6.188 Mean :230.7 Mean :146.7
## 3rd Qu.:22.80 3rd Qu.:8.000 3rd Qu.:326.0 3rd Qu.:180.0
## Max. :33.90 Max. :8.000 Max. :472.0 Max. :335.0
## drat wt qsec vs
## Min. :2.760 Min. :1.513 Min. :14.50 Min. :0.0000
## 1st Qu.:3.080 1st Qu.:2.581 1st Qu.:16.89 1st Qu.:0.0000
## Median :3.695 Median :3.325 Median :17.71 Median :0.0000
## Mean :3.597 Mean :3.217 Mean :17.85 Mean :0.4375
## 3rd Qu.:3.920 3rd Qu.:3.610 3rd Qu.:18.90 3rd Qu.:1.0000
## Max. :4.930 Max. :5.424 Max. :22.90 Max. :1.0000
## am gear carb
## Min. :0.0000 Min. :3.000 Min. :1.000
## 1st Qu.:0.0000 1st Qu.:3.000 1st Qu.:2.000
## Median :0.0000 Median :4.000 Median :2.000
## Mean :0.4062 Mean :3.688 Mean :2.812
## 3rd Qu.:1.0000 3rd Qu.:4.000 3rd Qu.:4.000
## Max. :1.0000 Max. :5.000 Max. :8.000
## Preparación de datos
datos <- df2 %>%
as_tibble(rownames = "modelo") %>%
mutate(cyl = as.factor(cyl),
gear = as.factor(gear),
carb = as.factor(carb),
vs = as.factor(vs),
am = as.factor(am))
part <- resample_partition(datos, c(train = 0.7, test = 0.3))
train <- as_tibble(part$train)
test <- as_tibble(part$test)
form <- mpg ~ cyl + disp + hp + drat + wt + qsec + vs + am + gear + carb
## Árbol de decisión
arbol <- rpart(
form, data = train, method = "anova",
control = rpart.control(
cp = 0.0001,
maxdepth = 30,
minsplit = 2,
minbucket = 1,
usesurrogate = 2,
xval = 0
)
)
rpart.plot(arbol, main = "Árbol de decisión complejo")
pred_arbol <- predict(arbol, newdata = test)
mae_arbol <- mean(abs(pred_arbol - test$mpg))
mae_arbol
## [1] 2.875
## Bosque aleatorio
set.seed(123)
p <- length(all.vars(update(form, . ~ .)))-1
rf <- randomForest(
form, data = train,
ntree = 5000,
mtry = max(2, floor(sqrt(p))*2),
nodesize = 1,
sampsize = nrow(train),
replace = TRUE,
importance = TRUE,
keep.inbag = TRUE
)
pred_rf <- predict(rf, newdata = test)
mae_rf <- mean(abs(pred_rf - test$mpg))
mae_rf
## [1] 1.842486
imp <- as_tibble(importance(rf), rownames = "Variable") |>
arrange(desc(IncNodePurity))
imp
## # A tibble: 10 × 3
## Variable `%IncMSE` IncNodePurity
## <chr> <dbl> <dbl>
## 1 hp 43.0 237.
## 2 wt 39.4 192.
## 3 disp 34.4 186.
## 4 cyl 24.0 91.2
## 5 drat 12.1 43.4
## 6 qsec 7.15 22.3
## 7 carb 17.0 21.1
## 8 gear 5.57 8.74
## 9 am 6.23 5.12
## 10 vs 3.87 2.47
## Comparación de modelos (MAE)
resultados <- tibble(
Modelo = c("Árbol de decisión (complejo)", "Bosque aleatorio (complejo)"),
MAE = c(mae_arbol, mae_rf)
)
resultados |> arrange(MAE)
## # A tibble: 2 × 2
## Modelo MAE
## <chr> <dbl>
## 1 Bosque aleatorio (complejo) 1.84
## 2 Árbol de decisión (complejo) 2.87