Librerias a usar
library(ggplot2)
## Warning: package 'ggplot2' was built under R version 4.0.5
library(caret)
## Warning: package 'caret' was built under R version 4.0.5
## Loading required package: lattice
library(MASS)
library(rpart)
## Warning: package 'rpart' was built under R version 4.0.5
library(rpart.plot)
## Warning: package 'rpart.plot' was built under R version 4.0.5
library(ggplot2)
library(e1071)
## Warning: package 'e1071' was built under R version 4.0.5
Se procede a cargar la base de datos y a seleccionar el dataframe a usar
data("Pima.tr");data("Pima.te")
Pima <- rbind(Pima.tr,Pima.te)
View(Pima)
rm(Pima.tr,Pima.te)
str(Pima)
## 'data.frame': 532 obs. of 8 variables:
## $ npreg: int 5 7 5 0 0 5 3 1 3 2 ...
## $ glu : int 86 195 77 165 107 97 83 193 142 128 ...
## $ bp : int 68 70 82 76 60 76 58 50 80 78 ...
## $ skin : int 28 33 41 43 25 27 31 16 15 37 ...
## $ bmi : num 30.2 25.1 35.8 47.9 26.4 35.6 34.3 25.9 32.4 43.3 ...
## $ ped : num 0.364 0.163 0.156 0.259 0.133 ...
## $ age : int 24 55 35 26 23 52 25 24 63 31 ...
## $ type : Factor w/ 2 levels "No","Yes": 1 2 1 1 1 2 1 1 1 2 ...
summary(Pima)
## npreg glu bp skin
## Min. : 0.000 Min. : 56.00 Min. : 24.00 Min. : 7.00
## 1st Qu.: 1.000 1st Qu.: 98.75 1st Qu.: 64.00 1st Qu.:22.00
## Median : 2.000 Median :115.00 Median : 72.00 Median :29.00
## Mean : 3.517 Mean :121.03 Mean : 71.51 Mean :29.18
## 3rd Qu.: 5.000 3rd Qu.:141.25 3rd Qu.: 80.00 3rd Qu.:36.00
## Max. :17.000 Max. :199.00 Max. :110.00 Max. :99.00
## bmi ped age type
## Min. :18.20 Min. :0.0850 Min. :21.00 No :355
## 1st Qu.:27.88 1st Qu.:0.2587 1st Qu.:23.00 Yes:177
## Median :32.80 Median :0.4160 Median :28.00
## Mean :32.89 Mean :0.5030 Mean :31.61
## 3rd Qu.:36.90 3rd Qu.:0.6585 3rd Qu.:38.00
## Max. :67.10 Max. :2.4200 Max. :81.00
attach(Pima)
names(Pima)
## [1] "npreg" "glu" "bp" "skin" "bmi" "ped" "age" "type"
Árbol de clasificación
set.seed(123)
arbol1 <- rpart(type ~ age + npreg + bmi + glu + bp + skin + ped ,
data = Pima,
method = "class")
rpart.plot(arbol1,digits = -1,type = 2,extra = 102,cex = 0.7, nn=TRUE)
Como se puede apreciar en el árbol de clasificación el nodo padre corresponde a la glucosa, ya que es la variable que el sistema considera que es la más apropiada para empezar la clasificación. Este nodo inicial expone que hay 355 datos que se categorizan con “No” para tener diabetes, mientras que los resultantes son “Sí”.
Cabe resaltar que el valor de referencia de la glucosa es menor que 128; a partir de allí se empiezan a ramificarse de acuerdo a las demás variables, tales como: edad, bmi, npreg, entre otros.
Matriz de Confusión
Prediccion_1 <- predict(arbol1, newdata = Pima, type = "class")
caret::confusionMatrix(Prediccion_1, Pima$type, positive = "Yes")
## Confusion Matrix and Statistics
##
## Reference
## Prediction No Yes
## No 326 46
## Yes 29 131
##
## Accuracy : 0.859
## 95% CI : (0.8265, 0.8875)
## No Information Rate : 0.6673
## P-Value [Acc > NIR] : < 2e-16
##
## Kappa : 0.6747
##
## Mcnemar's Test P-Value : 0.06467
##
## Sensitivity : 0.7401
## Specificity : 0.9183
## Pos Pred Value : 0.8187
## Neg Pred Value : 0.8763
## Prevalence : 0.3327
## Detection Rate : 0.2462
## Detection Prevalence : 0.3008
## Balanced Accuracy : 0.8292
##
## 'Positive' Class : Yes
##
La matriz de confusión expone que 326 datos corresponden a mujeres que efectivamente no tienen diabetes, frente a 131 observaciones que verdaderamente padecen de diabetes. Los falsos negativos equivalen a a 46, mientras que los falsos positivos corresponden a 29.
Por otro lado, la precisión del árbol corresponde a 85.9 %, el Kappa es de 67.47 % (aunque lo preferible es que aumente).
La sensitividad del árbol, es decir, la capacidad del algorítmo para la clasificación de los verdaderos positivos es de 74.01 %. Ahora la especificidad que corresponde a la capacidad de clasificar a los falsos negativos es de 91.83 %. Es posible apreciar la disparidad entre estas clasificaciones.
Hiperparámetros minbucket = 30, minsplit = 50
arbol2 <- rpart(type ~ age + npreg + bmi + glu + bp + skin + ped,
data = Pima,
control = rpart.control(minsplit = 50,minbucket = 30),
method = "class")
rpart.plot(arbol2,digits = -1,type = 2,extra = 102,cex = 0.8, nn=TRUE)
Prediccion_2 <- predict(arbol2, newdata = Pima, type = "class")
caret::confusionMatrix(Prediccion_2, Pima$type, positive = "Yes")
## Confusion Matrix and Statistics
##
## Reference
## Prediction No Yes
## No 313 58
## Yes 42 119
##
## Accuracy : 0.812
## 95% CI : (0.7762, 0.8444)
## No Information Rate : 0.6673
## P-Value [Acc > NIR] : 7.571e-14
##
## Kappa : 0.5669
##
## Mcnemar's Test P-Value : 0.1336
##
## Sensitivity : 0.6723
## Specificity : 0.8817
## Pos Pred Value : 0.7391
## Neg Pred Value : 0.8437
## Prevalence : 0.3327
## Detection Rate : 0.2237
## Detection Prevalence : 0.3026
## Balanced Accuracy : 0.7770
##
## 'Positive' Class : Yes
##
Con los ajustes hechos en el minsplit y minbucket se busca mejorar la bondad de ajuste, sin embargo, al aplicarlos se evidencia como el Kappa diminuye significativamente de 0.6747, para el primer árbol planteado, a 0.5669 con los ajustes. Así mismo, la sensitividad y especificidad se redujeron de 0.7401 - 0.9183 a 0.6723 - 0.8817 respectivamente. De lo anterior se puede decir que los ajustes hechos al árbol no contribuyeron al mejoramiento de la clasificación considerando la bondad de ajuste.
Se cambia el parámetro de complejidad (CP) a 0.05
arbol3 <- rpart(type ~ age + npreg + bmi + glu + bp + skin + ped,
data = Pima,
control = rpart.control(minsplit = 50,minbucket = 30,cp = 0.05),
method = "class")
rpart.plot(arbol3, digits = -1, type = 2, extra = 102, cex = 0.8, nn=TRUE)
Depués de ajustar el parámetro de complejidad a 0.05, el árbol tuvo una reducción significativa de los nodos hijos de 4 en el ejemplo anterior a solo 2 después de esta restricción.
Prediccion_3 <- predict(arbol3, newdata=Pima, type="class")
caret::confusionMatrix(Prediccion_3, type, positive="Yes")
## Confusion Matrix and Statistics
##
## Reference
## Prediction No Yes
## No 311 66
## Yes 44 111
##
## Accuracy : 0.7932
## 95% CI : (0.7563, 0.8269)
## No Information Rate : 0.6673
## P-Value [Acc > NIR] : 9.62e-11
##
## Kappa : 0.5194
##
## Mcnemar's Test P-Value : 0.04526
##
## Sensitivity : 0.6271
## Specificity : 0.8761
## Pos Pred Value : 0.7161
## Neg Pred Value : 0.8249
## Prevalence : 0.3327
## Detection Rate : 0.2086
## Detection Prevalence : 0.2914
## Balanced Accuracy : 0.7516
##
## 'Positive' Class : Yes
##
Ahora, al analizar la Matriz de confusión es posible notar que los valores correspondientes a los falsos negativos y positivos aumentaron, frente a la disminución de los verdaderos positivos y negativos. El Kappa se redujo de 0.5669 a 0.5194. Por otro lado, la sensitividad y la especificidad se redujeron levemente de 0.6723-0.8817 a 0.6271-0.8761 respectivamente.
arbol4 <- prune(arbol3, cp = 0.03)
rpart.plot(arbol4, digits = -1, type = 2, extra = 102, cex = 0.8, nn=TRUE)
Prediccion_4 <- predict(arbol4, newdata = Pima, type="class")
caret::confusionMatrix(Prediccion_4, type, positive="Yes")
## Confusion Matrix and Statistics
##
## Reference
## Prediction No Yes
## No 311 66
## Yes 44 111
##
## Accuracy : 0.7932
## 95% CI : (0.7563, 0.8269)
## No Information Rate : 0.6673
## P-Value [Acc > NIR] : 9.62e-11
##
## Kappa : 0.5194
##
## Mcnemar's Test P-Value : 0.04526
##
## Sensitivity : 0.6271
## Specificity : 0.8761
## Pos Pred Value : 0.7161
## Neg Pred Value : 0.8249
## Prevalence : 0.3327
## Detection Rate : 0.2086
## Detection Prevalence : 0.2914
## Balanced Accuracy : 0.7516
##
## 'Positive' Class : Yes
##
Al podar el arbol obtenemos como resultado ningún cambio en la clasificación, así mismo al analizar y comparar la matriz de confusión, se tiene que la poda del árbol no genera cambios en los valores que conforman la matriz, tampoco se presentan cambios en los estadisticos del ajuste del árbol.