Examen 2

Introducción

El objetivo de este informe es aplicar diferentes metodologías de clasificación supervisada para predecir el nivel de satisfacción de los empleados utilizando la base de datos Employee-IBM. Esta base contiene variables relacionadas con características laborales, salario, experiencia, desempeño y condiciones de trabajo.

La satisfacción de los empleados es importante para cualquier organización, ya que puede estar relacionada con la retención de talento y el ambiente laboral. Por esta razón, se busca analizar qué tan bien se puede clasificar el nivel de satisfacción utilizando métodos de aprendizaje supervisado.

En este trabajo se aplican tres metodologías vistas en clase: Árboles de Decisión, K-Vecinos más Cercanos (KNN) y Clasificador Bayesiano. Cada modelo será evaluado mediante matrices de confusión, tasas de aciertos y validación cruzada para analizar su desempeño y estabilidad.

library(dplyr)
library(caret)
library(rpart)
library(rpart.plot)
library(kknn)
library(class)
library(e1071)
library(naivebayes)

Preparación inicial y limpieza de los datos:

employee <- read.csv("Employee-IBM.csv")

employee$Satisfaction <- as.factor(employee$Satisfaction)

head(employee)
##   Satisfaction Age Gender HourlyRate JobInvolvement MonthlyIncome
## 1            1  41 Female         94              3          5993
## 2            4  49   Male         61              2          5130
## 3            2  37   Male         92              2          2090
## 4            3  33 Female         56              3          2909
## 5            4  27   Male         40              3          3468
## 6            3  32   Male         79              3          3068
##   NumCompaniesWorked PercentSalaryHike StockOptionLevel TotalWorkingYears
## 1                  8                11                0                 8
## 2                  1                23                1                10
## 3                  6                15                0                 7
## 4                  1                11                0                 8
## 5                  9                12                1                 6
## 6                  0                13                0                 8
##   TrainingTimesLastYear WorkLifeBalance YearsAtCompany YearsInCurrentRole
## 1                     0               1              6                  4
## 2                     3               3             10                  7
## 3                     3               3              0                  0
## 4                     3               3              8                  7
## 5                     3               3              2                  2
## 6                     2               2              7                  7
##   YearsSinceLastPromotion YearsWithCurrManager
## 1                       0                    5
## 2                       1                    7
## 3                       0                    0
## 4                       3                    0
## 5                       2                    2
## 6                       3                    6
dim(employee)
## [1] 1470   16
summary(employee)
##  Satisfaction      Age           Gender            HourlyRate    
##  1:276        Min.   :18.00   Length:1470        Min.   : 30.00  
##  2:303        1st Qu.:30.00   Class :character   1st Qu.: 48.00  
##  3:459        Median :36.00   Mode  :character   Median : 66.00  
##  4:432        Mean   :36.92                      Mean   : 65.89  
##               3rd Qu.:43.00                      3rd Qu.: 83.75  
##               Max.   :60.00                      Max.   :100.00  
##  JobInvolvement MonthlyIncome   NumCompaniesWorked PercentSalaryHike
##  Min.   :1.00   Min.   : 1009   Min.   :0.000      Min.   :11.00    
##  1st Qu.:2.00   1st Qu.: 2911   1st Qu.:1.000      1st Qu.:12.00    
##  Median :3.00   Median : 4919   Median :2.000      Median :14.00    
##  Mean   :2.73   Mean   : 6503   Mean   :2.693      Mean   :15.21    
##  3rd Qu.:3.00   3rd Qu.: 8379   3rd Qu.:4.000      3rd Qu.:18.00    
##  Max.   :4.00   Max.   :19999   Max.   :9.000      Max.   :25.00    
##  StockOptionLevel TotalWorkingYears TrainingTimesLastYear WorkLifeBalance
##  Min.   :0.0000   Min.   : 0.00     Min.   :0.000         Min.   :1.000  
##  1st Qu.:0.0000   1st Qu.: 6.00     1st Qu.:2.000         1st Qu.:2.000  
##  Median :1.0000   Median :10.00     Median :3.000         Median :3.000  
##  Mean   :0.7939   Mean   :11.28     Mean   :2.799         Mean   :2.761  
##  3rd Qu.:1.0000   3rd Qu.:15.00     3rd Qu.:3.000         3rd Qu.:3.000  
##  Max.   :3.0000   Max.   :40.00     Max.   :6.000         Max.   :4.000  
##  YearsAtCompany   YearsInCurrentRole YearsSinceLastPromotion
##  Min.   : 0.000   Min.   : 0.000     Min.   : 0.000         
##  1st Qu.: 3.000   1st Qu.: 2.000     1st Qu.: 0.000         
##  Median : 5.000   Median : 3.000     Median : 1.000         
##  Mean   : 7.008   Mean   : 4.229     Mean   : 2.188         
##  3rd Qu.: 9.000   3rd Qu.: 7.000     3rd Qu.: 3.000         
##  Max.   :40.000   Max.   :18.000     Max.   :15.000         
##  YearsWithCurrManager
##  Min.   : 0.000      
##  1st Qu.: 2.000      
##  Median : 3.000      
##  Mean   : 4.123      
##  3rd Qu.: 7.000      
##  Max.   :17.000
colSums(is.na(employee))
##            Satisfaction                     Age                  Gender 
##                       0                       0                       0 
##              HourlyRate          JobInvolvement           MonthlyIncome 
##                       0                       0                       0 
##      NumCompaniesWorked       PercentSalaryHike        StockOptionLevel 
##                       0                       0                       0 
##       TotalWorkingYears   TrainingTimesLastYear         WorkLifeBalance 
##                       0                       0                       0 
##          YearsAtCompany      YearsInCurrentRole YearsSinceLastPromotion 
##                       0                       0                       0 
##    YearsWithCurrManager 
##                       0
table(employee$Satisfaction)
## 
##   1   2   3   4 
## 276 303 459 432

En esta etapa se cargó la base de datos y se verificó su estructura. Además, se transformó la variable Satisfaction en factor, ya que será la variable categórica que se desea predecir. No se observaron valores faltantes en la base de datos.

Dividir los datos en conjunto de entrenamiento y prueba:

set.seed(2025)

folds <- createFolds(employee$Satisfaction, k = 5)

entrenamiento <- employee[-folds[[5]], ]
prueba <- employee[folds[[5]], ]

entrenamiento_labels <- employee$Satisfaction[-folds[[5]]]
prueba_labels <- employee$Satisfaction[folds[[5]]]

Entrenamiento

dim(entrenamiento)
## [1] 1176   16

Prueba

dim(prueba)
## [1] 294  16

Se dividió la base de datos en cinco grupos utilizando createFolds(). Cuatro grupos fueron utilizados para entrenamiento y uno para prueba. Esto permite evaluar el modelo con datos que no fueron usados directamente para entrenarlo.

Árboles de decisión

Construcción del árbol de decisión:

modelo1 <- rpart(Satisfaction ~ .,
                 data = entrenamiento,
                 method = "class")

rpart.plot(modelo1)

El primer modelo aplicado fue Árboles de Decisión. Este método permite visualizar de manera jerárquica las reglas que determinan la clasificación del nivel de satisfacción de los empleados.

Validar la estabilidad del modelo:

set.seed(123)

train_control <- trainControl(method = "cv",
                              number = 5)

arbol_cv <- train(Satisfaction ~ .,
                  data = entrenamiento,
                  method = "rpart",
                  trControl = train_control,
                  tuneLength = 5)

pred_arbol <- predict(arbol_cv,
                      newdata = prueba)

confusionMatrix(pred_arbol,
                prueba$Satisfaction)
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction  1  2  3  4
##          1  0  0  0  0
##          2  0  0  0  0
##          3 25 31 45 47
##          4 31 29 47 39
## 
## Overall Statistics
##                                          
##                Accuracy : 0.2857         
##                  95% CI : (0.2348, 0.341)
##     No Information Rate : 0.3129         
##     P-Value [Acc > NIR] : 0.8578         
##                                          
##                   Kappa : -0.0245        
##                                          
##  Mcnemar's Test P-Value : NA             
## 
## Statistics by Class:
## 
##                      Class: 1 Class: 2 Class: 3 Class: 4
## Sensitivity            0.0000   0.0000   0.4891   0.4535
## Specificity            1.0000   1.0000   0.4901   0.4856
## Pos Pred Value            NaN      NaN   0.3041   0.2671
## Neg Pred Value         0.8095   0.7959   0.6781   0.6824
## Prevalence             0.1905   0.2041   0.3129   0.2925
## Detection Rate         0.0000   0.0000   0.1531   0.1327
## Detection Prevalence   0.0000   0.0000   0.5034   0.4966
## Balanced Accuracy      0.5000   0.5000   0.4896   0.4695

Se utilizó validación cruzada de 5 folds para evaluar la estabilidad del árbol de decisión. Esto permite verificar si el modelo mantiene un desempeño razonable al cambiar las particiones de los datos.

Interpretación de los resultados finales:

Entrenamiento

#Entrenamiento
pred_ent <- predict(arbol_cv,
                    entrenamiento,
                    type = "raw")

tt_ent <- table(Prediccion = pred_ent,
                Real = entrenamiento$Satisfaction)

tt_ent
##           Real
## Prediccion   1   2   3   4
##          1   0   0   0   0
##          2   0   0   0   0
##          3 102 122 217 128
##          4 118 121 150 218
TA_ent <- sum(diag(tt_ent)) / sum(tt_ent)

paste0("Tasa de aciertos con los datos de entrenamiento: ",
       round(TA_ent, 4) * 100,
       "%")
## [1] "Tasa de aciertos con los datos de entrenamiento: 36.99%"

Prueba

# Prueba
pred_prueba <- predict(arbol_cv,
                       prueba,
                       type = "raw")

tt_prueba <- table(Prediccion = pred_prueba,
                   Real = prueba$Satisfaction)

tt_prueba
##           Real
## Prediccion  1  2  3  4
##          1  0  0  0  0
##          2  0  0  0  0
##          3 25 31 45 47
##          4 31 29 47 39
TA_prueba <- sum(diag(tt_prueba)) / sum(tt_prueba)

paste0("Tasa de aciertos con los datos de prueba: ",
       round(TA_prueba, 4) * 100,
       "%")
## [1] "Tasa de aciertos con los datos de prueba: 28.57%"

Al analizar la matriz de confusión, se observa que el árbol de decisión tiende a predecir principalmente las clases 3 y 4. Esto indica que el modelo tiene dificultad para distinguir correctamente las clases 1 y 2. La tasa de aciertos en prueba fue baja, lo que sugiere que el árbol tiene poder predictivo limitado para clasificar los cuatro niveles de satisfacción.

KNN

Aplicar el método K-NN:

modelo_knn <- train.kknn(as.factor(entrenamiento_labels) ~ ., 
                         data = entrenamiento[, names(entrenamiento) != "Satisfaction"], 
                         kmax = 50)

modelo_knn
## 
## Call:
## train.kknn(formula = as.factor(entrenamiento_labels) ~ ., data = entrenamiento[,     names(entrenamiento) != "Satisfaction"], kmax = 50)
## 
## Type of response variable: nominal
## Minimal misclassification: 0.7040816
## Best kernel: optimal
## Best k: 50

El segundo modelo aplicado fue KNN. Este método clasifica cada empleado según la similitud con sus vecinos más cercanos. Se utilizó train.kknn() para explorar distintos valores de vecinos hasta un máximo de 50. El modelo recomendó utilizar k = 50, por lo cual se usó este valor en la clasificación final.

Validar la estabilidad del modelo:

entrenamiento_labels <- as.factor(entrenamiento_labels)
prueba_labels <- as.factor(prueba_labels)

entrenamiento_x <- entrenamiento[, names(entrenamiento) != "Satisfaction"]
prueba_x <- prueba[, names(prueba) != "Satisfaction"]

# Convertir Gender a variable numérica si aparece como texto
entrenamiento_x$Gender <- as.factor(entrenamiento_x$Gender)
prueba_x$Gender <- as.factor(prueba_x$Gender)

entrenamiento_x <- model.matrix(~ . - 1, data = entrenamiento_x)
prueba_x <- model.matrix(~ . - 1, data = prueba_x)

# Escalar variables
entrenamiento_x <- as.data.frame(scale(entrenamiento_x))
prueba_x <- as.data.frame(scale(prueba_x))

pred <- knn(train = entrenamiento_x,
            test = prueba_x,
            cl = entrenamiento_labels,
            k = 50)

confusionMatrix(data = pred,
                reference = prueba_labels)
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction  1  2  3  4
##          1  0  3  3  0
##          2  2  6  4  6
##          3 26 31 47 43
##          4 28 20 38 37
## 
## Overall Statistics
##                                           
##                Accuracy : 0.3061          
##                  95% CI : (0.2539, 0.3623)
##     No Information Rate : 0.3129          
##     P-Value [Acc > NIR] : 0.6207          
##                                           
##                   Kappa : 0.0155          
##                                           
##  Mcnemar's Test P-Value : 3.631e-14       
## 
## Statistics by Class:
## 
##                      Class: 1 Class: 2 Class: 3 Class: 4
## Sensitivity           0.00000  0.10000   0.5109   0.4302
## Specificity           0.97479  0.94872   0.5050   0.5865
## Pos Pred Value        0.00000  0.33333   0.3197   0.3008
## Neg Pred Value        0.80556  0.80435   0.6939   0.7135
## Prevalence            0.19048  0.20408   0.3129   0.2925
## Detection Rate        0.00000  0.02041   0.1599   0.1259
## Detection Prevalence  0.02041  0.06122   0.5000   0.4184
## Balanced Accuracy     0.48739  0.52436   0.5079   0.5084

Antes de aplicar KNN, se transformó la variable Gender a factor y luego se utilizaron variables numéricas mediante model.matrix(). También se escalaron los datos, ya que KNN depende de distancias y las variables con mayor magnitud pueden dominar el cálculo.

Validar la estabilidad del modelo:

exactitud <- numeric(length = 5)

for(i in 1:5){
  
  prueba_i <- employee[folds[[i]], ]
  
  entrenamiento_i <- employee[-folds[[i]], ]
  
  entrenamiento_labels_i <- as.factor(employee$Satisfaction[-folds[[i]]])
  
  prueba_labels_i <- as.factor(employee$Satisfaction[folds[[i]]])
  
  entrenamiento_x_i <- entrenamiento_i[, names(entrenamiento_i) != "Satisfaction"]
  
  prueba_x_i <- prueba_i[, names(prueba_i) != "Satisfaction"]

  entrenamiento_x_i$Gender <- as.factor(entrenamiento_x_i$Gender)
  
  prueba_x_i$Gender <- as.factor(prueba_x_i$Gender)
  
  entrenamiento_x_i <- model.matrix(~ . - 1,
                                    data = entrenamiento_x_i)
  
  prueba_x_i <- model.matrix(~ . - 1,
                             data = prueba_x_i)
  
  entrenamiento_x_i <- as.data.frame(scale(entrenamiento_x_i))
  
  prueba_x_i <- as.data.frame(scale(prueba_x_i))
  
  pred_i <- knn(train = entrenamiento_x_i,
                test = prueba_x_i,
                cl = entrenamiento_labels_i,
                k = 50)

  cm_i <- confusionMatrix(pred_i,
                          prueba_labels_i)
  
  exactitud[i] <- cm_i$overall["Accuracy"]
  
  cat("Fold", i,
      "- Exactitud:",
      exactitud[i],
      "\n")
}
## Fold 1 - Exactitud: 0.2687075 
## Fold 2 - Exactitud: 0.3071672 
## Fold 3 - Exactitud: 0.2789116 
## Fold 4 - Exactitud: 0.3152542 
## Fold 5 - Exactitud: 0.3027211
Exactitud_promedio <- round(mean(exactitud), 4) * 100

paste("Exactitud promedio:",
      Exactitud_promedio,
      "%")
## [1] "Exactitud promedio: 29.46 %"

La validación cruzada manual permite observar si el desempeño de KNN se mantiene relativamente constante en diferentes particiones de los datos.

Interpretación de los resultados finales:

set.seed(123)

train_control <- trainControl(method = "cv",
                              number = 10,
                              savePredictions = TRUE)

# Convertir Gender a factor
employee$Gender <- as.factor(employee$Gender)

# Convertir variables categóricas a numéricas
employee_x <- employee[, names(employee) != "Satisfaction"]

employee_x <- model.matrix(~ . - 1,
                           data = employee_x)

# Escalar variables
employee_norm <- as.data.frame(scale(employee_x))

# Unir con variable objetivo
employee_knn_final <- cbind(employee_norm,
                            Satisfaction = as.factor(employee$Satisfaction))

# Modelo KNN
knn_cv <- train(Satisfaction ~ .,
                data = employee_knn_final,
                method = "knn",
                trControl = train_control,
                tuneGrid = data.frame(k = 50))

knn_cv
## k-Nearest Neighbors 
## 
## 1470 samples
##   16 predictor
##    4 classes: '1', '2', '3', '4' 
## 
## No pre-processing
## Resampling: Cross-Validated (10 fold) 
## Summary of sample sizes: 1322, 1321, 1324, 1324, 1323, 1323, ... 
## Resampling results:
## 
##   Accuracy   Kappa     
##   0.3047805  0.01721416
## 
## Tuning parameter 'k' was held constant at a value of 50
# Matriz de confusión
confusionMatrix(data = pred,
                reference = prueba_labels)
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction  1  2  3  4
##          1  0  3  3  0
##          2  2  6  4  6
##          3 26 31 47 43
##          4 28 20 38 37
## 
## Overall Statistics
##                                           
##                Accuracy : 0.3061          
##                  95% CI : (0.2539, 0.3623)
##     No Information Rate : 0.3129          
##     P-Value [Acc > NIR] : 0.6207          
##                                           
##                   Kappa : 0.0155          
##                                           
##  Mcnemar's Test P-Value : 3.631e-14       
## 
## Statistics by Class:
## 
##                      Class: 1 Class: 2 Class: 3 Class: 4
## Sensitivity           0.00000  0.10000   0.5109   0.4302
## Specificity           0.97479  0.94872   0.5050   0.5865
## Pos Pred Value        0.00000  0.33333   0.3197   0.3008
## Neg Pred Value        0.80556  0.80435   0.6939   0.7135
## Prevalence            0.19048  0.20408   0.3129   0.2925
## Detection Rate        0.00000  0.02041   0.1599   0.1259
## Detection Prevalence  0.02041  0.06122   0.5000   0.4184
## Balanced Accuracy     0.48739  0.52436   0.5079   0.5084

El modelo KNN obtuvo una exactitud cercana al 30% en prueba y una exactitud promedio similar en la validación cruzada. Esto indica que el modelo es relativamente estable, pero su capacidad predictiva es limitada. Aunque se utilizaron transformaciones y escalamiento, las variables disponibles no permiten separar claramente los cuatro niveles de satisfacción.

Clasificador Bayesiano

Preparación inicial y limpieza de los datos:

Aplicar el Clasificador Bayesiano:

modelo_nb <- naiveBayes(Satisfaction ~ .,
                        data = entrenamiento)

modelo_nb
## 
## Naive Bayes Classifier for Discrete Predictors
## 
## Call:
## naiveBayes.default(x = X, y = Y, laplace = laplace)
## 
## A-priori probabilities:
## Y
##         1         2         3         4 
## 0.1870748 0.2066327 0.3120748 0.2942177 
## 
## Conditional probabilities:
##    Age
## Y       [,1]     [,2]
##   1 36.31818 8.789712
##   2 36.35391 8.813392
##   3 37.02997 8.828770
##   4 37.34971 9.841746
## 
##    Gender
## Y      Female      Male
##   1 0.4181818 0.5818182
##   2 0.3621399 0.6378601
##   3 0.4168937 0.5831063
##   4 0.4046243 0.5953757
## 
##    HourlyRate
## Y       [,1]     [,2]
##   1 64.70000 20.11976
##   2 67.50206 20.38359
##   3 64.72480 20.18529
##   4 66.78902 19.90001
## 
##    JobInvolvement
## Y       [,1]      [,2]
##   1 2.722727 0.7527313
##   2 2.674897 0.7196098
##   3 2.746594 0.6962688
##   4 2.765896 0.7263919
## 
##    MonthlyIncome
## Y       [,1]     [,2]
##   1 6230.464 4432.888
##   2 6418.255 4529.077
##   3 6514.967 4673.431
##   4 6457.890 4824.202
## 
##    NumCompaniesWorked
## Y       [,1]     [,2]
##   1 2.400000 2.256194
##   2 2.650206 2.442113
##   3 2.858311 2.494054
##   4 2.731214 2.635325
## 
##    PercentSalaryHike
## Y       [,1]     [,2]
##   1 15.40455 3.684470
##   2 15.45679 3.748441
##   3 15.07629 3.754729
##   4 15.15607 3.514596
## 
##    StockOptionLevel
## Y        [,1]      [,2]
##   1 0.8272727 0.8370321
##   2 0.7530864 0.7956109
##   3 0.8092643 0.8567452
##   4 0.7341040 0.8262673
## 
##    TotalWorkingYears
## Y       [,1]     [,2]
##   1 11.04545 7.459340
##   2 11.02881 7.024396
##   3 11.40599 7.784057
##   4 11.47399 8.420518
## 
##    TrainingTimesLastYear
## Y       [,1]     [,2]
##   1 2.840909 1.360620
##   2 2.744856 1.230100
##   3 2.822888 1.279822
##   4 2.803468 1.328218
## 
##    WorkLifeBalance
## Y       [,1]      [,2]
##   1 2.672727 0.7537921
##   2 2.810700 0.7020989
##   3 2.716621 0.6944916
##   4 2.783237 0.6910248
## 
##    YearsAtCompany
## Y       [,1]     [,2]
##   1 7.045455 5.861236
##   2 6.617284 5.561604
##   3 6.694823 5.951493
##   4 7.534682 6.787474
## 
##    YearsInCurrentRole
## Y       [,1]     [,2]
##   1 4.350000 3.556491
##   2 4.205761 3.593907
##   3 3.986376 3.480206
##   4 4.358382 3.667152
## 
##    YearsSinceLastPromotion
## Y       [,1]     [,2]
##   1 2.172727 3.110915
##   2 2.168724 3.023382
##   3 1.776567 2.836953
##   4 2.630058 3.660461
## 
##    YearsWithCurrManager
## Y       [,1]     [,2]
##   1 4.240909 3.524365
##   2 3.934156 3.468242
##   3 3.877384 3.523335
##   4 4.387283 3.642783
pred_nb <- predict(modelo_nb,
                   prueba)

tt <- table(pred_nb,
            prueba_labels)
tt
##        prueba_labels
## pred_nb  1  2  3  4
##       1  2  2  5  6
##       2  9  6 10  6
##       3 28 39 56 52
##       4 17 13 21 22
TA <- (sum(diag(tt))) / sum(tt)

paste("Tasa de aciertos: ",
      round(TA,4) * 100,
      "%",
      sep = "")
## [1] "Tasa de aciertos: 29.25%"

El Clasificador Bayesiano estima la probabilidad de que un empleado pertenezca a cada nivel de satisfacción según sus características. Luego asigna la clase con mayor probabilidad.

Validar la estabilidad del modelo:

set.seed(123)

data_cb <- employee %>%
  select(Age, Gender, HourlyRate, JobInvolvement, MonthlyIncome,
         NumCompaniesWorked, PercentSalaryHike, StockOptionLevel,
         TotalWorkingYears, TrainingTimesLastYear, WorkLifeBalance,
         YearsAtCompany, YearsInCurrentRole, YearsSinceLastPromotion,
         YearsWithCurrManager, Satisfaction)

train_control <- trainControl(method = "cv",
                              number = 4,
                              savePredictions = TRUE)

modelo_cv <- train(Satisfaction ~ .,
                   data = data_cb,
                   method = "naive_bayes",
                   trControl = train_control)

modelo_cv
## Naive Bayes 
## 
## 1470 samples
##   15 predictor
##    4 classes: '1', '2', '3', '4' 
## 
## No pre-processing
## Resampling: Cross-Validated (4 fold) 
## Summary of sample sizes: 1102, 1103, 1103, 1102 
## Resampling results across tuning parameters:
## 
##   usekernel  Accuracy   Kappa     
##   FALSE      0.2945667  0.01963484
##    TRUE      0.3142974  0.02591585
## 
## Tuning parameter 'laplace' was held constant at a value of 0
## Tuning
##  parameter 'adjust' was held constant at a value of 1
## Accuracy was used to select the optimal model using the largest value.
## The final values used for the model were laplace = 0, usekernel = TRUE
##  and adjust = 1.
confusionMatrix(modelo_cv$pred$pred,
                modelo_cv$pred$obs)
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction   1   2   3   4
##          1  63  52  68  86
##          2  40  37  67  61
##          3 296 348 533 455
##          4 153 169 250 262
## 
## Overall Statistics
##                                           
##                Accuracy : 0.3044          
##                  95% CI : (0.2878, 0.3214)
##     No Information Rate : 0.3122          
##     P-Value [Acc > NIR] : 0.8251          
##                                           
##                   Kappa : 0.0227          
##                                           
##  Mcnemar's Test P-Value : <2e-16          
## 
## Statistics by Class:
## 
##                      Class: 1 Class: 2 Class: 3 Class: 4
## Sensitivity           0.11413  0.06106   0.5806  0.30324
## Specificity           0.91374  0.92802   0.4565  0.72447
## Pos Pred Value        0.23420  0.18049   0.3266  0.31415
## Neg Pred Value        0.81692  0.79196   0.7057  0.71415
## Prevalence            0.18776  0.20612   0.3122  0.29388
## Detection Rate        0.02143  0.01259   0.1813  0.08912
## Detection Prevalence  0.09150  0.06973   0.5551  0.28367
## Balanced Accuracy     0.51393  0.49454   0.5185  0.51386

La validación cruzada permite evaluar el desempeño promedio del Clasificador Bayesiano en distintas particiones de los datos. Esto ofrece una medida más confiable que una sola división de entrenamiento y prueba.

Interpretación de los resultados finales

El Clasificador Bayesiano permitió clasificar el nivel de satisfacción utilizando un enfoque probabilístico. Este método tiene la ventaja de ser sencillo y rápido de implementar. Sin embargo, asume independencia entre las variables predictoras, lo cual puede no cumplirse completamente en un contexto laboral, ya que muchas variables pueden estar relacionadas entre sí.

Comparación general de los modelos

Los tres modelos utilizados permiten estudiar el nivel de satisfacción de los empleados desde perspectivas diferentes. El árbol de decisión ofrece una interpretación visual de las reglas de clasificación. KNN clasifica a los empleados según su similitud con otros casos. El Clasificador Bayesiano usa probabilidades condicionales para estimar la categoría más probable.

comparacion <- data.frame(
  Modelo = c("Árbol de decisión", "KNN", "Clasificador Bayesiano"),
  Exactitud = c(TA_prueba,
                mean(pred == prueba_labels),
                TA)
)

comparacion
##                   Modelo Exactitud
## 1      Árbol de decisión 0.2857143
## 2                    KNN 0.3061224
## 3 Clasificador Bayesiano 0.2925170

Conclusión general

En este trabajo se aplicaron tres metodologías de clasificación supervisada para predecir el nivel de satisfacción de los empleados utilizando la base de datos Employee-IBM.

Los Árboles de Decisión permitieron visualizar reglas asociadas a la clasificación de satisfacción laboral. KNN permitió clasificar empleados según su similitud con otros empleados luego de transformar y escalar los datos. Por otro lado, el Clasificador Bayesiano ofreció una alternativa probabilística simple y eficiente.

En cuanto al desempeño, los tres modelos obtuvieron exactitudes cercanas al No Information Rate, aproximadamente 31%. Esto sugiere que las variables disponibles tienen un poder predictivo limitado para distinguir claramente entre los cuatro niveles de satisfacción. Aunque KNN obtuvo una exactitud ligeramente mayor en la prueba, la diferencia entre los modelos fue pequeña.

Por esta razón, los resultados deben interpretarse con cautela. Las variables relacionadas con salario, experiencia, condiciones laborales y trayectoria en la empresa aportan información, pero no son suficientes para clasificar con alta precisión el nivel de satisfacción. La empresa podría complementar estos datos con factores cualitativos como ambiente laboral, relación con supervisores, motivación personal o cultura organizacional para mejorar la predicción y apoyar estrategias de retención de talento.