suppressMessages(library(rpart))
suppressMessages(library(caret))
suppressMessages(library(readr))
suppressMessages(library(dplyr))

1 Archivos de datos

2 Leer archivos Entrenamiento y Testeo:

Al usar la funcion read_csv del paquete readr tenemos la posibilidad de definir el tipo de dato que queremos para cada variable.

data_train <- readr::read_csv("./data/arbolado-mza-dataset.csv",
                              col_types = cols(
  id = col_integer(),
  especie = col_character(),
  ultima_modificacion = col_character(),
  altura = col_character(),
  circ_tronco_cm = col_double(),
  diametro_tronco = col_character(),
  long = col_double(),
  lat = col_double(),
  seccion = col_integer(),
  nombre_seccion = col_character(),
  area_seccion = col_double(),
  inclinacion_peligrosa = col_integer()
))

data_test <-  readr::read_csv("./data/arbolado-mza-dataset-test.csv",col_types = cols(
  id = col_integer(),
  especie = col_character(),
  ultima_modificacion = col_character(),
  altura = col_character(),
  circ_tronco_cm = col_double(),
  diametro_tronco = col_character(),
  long = col_double(),
  lat = col_double(),
  seccion = col_integer(),
  nombre_seccion = col_character(),
  area_seccion = col_double()
))

2.1 Transformaciones:

Algunos algoritmos no permiten nombres de factores como 1 y 0, se transforma la clase inclinacion_peligrosa a si y no

data_train<-data_train %>% mutate(inclinacion_peligrosa=ifelse(inclinacion_peligrosa=='1','si','no'))
data_train$inclinacion_peligrosa <-as.factor(data_train$inclinacion_peligrosa)

3 Arbol de Decision (Rpart)

3.1 Entrenamiento

Seleccionamos algunos atributos que a priori creemos que pueden explicar la inclinacion del arbol

  • altura
  • circunferencia del tronco
  • Latitud
  • Longitud
  • Seccion Administrativa
  • Especie

Luego se entrena un arbol de decision utilizando los parametros por omision.

train_formula<-formula(inclinacion_peligrosa~altura+circ_tronco_cm+lat+long+seccion+especie)
tree_model_3<-rpart(train_formula,data=data_train)

3.2 Generacion del archivo de ENVIO

Para generar un archivo de envio, necesitamos aplicar la funcion predict() sobre el conjunto de evaluacion. La prediccion da como resultado la probabilidad asignada a cada clase.

preds_tree_probs=predict(tree_model_3,data_test,type='prob')
head(preds_tree_probs)
##             no        si
## [1,] 0.8878478 0.1121522
## [2,] 0.8878478 0.1121522
## [3,] 0.8878478 0.1121522
## [4,] 0.8878478 0.1121522
## [5,] 0.8878478 0.1121522
## [6,] 0.8878478 0.1121522

Sim embargo para poder hacer el envio a Kaggle, necesitamos un archivo que tenga los ID de cada registro y el valor 0 (no peligrosa) o 1 (peligrosa). Para esto hay que por un lado convertir las probabilidades de las classes si y no a sus correspondientes 0 y 1.

Para esto hay que establecer un umbral (threshold) a partir del cual se decide si un registro pertenece a la clase 0 o a la clase 1. Comunmente se toma un \(valor >=0.5\) para indicar la pertenencia a una clase. Por ejemplo el registro con el ID tiene una probabilidad 0.92798 la cual es >=0.5 por lo tanto \(\in\) a la clase 1. Esto se puede hacer facilmente en una linea usando la funcion ifelse()

preds_tree=ifelse(preds_tree_probs[,2] >=0.5,1,0)
head(preds_tree)
## [1] 0 0 0 0 0 0

Ahora tenemos para cada registro del conjunto de testeo la clase a la que pertenece segun las predicciones del arbol de decision. Lo que queda entonces es simplemente agregar los ID de cada registro y crear un archivo con el envio.

submission<-data.frame(id=data_test$id,inclinacion_peligrosa=preds_tree)
readr::write_csv(submission,"./arbolado-mza-dataset-envio-ejemplo-rpart.csv")
head(submission)
##   id inclinacion_peligrosa
## 1  1                     0
## 2  2                     0
## 3  4                     0
## 4  6                     0
## 5  9                     0
## 6 13                     0

4 Arbol de Decision con Validacion

4.1 Creando un archivos de Validacion

Antes de hacer un envio a Kaggle podemos darnos una idea de lo bien que funciona nuestro algoritmo, para esto basta con separar una porcion del conjunto de entrenamiento y usarla para validadcion

set.seed(100) # para que sea un ejemplo reproducible
data_validation_index<-sample(nrow(data_train),nrow(data_train)*0.1)
data_validation<-data_train[data_validation_index,]
data_train<-data_train[-data_validation_index,]

Una vez separado en 2 archivos, rentrenamos el modelo usando la funcion rpart() ## Entrenamiento

train_formula<-formula(inclinacion_peligrosa~altura+circ_tronco_cm+lat+long+seccion+especie)
tree_model_4<-rpart(train_formula,data=data_train)

y ahora calculamos las predicciones para el conjunto de validacion. Aca se repite el mismo proceso que en ejemplo anterior para convertir las probabilidades a las correspondientes classes 0 y 1. ## Generacion del dataframe con los resultados de la validacion

preds_tree_probs=predict(tree_model_4,data_validation,type='prob')
preds_tree=ifelse(preds_tree_probs[,2] >=0.5,'si','no')
resultados_validation<-data.frame(inclinacion_peligrosa=preds_tree)

4.2 Calculo de la matriz de confusion

Luego podemos calcular algunas metricas utilizando los resultados de nuestro prediccion y comparandolos con los valores correctos del archivo data_validation.

La funcion confusionMatrix() del paquete caret nos facilita calcular la matriz de confusion ademas de varias metricas

confusionMatrix(resultados_validation$inclinacion_peligrosa,data_validation$inclinacion_peligrosa)
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction   no   si
##         no 2805  386
##         si    0    0
##                                           
##                Accuracy : 0.879           
##                  95% CI : (0.8672, 0.8902)
##     No Information Rate : 0.879           
##     P-Value [Acc > NIR] : 0.5136          
##                                           
##                   Kappa : 0               
##  Mcnemar's Test P-Value : <2e-16          
##                                           
##             Sensitivity : 1.000           
##             Specificity : 0.000           
##          Pos Pred Value : 0.879           
##          Neg Pred Value :   NaN           
##              Prevalence : 0.879           
##          Detection Rate : 0.879           
##    Detection Prevalence : 1.000           
##       Balanced Accuracy : 0.500           
##                                           
##        'Positive' Class : no              
## 

Podemos ver que para este caso, el arbol a clasificado a todas los registros como NO peligrosos. Por que sera?