library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.2.1 ✔ readr 2.2.0
## ✔ forcats 1.0.1 ✔ stringr 1.6.0
## ✔ ggplot2 4.0.3 ✔ tibble 3.3.1
## ✔ lubridate 1.9.5 ✔ tidyr 1.3.2
## ✔ purrr 1.2.2
## ── 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(caret)
## Loading required package: lattice
##
## Attaching package: 'caret'
##
## The following object is masked from 'package:purrr':
##
## lift
library(randomForest)
## randomForest 4.7-1.2
## Type rfNews() to see new features/changes/bug fixes.
##
## Attaching package: 'randomForest'
##
## The following object is masked from 'package:dplyr':
##
## combine
##
## The following object is masked from 'package:ggplot2':
##
## margin
## 3. Carga de datos
data(iris)
head(iris)
## 4. Análisis exploratorio (EDA)
# Distribución de clases
ggplot(iris, aes(x = Species, fill = Species)) +
geom_bar() +
theme_minimal() +
labs(title = "Distribución de especies")

# Boxplots
iris %>%
pivot_longer(cols = -Species) %>%
ggplot(aes(x = Species, y = value, fill = Species)) +
geom_boxplot() +
facet_wrap(~name, scales = "free") +
theme_minimal()

## 5. Train/Test (Entrenando al 70/30)
set.seed(123)
library(caret)
trainIndex <- createDataPartition(iris$Species, p = 0.7, list = FALSE)
train <- iris[trainIndex, ]
test <- iris[-trainIndex, ]
# Ver tamaños
dim(train)
## [1] 105 5
dim(test)
## [1] 45 5
## 6. Entrenamiento del modelo
set.seed(123)
control <- trainControl(
method = "cv", # validación cruzada
number = 5 # 5 folds
)
model_rf <- train(
Species ~ .,
data = train,
method = "rf",
trControl = control,
tuneLength = 3
)
model_rf
## Random Forest
##
## 105 samples
## 4 predictor
## 3 classes: 'setosa', 'versicolor', 'virginica'
##
## No pre-processing
## Resampling: Cross-Validated (5 fold)
## Summary of sample sizes: 84, 84, 84, 84, 84
## Resampling results across tuning parameters:
##
## mtry Accuracy Kappa
## 2 0.9428571 0.9142857
## 3 0.9428571 0.9142857
## 4 0.9428571 0.9142857
##
## Accuracy was used to select the optimal model using the largest value.
## The final value used for the model was mtry = 2.
## 7.Predicciones
predictions <- predict(model_rf, newdata = test)
predictions
## [1] setosa setosa setosa setosa setosa setosa
## [7] setosa setosa setosa setosa setosa setosa
## [13] setosa setosa setosa versicolor versicolor versicolor
## [19] versicolor versicolor versicolor virginica versicolor versicolor
## [25] versicolor versicolor versicolor versicolor versicolor versicolor
## [31] virginica virginica virginica virginica virginica virginica
## [37] versicolor virginica virginica virginica versicolor virginica
## [43] virginica virginica virginica
## Levels: setosa versicolor virginica
## 8.Evaluaciones
conf_matrix <- confusionMatrix(predictions, test$Species)
conf_matrix
## Confusion Matrix and Statistics
##
## Reference
## Prediction setosa versicolor virginica
## setosa 15 0 0
## versicolor 0 14 2
## virginica 0 1 13
##
## Overall Statistics
##
## Accuracy : 0.9333
## 95% CI : (0.8173, 0.986)
## No Information Rate : 0.3333
## P-Value [Acc > NIR] : < 2.2e-16
##
## Kappa : 0.9
##
## Mcnemar's Test P-Value : NA
##
## Statistics by Class:
##
## Class: setosa Class: versicolor Class: virginica
## Sensitivity 1.0000 0.9333 0.8667
## Specificity 1.0000 0.9333 0.9667
## Pos Pred Value 1.0000 0.8750 0.9286
## Neg Pred Value 1.0000 0.9655 0.9355
## Prevalence 0.3333 0.3333 0.3333
## Detection Rate 0.3333 0.3111 0.2889
## Detection Prevalence 0.3333 0.3556 0.3111
## Balanced Accuracy 1.0000 0.9333 0.9167
## Accuracy = 0.9333 (93.33%) De 45 observaciones, solo fallaste en 3, esto indica que es un modelo muy sólido.
## Kappa = 0.9, sabemos que si 0.8 → excelente acuerdo, nuestro modelo → muy por encima del azar, esto indica que el modelo no solo tiene buena accuracy, también presenta alta concordancia ajustada por azar (Kappa = 0.9).
## Análisis por clase
##Setosa
##Sensitivity = 1.0
##Specificity = 1.0
## Setosa es completamente separable del resto
##Versicolor
##Sensitivity = 0.93
##Precision (Pos Pred Value) = 0.87
## Conclusiones
## El modelo Random Forest logró una accuracy de 93.33%, mostrando un desempeño sólido en la clasificación. La clase setosa fue perfectamente identificada, lo que indica una clara separabilidad en los datos. Sin embargo, se observan errores entre las clases versicolor y virginica, lo cual sugiere una superposición en sus características, especialmente en variables relacionadas con los pétalos. El modelo presenta un Kappa de 0.9, lo que indica un alto nivel de concordancia más allá del azar.
var_imp <- varImp(model_rf)
var_imp
## rf variable importance
##
## Overall
## Petal.Width 100.00
## Petal.Length 89.51
## Sepal.Length 19.03
## Sepal.Width 0.00
plot(var_imp)

## Importancia de variables
##Las variables más relevantes para el modelo fueron Petal.Length y Petal.Width. Esto indica que las características relacionadas con los pétalos tienen mayor capacidad de discriminación entre especies, en comparación con las variables del sépalo.
## Guardamos el modelo
saveRDS(model_rf, "modelo_random_forest.rds")