Objetivo:
Construir un modelo con árboles de regresión y realizar predicciones con el mismo.
Descripción:
Aplicar el modelo de árboles de regresión en el conjunto de datos de precios de casas en Durango.
Proceso
- Cargar librerías
- Cargar datos
- Limpiar datos
- División datos (entrenamiento/validación)
- Generar modelo
- Visualizar modelo
- Predecir con datos de validación
- Predecir con nuevos valores
- Comparar modelo actual con modelo de regresión múltiple
- Interpretar el caso
1. Cargar librerías
library(rpart)
library(rpart.plot)
library(caret)
library(dplyr)
library(readr)
library(ggplot2)
library(reshape)
library(knitr)
options(scipen = 999)
2. Cargar datos
datos <- read.csv("https://raw.githubusercontent.com/rpizarrog/FundamentosMachineLearning/master/datos/datos%20precios%20de%20casas.csv", encoding = "UTF-8")
3. Limpiar datos
datos <- datos[,c(1,2,3,4,7,8)]
names(datos)[4] <- c('banio')
datos <- mutate(datos, estacionamientos = ifelse(is.na(estacionamientos), 0, estacionamientos))
datos <- mutate(datos, construccion = ifelse(is.na(construccion), mean(construccion, na.rm = TRUE), construccion))
kable(head(datos), caption = "Registros")
Registros
| 1780000 |
2 |
3 |
2 |
169 |
126 |
| 650000 |
1 |
3 |
1 |
90 |
90 |
| 590000 |
2 |
2 |
2 |
63 |
90 |
| 1300000 |
2 |
3 |
2 |
130 |
120 |
| 1000000 |
2 |
2 |
1 |
110 |
160 |
| 465000 |
2 |
3 |
1 |
53 |
89 |
4. División datos (entrenamiento/validación)
set.seed(2020)
para_entrenar <- createDataPartition(y = datos$precio, p = 0.7, list = FALSE, times = 1)
conjunto_entrenamiento <- datos[para_entrenar, ]
conjunto_validacion <- datos[-para_entrenar, ]
kable(head(conjunto_entrenamiento, 10), caption = "Datos de entrenamiento (primeros diez registros)", row.names = 1:row(conjunto_entrenamiento))
Datos de entrenamiento (primeros diez registros)
| 2 |
650000 |
1 |
3 |
1 |
90.0000 |
90 |
| 3 |
590000 |
2 |
2 |
2 |
63.0000 |
90 |
| 4 |
1300000 |
2 |
3 |
2 |
130.0000 |
120 |
| 5 |
1000000 |
2 |
2 |
1 |
110.0000 |
160 |
| 7 |
780000 |
2 |
1 |
1 |
84.0000 |
90 |
| 8 |
464520 |
0 |
2 |
1 |
47.0000 |
98 |
| 10 |
580000 |
0 |
3 |
1 |
65.0000 |
103 |
| 11 |
1550000 |
2 |
3 |
2 |
155.0000 |
126 |
| 12 |
640000 |
0 |
2 |
1 |
151.1156 |
90 |
| 14 |
480000 |
0 |
2 |
1 |
53.0000 |
90 |
kable(head(conjunto_validacion, 10), caption = "Datos de validación (primeros diez registros)", row.names = 1:row(conjunto_validacion))
Datos de validación (primeros diez registros)
| 1 |
1780000 |
2 |
3 |
2.0 |
169.00 |
126 |
| 6 |
465000 |
2 |
3 |
1.0 |
53.00 |
89 |
| 9 |
660000 |
0 |
3 |
1.0 |
73.00 |
112 |
| 13 |
2350000 |
2 |
3 |
2.5 |
194.56 |
203 |
| 16 |
1000000 |
2 |
3 |
2.0 |
110.00 |
120 |
| 23 |
660000 |
0 |
3 |
1.0 |
73.00 |
112 |
| 25 |
1750000 |
1 |
3 |
2.0 |
154.00 |
130 |
| 32 |
2100000 |
0 |
4 |
2.0 |
151.00 |
151 |
| 34 |
640000 |
1 |
2 |
1.0 |
60.00 |
90 |
| 35 |
462000 |
1 |
2 |
1.0 |
47.00 |
90 |
5. Generar modelo
set.seed(2020)
modelo <- rpart(formula = precio ~ ., data = conjunto_entrenamiento)
modelo
n= 38
node), split, n, deviance, yval
* denotes terminal node
1) root 38 81930710000000 1572540.0
2) construccion< 205.5 30 6480123000000 991950.7
4) construccion< 152.5578 23 1930233000000 807892.2
8) construccion< 96.5 12 116237700000 603043.3 *
9) construccion>=96.5 11 761104500000 1031364.0 *
5) construccion>=152.5578 7 1210533000000 1596714.0 *
3) construccion>=205.5 8 27416120000000 3749750.0 *
6. Visualizar modelo
prp(modelo, type = 2, nn = TRUE, fallen.leaves = TRUE, faclen = 4, varlen =8, shadow.col = "gray")

7. Predecir con datos de validación
predicciones <- predict(object = modelo, newdata = conjunto_validacion)
predicciones_df <- data.frame(conjunto_validacion, predicciones)
kable(predicciones_df)
| 1 |
1780000 |
2 |
3 |
2.0 |
169.00 |
126 |
1596714.3 |
| 6 |
465000 |
2 |
3 |
1.0 |
53.00 |
89 |
603043.3 |
| 9 |
660000 |
0 |
3 |
1.0 |
73.00 |
112 |
603043.3 |
| 13 |
2350000 |
2 |
3 |
2.5 |
194.56 |
203 |
1596714.3 |
| 16 |
1000000 |
2 |
3 |
2.0 |
110.00 |
120 |
1031363.6 |
| 23 |
660000 |
0 |
3 |
1.0 |
73.00 |
112 |
603043.3 |
| 25 |
1750000 |
1 |
3 |
2.0 |
154.00 |
130 |
1596714.3 |
| 32 |
2100000 |
0 |
4 |
2.0 |
151.00 |
151 |
1031363.6 |
| 34 |
640000 |
1 |
2 |
1.0 |
60.00 |
90 |
603043.3 |
| 35 |
462000 |
1 |
2 |
1.0 |
47.00 |
90 |
603043.3 |
| 45 |
960000 |
1 |
3 |
2.0 |
162.00 |
90 |
1596714.3 |
| 49 |
1200000 |
1 |
3 |
1.5 |
115.00 |
112 |
1031363.6 |
| 51 |
3450000 |
2 |
3 |
2.0 |
200.00 |
280 |
1596714.3 |
8. Predecir con nuevos valores
estacionamiento <- 3
recamara <- 4
bano <- 3
const <- 250
trrn <- 203
nuevos_datos <- data.frame(estacionamientos = estacionamiento, recamaras = recamara, banio = bano, construccion = const, terreno = trrn)
nueva_prediccion <- predict(object = modelo, newdata = nuevos_datos)
paste("El valor del precio predicho es de:", round(nueva_prediccion, 2))
[1] "El valor del precio predicho es de: 3749750"
9. Comparar modelo actual con modelo de regresión múltiple
Si comparamos las tablas donde tenemos las predicciones, el modelo con árboles de regresión es bastante aproximado a valores bajos en casas, mientras que en valores altos suele quedar ligeramente bajo el precio real o exageradamente por arriba de la realidad. En cuanto al modelo con regresión lineal múltiple observamos que es el caso contrario, para los precios altos en las casas es preciso con diferencias en pesos no tan significativas, pero para valores bajos suele quedar muy por debajo del precio real la gran parte de los registros.
10. Interpretar el caso
Como se mencionó en el punto anterior, este modelo predice muy bien los valores bajos e intermedios de las casas, en el precio más alto del conjunto de datos se quedo bastante por debajo del precio real de la casa, en cuanto a la variable que determina mejor el precio es la de construcción con un valor menor a 206 metros siendo los precios más altos, seguido de un valor menor a 153 metros con valores intermedios y para los precios más bajos corresponde una construcción menor a los 97 metros. Estos valores determinaron los nodos finales de nuestro árbol de regresión.