Python
R
Machine Learning
Autor/a

Joel Burbano

Fecha de publicación

11 de marzo de 2024

Introducción a la Regresión Logística

La regresión logística es una técnica de modelado estadístico utilizada para predecir el resultado de una variable categórica basada en una o más variables independientes. Es especialmente útil cuando queremos clasificar observaciones en dos o más clases. A diferencia de la regresión lineal, que predice valores continuos, la regresión logística predice probabilidades de pertenencia a una categoría.

¿Comó Funciona?

La regresión logística utiliza la función logística, también conocida como función sigmoide, para transformar la salida de una combinación lineal de las variables independientes. La función sigmoide produce valores entre 0 y 1, que pueden interpretarse como probabilidades.

Importante

La fórmula de la función sigmoide es:

\[\sigma(z)=\frac{1}{1+ e^{-z}}\]

donde \(z\) es la combinación lineal de las variables independientes, es decir \(z=\beta_0 + \sum_{i=1}^n \beta_i z_i\)

Ejemplo Práctico

Imaginemos que queremos predecir si un correo electrónico es spam o no, usando características como la frecuencia de ciertas palabras y la longitud del correo.

Paso 1: Importar Librerías

Código
import pandas as pd
pd.options.display.max_columns=None
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report
Código
library(dplyr)
library(caTools)
library(caret)

Paso 2: Cargar Datos

Código
colums = ["word_freq_make", "word_freq_address", "word_freq_all", "word_freq_3d", "word_freq_our",
"word_freq_over", "word_freq_remove", "word_freq_internet", "word_freq_order", "word_freq_mail",
"word_freq_receive", "word_freq_will", "word_freq_people", "word_freq_report", "word_freq_addresses",
"word_freq_free", "word_freq_business", "word_freq_email", "word_freq_you", "word_freq_credit","word_freq_your", "word_freq_font", "word_freq_000", "word_freq_money", "word_freq_hp", "word_freq_hpl", "word_freq_george", "word_freq_650", "word_freq_lab",
"word_freq_labs", "word_freq_telnet", "word_freq_857", "word_freq_data", "word_freq_415",
"word_freq_85", "word_freq_technology", "word_freq_1999", "word_freq_parts", "word_freq_pm",
"word_freq_direct", "word_freq_cs", "word_freq_meeting", "word_freq_original", "word_freq_project",
"word_freq_re", "word_freq_edu", "word_freq_table", "word_freq_conference", "char_freq_;",
"char_freq_(", "char_freq_[", "char_freq_!", "char_freq_$", "char_freq_#", 
"capital_run_length_average", "capital_run_length_longest","capital_run_length_total","spam"
]

data = pd.read_csv("spambase.data", header=None, names=colums)


X = data.drop(columns=['spam'])
y = data['spam']
Código
columns <- c("word_freq_make", "word_freq_address", "word_freq_all", "word_freq_3d", "word_freq_our",
"word_freq_over", "word_freq_remove", "word_freq_internet", "word_freq_order", "word_freq_mail",
"word_freq_receive", "word_freq_will", "word_freq_people", "word_freq_report", "word_freq_addresses",
"word_freq_free", "word_freq_business", "word_freq_email", "word_freq_you", "word_freq_credit","word_freq_your", "word_freq_font", "word_freq_000", "word_freq_money", "word_freq_hp", "word_freq_hpl", "word_freq_george", "word_freq_650", "word_freq_lab",
"word_freq_labs", "word_freq_telnet", "word_freq_857", "word_freq_data", "word_freq_415",
"word_freq_85", "word_freq_technology", "word_freq_1999", "word_freq_parts", "word_freq_pm",
"word_freq_direct", "word_freq_cs", "word_freq_meeting", "word_freq_original", "word_freq_project",
"word_freq_re", "word_freq_edu", "word_freq_table", "word_freq_conference", "char_freq_;",
"char_freq_(", "char_freq_[", "char_freq_!", "char_freq_$", "char_freq_#", 
"capital_run_length_average", "capital_run_length_longest","capital_run_length_total","spam")

data <- read.csv("spambase.data", header = FALSE, col.names = columns)

# Convertimos la variable dependiente en factor

data$spam <- as.factor(data$spam)

Paso 3: Dividir el Conjunto de Datos

Código
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
Código
set.seed(42)

split <- sample.split(data$spam, SplitRatio = 0.7)

train_data <- subset(data, split == TRUE)
test_data <- subset(data, split == FALSE)

Paso 4: Entrenar el Modelo

Código
model = LogisticRegression()

model.fit(X_train, y_train)
LogisticRegression()
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
Código
model <- glm(spam ~ ., data = train_data, family = binomial)

Paso 5: Evaluar el Modelo

Código
y_pred = model.predict(X_test)
print(f'Accuracy: {accuracy_score(y_test, y_pred)}')
Accuracy: 0.9268645908761767
Código
print('Confusion Matrix:')
Confusion Matrix:
Código
print(confusion_matrix(y_test, y_pred))
[[757  47]
 [ 54 523]]
Código
print('Clasification Report:')
Clasification Report:
Código
print(classification_report(y_test, y_pred))
              precision    recall  f1-score   support

           0       0.93      0.94      0.94       804
           1       0.92      0.91      0.91       577

    accuracy                           0.93      1381
   macro avg       0.93      0.92      0.92      1381
weighted avg       0.93      0.93      0.93      1381
Código
predictions <- predict(model, test_data, type = "response")
predicted_classes <- ifelse(predictions > 0.5, 1, 0)

# Calcular el accuracy del modelo
accuracy <- mean(predicted_classes == test_data$spam)
print(paste("Accuracy:", round(accuracy * 100, 2),"%"))
[1] "Accuracy: 92.46 %"
Código
# Matriz de consfusión
confusion <- table(Predicted = predicted_classes, Actual = test_data$spam)
print("Confusion Matrix:")
[1] "Confusion Matrix:"
Código
print(confusion)
         Actual
Predicted   0   1
        0 793  61
        1  43 483
Código
# Reporte de clasificacion
confusionMatrix(as.factor(predicted_classes), test_data$spam)
Confusion Matrix and Statistics

          Reference
Prediction   0   1
         0 793  61
         1  43 483
                                         
               Accuracy : 0.9246         
                 95% CI : (0.9094, 0.938)
    No Information Rate : 0.6058         
    P-Value [Acc > NIR] : < 2e-16        
                                         
                  Kappa : 0.8413         
                                         
 Mcnemar's Test P-Value : 0.09552        
                                         
            Sensitivity : 0.9486         
            Specificity : 0.8879         
         Pos Pred Value : 0.9286         
         Neg Pred Value : 0.9183         
             Prevalence : 0.6058         
         Detection Rate : 0.5746         
   Detection Prevalence : 0.6188         
      Balanced Accuracy : 0.9182         
                                         
       'Positive' Class : 0              
                                         

Resultados y Evaluación

En general se ha conseguido un accuracy de alrededor del \(92\%\) lo cual indica que el modelo predice un resultado correcto 92 de cada 100 veces, lo que en general es un buen modelo pero se lo podria mejorar seleccionando mejor las variables en este caso se ha utilizado todas sin un analisis de su poder predicitivo.

Ventajas y Desventajas

Ventajas

  • Interpretabilidad: Es fácil de entender y explicar

  • Eficiencia: Es computacionalmente menos costosa que otros métodos complejos

Desventajas

  • Linealidad: Asume una relación lineal entre las variables independientes y la probabilidad de la clase.

  • Limitación: La versión básica está diseñada para clasificación binaria.

Conclusión

La regresión logística es una herramienta poderosa y ampliamente utilizada en la ciencia de datos para problemas de clasificación. Su simplicidad y eficacia la hacen ideal para muchas aplicaciones, desde el diagnóstico médico hasta la detección de fraude.