Introducción:
Aplicamos Machine Learning para predecir la supervivencia de los pasajeros del Titanic usando regresión logística, un algoritmo supervisado adecuado para problemas de clasificación binaria.
El flujo de trabajo de Machine Learning que seguimos incluye:
Carga de datos:
rm(list = ls())
library(readr)
data_titanic <- read_csv("../Datas/Libro1-titanic.csv")
View(data_titanic)
class(data_titanic) # Debe ser data.frame
## [1] "spec_tbl_df" "tbl_df" "tbl" "data.frame"
Exploración y limpieza:
El Machine Learning requiere datos limpios. Primero revisamos si hay valores faltantes (NA) y los eliminamos.
library(VIM)
# Visualizamos los NA
aggr(data_titanic, numbers = TRUE)
# Eliminamos pasajeros sin edad registrada
No_NA_titanic <- subset(data_titanic, !is.na(data_titanic$age))
Seleccionamos las variables que creemos predictoras de la supervivencia:
survived → variable objetivo (0 = muerto, 1 = vivo)
sex, age, sibsp, class, alone → variables predictoras
library(dplyr)
Base_depurada <- No_NA_titanic %>%
select(survived, sex, age, sibsp, class, alone)
# Proporción de sobrevivientes
(prop.table(table(Base_depurada$survived))) * 100
##
## 0 1
## 59.38375 40.61625
En Machine Learning, es importante conocer la distribución de la variable objetivo para evitar problemas de clases desbalanceadas.
Interpretación
El 59% de los pasajeros no sobrevivieron El 41% de los pasajeros sobrevivieron
Esto significa que las clases no están perfectamente balanceadas, pero tampoco están extremadamente desbalanceadas.
Balance perfecto sería ~50%-50% Desbalance muy fuerte sería, por ejemplo, 90%-10%
Con ~59%-41%, el desbalance es moderado, así que un modelo como regresión logística funcionará razonablemente bien.
Un principio clave de ML: entrenar el modelo con datos que no veremos en la evaluación, y validarlo con datos nuevos. En Machine Learning es fundamental separar los datos en dos conjuntos:
Entrenamiento (train) → donde el modelo aprende los patrones de los datos.
Prueba (test) → donde el modelo se evalúa con datos que no ha visto antes, simulando su desempeño en situaciones reales.
Esta separación evita que el modelo se sobreajuste y nos da una medida realista de su capacidad predictiva.
library(caTools)
set.seed(123) # Fija la semilla para reproducibilidad
# Dividimos los datos: 70% entrenamiento, 30% prueba
data_70_30 <- sample.split(Base_depurada$survived, SplitRatio = 0.70)
data_train <- subset(Base_depurada, data_70_30 == TRUE)
data_test <- subset(Base_depurada, data_70_30 == FALSE)
# Revisión rápida de estructura de los conjuntos
str(data_train)
## tibble [500 × 6] (S3: tbl_df/tbl/data.frame)
## $ survived: num [1:500] 0 1 1 0 1 1 0 0 1 0 ...
## $ sex : chr [1:500] "male" "female" "female" "male" ...
## $ age : num [1:500] 22 26 35 54 27 14 39 14 55 31 ...
## $ sibsp : num [1:500] 1 0 1 0 0 1 1 0 0 1 ...
## $ class : chr [1:500] "Third" "Third" "First" "First" ...
## $ alone : logi [1:500] FALSE TRUE FALSE TRUE FALSE FALSE ...
str(data_test)
## tibble [214 × 6] (S3: tbl_df/tbl/data.frame)
## $ survived: num [1:214] 1 0 0 1 1 0 0 1 0 0 ...
## $ sex : chr [1:214] "female" "male" "male" "female" ...
## $ age : num [1:214] 38 35 2 4 58 20 2 15 8 42 ...
## $ sibsp : num [1:214] 1 0 3 1 0 0 4 0 3 1 ...
## $ class : chr [1:214] "First" "Third" "Third" "Third" ...
## $ alone : logi [1:214] FALSE TRUE FALSE FALSE TRUE TRUE ...
Distribución de la variable objetivo (sobrevivientes)
Es importante mantener la proporción de clases (balance) en ambos conjuntos, para que el modelo aprenda patrones representativos y no se sesgue hacia la clase mayoritaria.
# Porcentaje de sobrevivientes en entrenamiento
(prop.table(table(data_train$survived))) * 100
##
## 0 1
## 59.4 40.6
# Porcentaje de sobrevivientes en prueba
(prop.table(table(data_test$survived))) * 100
##
## 0 1
## 59.34579 40.65421
Mantener la proporción de clases en entrenamiento y prueba ayuda a que el modelo aprenda correctamente y funcione bien con datos nuevos.
glmEn Machine Learning supervisado, cuando nuestra
variable objetivo es binaria (0/1), como
survived en el Titanic, usamos la regresión
logística para predecir la probabilidad de que ocurra un
evento.
En R, se hace usando la función glm()
(Generalized Linear Model), que permite:
Antes de entrenar el modelo, es importante asegurarnos de que las variables categóricas estén correctamente definidas como factores, ya que R las trata de forma diferente a las numéricas:
# Convertimos la variable categórica "alone" a factor
data_train$alone <- as.factor(data_train$alone) #En train
data_test$alone <- as.factor(data_test$alone) # En Test
Luego, ajustamos el modelo usando todas las demás variables como predictores (“.” significa “todas las columnas excepto la variable dependiente survived):
# Ajuste del modelo de regresión logística (GLM)
modelo_glm <- glm(
survived ~ ., # Variable objetivo: survived
family = binomial(link = "logit"), # Modelo logístico
data = data_train # Usamos solo datos de entrenamiento
)
# Resumen de los coeficientes y su significancia
summary(modelo_glm)
##
## Call:
## glm(formula = survived ~ ., family = binomial(link = "logit"),
## data = data_train)
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) 4.485111 0.547241 8.196 2.49e-16 ***
## sexmale -2.560870 0.261078 -9.809 < 2e-16 ***
## age -0.046672 0.009765 -4.780 1.76e-06 ***
## sibsp -0.609121 0.196763 -3.096 0.001963 **
## classSecond -1.189615 0.341920 -3.479 0.000503 ***
## classThird -2.302076 0.338226 -6.806 1.00e-11 ***
## aloneTRUE -0.462332 0.318970 -1.449 0.147211
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 675.37 on 499 degrees of freedom
## Residual deviance: 447.75 on 493 degrees of freedom
## AIC: 461.75
##
## Number of Fisher Scoring iterations: 5
Entrenar un modelo significa encontrar los coeficientes \((\beta_0, \beta_1, \dots, \beta_k)\) que
mejor predicen la variable objetivo (survived) usando los
datos de entrenamiento. Estos coeficientes representan cómo cada
variable independiente (edad, sexo, clase, etc.) afecta la probabilidad
de supervivencia.
Una vez que tenemos nuestro modelo de regresión logística, necesitamos evaluar qué tan bien funciona. En Machine Learning esto se hace usando datos que el modelo ya vio (entrenamiento) y datos que nunca vio (prueba/test).
Paso 1: Predicciones en entrenamiento
# Predicciones de probabilidad para el conjunto de entrenamiento
ypred_prob_train <- predict(modelo_glm, newdata = data_train[,-1], type = "response")
# Convertimos probabilidades a clases (0 = no sobrevivió, 1 = sobrevivió)
ypred_train <- as.numeric(ypred_prob_train >= 0.5)
# Valores reales de la variable objetivo
ytrue_train <- data_train$survived
# Calculamos la exactitud (accuracy)
accuracy_train <- 1 - mean(ytrue_train != ypred_train)
accuracy_train
## [1] 0.798
Paso 2: Predicciones en prueba (test)
# Predicciones de probabilidad para el conjunto de prueba
ypred_prob_test <- predict(modelo_glm, newdata = data_test[,-1], type = "response")
# Convertimos a clases
ypred_test <- as.numeric(ypred_prob_test >= 0.5)
# Valores reales de la variable objetivo
ytrue_test <- data_test$survived
# Exactitud en el conjunto de prueba
accuracy_test <- 1 - mean(ytrue_test != ypred_test)
accuracy_test
## [1] 0.8037383
Conceptos clave de Machine Learning:
Métricas de Desempeño para Modelos de Clasificación
En problemas de Machine Learning supervisado, evaluamos nuestros modelos usando métricas derivadas de la matriz de confusión:
| Predicción Positiva (1) | Predicción Negativa (0) | |
|---|---|---|
| Real Positivo (1) | VP (Verdaderos Positivos) | FN (Falsos Negativos) |
| Real Negativo (0) | FP (Falsos Positivos) | VN (Verdaderos Negativos) |
Definición: Proporción de predicciones correctas sobre el total de observaciones.
Fórmula:
\[ \text{Accuracy} = \frac{VP + VN}{VP + VN + FP + FN} \]
Indica qué tan bien el modelo acierta en general.
Definición: Proporción de casos positivos correctamente identificados por el modelo.
Fórmula:
\[ \text{Sensibilidad} = \frac{VP}{VP + FN} \]
También se llama recall. Es importante cuando nos interesa no perder positivos reales, como sobrevivientes en Titanic.
Definición: Proporción de casos negativos correctamente identificados por el modelo.
Fórmula:
\[ \text{Especificidad} = \frac{VN}{VN + FP} \]
Evalúa la capacidad del modelo para identificar correctamente los negativos.
Definición: Proporción de predicciones positivas que realmente son positivas.
Fórmula:
\[ \text{Precisión} = \frac{VP}{VP + FP} \]
Útil cuando queremos que las predicciones positivas sean confiables.
caret::confusionMatrix().Matriz de Confusión
La matriz de confusión muestra verdaderos positivos, falsos positivos, verdaderos negativos y falsos negativos, métricas clave en ML
library(caret) #Este paquete incluye muchas herramientas para machine learning, entre ellas la matriz de confusión y métricas de desempeño.
# Para data Training
ypred_train_factor <- as.factor(ypred_train)
data_train$survived <- as.factor(data_train$survived)
confusionMatrix(ypred_train_factor, data_train$survived, positive = "1")
## Confusion Matrix and Statistics
##
## Reference
## Prediction 0 1
## 0 252 56
## 1 45 147
##
## Accuracy : 0.798
## 95% CI : (0.7601, 0.8323)
## No Information Rate : 0.594
## P-Value [Acc > NIR] : <2e-16
##
## Kappa : 0.5776
##
## Mcnemar's Test P-Value : 0.3197
##
## Sensitivity : 0.7241
## Specificity : 0.8485
## Pos Pred Value : 0.7656
## Neg Pred Value : 0.8182
## Prevalence : 0.4060
## Detection Rate : 0.2940
## Detection Prevalence : 0.3840
## Balanced Accuracy : 0.7863
##
## 'Positive' Class : 1
##
# Para data Test
ypred_test_factor <- as.factor(ypred_test)
data_test$survived <- as.factor(data_test$survived)
confusionMatrix(ypred_test_factor, data_test$survived, positive = "1")
## Confusion Matrix and Statistics
##
## Reference
## Prediction 0 1
## 0 110 25
## 1 17 62
##
## Accuracy : 0.8037
## 95% CI : (0.7441, 0.8547)
## No Information Rate : 0.5935
## P-Value [Acc > NIR] : 4.456e-11
##
## Kappa : 0.5873
##
## Mcnemar's Test P-Value : 0.2801
##
## Sensitivity : 0.7126
## Specificity : 0.8661
## Pos Pred Value : 0.7848
## Neg Pred Value : 0.8148
## Prevalence : 0.4065
## Detection Rate : 0.2897
## Detection Prevalence : 0.3692
## Balanced Accuracy : 0.7894
##
## 'Positive' Class : 1
##
La matriz de confusión permite evaluar precisión, sensibilidad y especificidad, esenciales para medir el desempeño de modelos de ML.
Curva ROC y Área Bajo la Curva (AUC)
En problemas de clasificación binaria, además de medir la exactitud (accuracy), es muy útil analizar la capacidad del modelo para distinguir entre clases. Para esto usamos la Curva ROC (Receiver Operating Characteristic) y el AUC (Area Under the Curve).
Curva ROC
La curva ROC compara:
La curva ROC muestra la relación entre la proporción de verdaderos positivos (sensibilidad) y la proporción de falsos positivos. Cada punto refleja cómo el modelo clasifica los sobrevivientes y no sobrevivientes.
La línea diagonal gris indica un modelo que predice al azar (AUC = 0.5), sin capacidad para diferenciar las clases.
Cuanto más cerca del borde superior izquierdo esté la curva, mejor es el modelo, porque significa que identifica correctamente la mayoría de los sobrevivientes sin confundir muchos pasajeros que no sobrevivieron.
Área Bajo la Curva (AUC)
library(ROCR)
# Para data Training
#Convertimos a numérico para ROC
pred_area_train <- prediction(as.numeric(ypred_train), as.numeric(ytrue_train))
#Calculamos el área bajo la curva
auc_train <- as.numeric(performance(pred_area_train, "auc")@y.values)
#Curva ROC
pred_curva_train <- performance(pred_area_train, "tpr", "fpr")
plot(pred_curva_train, col="green", lwd=2,
main=paste("Curva ROC - Data Training (AUC =", round(auc_train, 2), ")"),
xlab="1 - Especificidad (FPR)", ylab="Sensibilidad (TPR)")
abline(a=0, b=1, lty=2, col="gray40")
# Test
#Convertimos a numérico para ROC
pred_area_test <- prediction(as.numeric(ypred_test), as.numeric(ytrue_test))
#Calculamos el área bajo la curva
auc_test <- as.numeric(performance(pred_area_test, "auc")@y.values)
#Curva ROC
pred_curva_test <- performance(pred_area_test, "tpr", "fpr")
plot(pred_curva_test, col="blue", lwd=2,
main=paste("Curva ROC - Data Test (AUC =", round(auc_test, 2), ")"),
xlab="1 - Especificidad (FPR)", ylab="Sensibilidad (TPR)")
abline(a=0, b=1, lty=2, col="gray40")
Curvas ROC combinadas: Training vs Test Visualizamos simultáneamente la curva ROC de entrenamiento y prueba para evaluar generalización.
plot(pred_curva_train, col="green", lwd=1,
main="Curva ROC - Training vs Test",
xlab="1 - Especificidad (FPR)", ylab="Sensibilidad (TPR)")
plot(pred_curva_test, col="red", lwd=1, add=TRUE)
abline(a=0, b=1, lty=2, col="gray40")
legend("bottomright",
legend=c(paste("Training AUC =", round(auc_train,2)),
paste("Test AUC =", round(auc_test,2))),
col=c("green","red"), lwd=3)
Las curvas prácticamente se superponen → el modelo generaliza bien y no está sobreajustado.
Este ejercicio muestra cómo aplicar Machine Learning supervisado para problemas de clasificación binaria, usando la regresión logística para predecir la supervivencia de los pasajeros del Titanic.
El modelo construido no solo aprende de los datos de entrenamiento, sino que también generaliza bien a nuevos datos, cumpliendo con uno de los principios fundamentales de Machine Learning supervisado: aprender patrones y aplicarlos a casos no vistos.