Implementación de la Regresión Logística para la Clasificación Multiclase en Python: Una Guía Integral
En el campo en constante evolución del aprendizaje automático, la clasificación multiclase se presenta como una tarea fundamental, permitiendo la diferenciación entre múltiples categorías dentro de un conjunto de datos. Entre la miríada de algoritmos disponibles, la Regresión Logística surge como una opción robusta e interpretable para abordar tales problemas. En esta guía, profundizamos en la implementación de la regresión logística para la clasificación multiclase usando Python, aprovechando herramientas como Scikit-learn y un conjunto de datos de música Bangla obtenido de Kaggle.
Tabla de Contenidos
- Introducción a la Clasificación Multiclase
- Comprensión del Conjunto de Datos
- Preprocesamiento de Datos
- Selección de Características
- Entrenamiento y Evaluación del Modelo
- Análisis Comparativo
- Conclusión
- Implementación Completa en Python
Introducción a la Clasificación Multiclase
La clasificación multiclase es un tipo de tarea de clasificación donde cada instancia se categoriza en una de tres o más clases. A diferencia de la clasificación binaria, que trata con dos clases, la clasificación multiclase presenta desafíos únicos y requiere algoritmos que puedan distinguir efectivamente entre múltiples categorías.
Regresión Logística es tradicionalmente conocida por la clasificación binaria pero puede extenderse para manejar escenarios multiclase utilizando estrategias como Uno contra el Resto (OvR) o enfoques multinomial. Su simplicidad, interpretabilidad y eficiencia la convierten en una opción popular para diversas tareas de clasificación.
Comprensión del Conjunto de Datos
Para esta guía, utilizamos el Conjunto de Datos de Música Bangla, que contiene características extraídas de canciones Bangla. El objetivo principal es clasificar las canciones en géneros basados en estas características. El conjunto de datos incluye varias características de audio como centroides espectrales, ancho de banda espectral, frecuencia de croma y coeficientes espectrales de Mel (MFCCs).
Fuente del Conjunto de Datos: Kaggle – Conjunto de Datos de Música Bangla
Descripción de Muestra de Datos
1 2 3 4 5 |
import pandas as pd # Cargar el conjunto de datos data = pd.read_csv('bangla.csv') print(data.tail()) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
file_name zero_crossing \ 1737 Tumi Robe Nirobe, Artist - DWIJEN MUKHOPADHYA... 78516 1738 TUMI SANDHYAR MEGHMALA Srikanta Acharya Rabi... 176887 1739 Utal Haowa Laglo Amar Gaaner Taranite Sagar S... 133326 1740 venge mor ghorer chabi by anima roy.. album ro... 179932 1741 vora thak vora thak by anima roy ( 160kbps ).mp3 175244 spectral_centroid spectral_rolloff spectral_bandwidth \ 1737 800.797115 1436.990088 1090.389766 1738 1734.844686 3464.133429 1954.831684 1739 1380.139172 2745.410904 1775.717428 1740 1961.435018 4141.554401 2324.507425 1741 1878.657768 3877.461439 2228.147952 chroma_frequency rmse delta melspectogram tempo \ 1737 0.227325 0.108344 2.078194e-08 3.020211 117.453835 1738 0.271189 0.124934 5.785562e-08 4.098559 129.199219 1739 0.263462 0.111411 4.204189e-08 3.147722 143.554688 1740 0.261823 0.168673 3.245319e-07 7.674615 143.554688 1741 0.232985 0.311113 1.531590e-07 26.447679 129.199219 ... mfcc11 mfcc12 mfcc13 mfcc14 mfcc15 mfcc16 \ 1737 ... -2.615630 2.119485 -12.506942 -1.148996 0.090582 -8.694072 1738 ... 1.693247 -4.076407 -2.017894 -7.419591 -0.488603 -8.690254 1739 ... 2.487961 -3.434017 -6.099467 -6.008315 -7.483330 -2.908477 1740 ... 1.192605 -13.142963 0.281834 -5.981567 -1.066383 0.677886 1741 ... -5.636770 -12.078487 1.692546 -6.005674 1.502304 -0.415201 mfcc17 mfcc18 mfcc19 label 1737 -6.597594 2.925687 -6.154576 rabindra 1738 -7.090489 -6.530357 -5.593533 rabindra 1739 0.783345 -3.394053 -3.157621 rabindra 1740 0.803132 -3.304548 4.309490 rabindra 1741 2.389623 -3.135799 0.225479 rabindra [5 filas x 31 columnas] |
Preprocesamiento de Datos
Un preprocesamiento de datos efectivo es primordial para construir un modelo de aprendizaje automático confiable. Esta sección describe los pasos realizados para preparar los datos para el modelado.
Manejo de Datos Faltantes
Los datos faltantes pueden afectar negativamente el rendimiento de los modelos de aprendizaje automático. Es crucial identificar y manejar apropiadamente los valores faltantes.
Datos Numéricos
Para las características numéricas, los valores faltantes se imputan utilizando la estrategia de media.
1 2 3 4 5 6 7 8 9 10 11 12 |
import numpy as np from sklearn.impute import SimpleImputer # Identificar columnas numéricas numerical_cols = list(np.where((X.dtypes == np.int64) | (X.dtypes == np.float64))[0]) # Inicializar SimpleImputer para la estrategia de media imp_mean = SimpleImputer(missing_values=np.nan, strategy='mean') # Ajustar y transformar los datos imp_mean.fit(X.iloc[:, numerical_cols]) X.iloc[:, numerical_cols] = imp_mean.transform(X.iloc[:, numerical_cols]) |
Datos Categóricos
Para las características categóricas, los valores faltantes se imputan utilizando la estrategia más frecuente.
1 2 3 4 5 6 7 8 9 |
# Identificar columnas de texto string_cols = list(np.where((X.dtypes == object))[0]) # Inicializar SimpleImputer para la estrategia más frecuente imp_freq = SimpleImputer(missing_values=np.nan, strategy='most_frequent') # Ajustar y transformar los datos imp_freq.fit(X.iloc[:, string_cols]) X.iloc[:, string_cols] = imp_freq.transform(X.iloc[:, string_cols]) |
Codificación de Variables Categóricas
Los algoritmos de aprendizaje automático requieren entradas numéricas. Por lo tanto, las variables categóricas necesitan ser codificadas apropiadamente.
Codificación One-Hot
Para características categóricas con un alto número de categorías únicas, se emplea la Codificación One-Hot para evitar la introducción de relaciones ordinales.
1 2 3 4 5 6 7 8 9 |
from sklearn.compose import ColumnTransformer from sklearn.preprocessing import OneHotEncoder def OneHotEncoderMethod(indices, data): columnTransformer = ColumnTransformer( [('encoder', OneHotEncoder(), indices)], remainder='passthrough' ) return columnTransformer.fit_transform(data) |
Codificación de Etiquetas
Para características categóricas binarias o aquellas con un número manejable de categorías, se utiliza la Codificación de Etiquetas.
1 2 3 4 5 6 |
from sklearn import preprocessing def LabelEncoderMethod(series): le = preprocessing.LabelEncoder() le.fit(series) return le.transform(series) |
Selección de Codificación para X
Se aplica una combinación de estrategias de codificación basada en el número de categorías únicas en cada característica.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
def EncodingSelection(X, threshold=10): # Paso 01: Seleccionar las columnas de texto string_cols = list(np.where((X.dtypes == object))[0]) one_hot_encoding_indices = [] # Paso 02: Codificar con etiquetas columnas con 2 o más de 'threshold' categorías for col in string_cols: length = len(pd.unique(X[X.columns[col]])) if length == 2 or length > threshold: X[X.columns[col]] = LabelEncoderMethod(X[X.columns[col]]) else: one_hot_encoding_indices.append(col) # Paso 03: Codificar one-hot las columnas restantes X = OneHotEncoderMethod(one_hot_encoding_indices, X) return X # Aplicar selección de codificación X = EncodingSelection(X) print(f"Forma de características codificadas: {X.shape}") |
Salida:
1 |
Encoded feature shape: (1742, 30) |
Selección de Características
Seleccionar las características más relevantes mejora el rendimiento del modelo y reduce la complejidad computacional.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
from sklearn.feature_selection import SelectKBest, chi2 from sklearn import preprocessing # Inicializar Min-Max Scaler MMS = preprocessing.MinMaxScaler() # Definir número de mejores características a seleccionar K_features = 12 # Escalar las características x_temp = MMS.fit_transform(X) # Aplicar SelectKBest con función de puntuación chi-cuadrado kbest = SelectKBest(score_func=chi2, k=10) x_temp = kbest.fit(x_temp, y) # Identificar las mejores características best_features = np.argsort(x_temp.scores_)[-K_features:] # Determinar características a eliminar features_to_delete = np.argsort(x_temp.scores_)[:-K_features] # Reducir X a las características seleccionadas X = np.delete(X, features_to_delete, axis=1) print(f"Forma de características reducidas: {X.shape}") |
Salida:
1 |
Reduced feature shape: (1742, 12) |
Entrenamiento y Evaluación del Modelo
Con los datos preprocesados y las características seleccionadas, procedemos a entrenar y evaluar nuestros modelos.
Clasificador K-Nearest Neighbors (KNN)
KNN es un algoritmo de aprendizaje basado en instancias simple que puede servir como una línea base para tareas de clasificación.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
from sklearn.neighbors import KNeighborsClassifier from sklearn.metrics import accuracy_score # Inicializar KNN con 8 vecinos knnClassifier = KNeighborsClassifier(n_neighbors=8) # Entrenar el modelo knnClassifier.fit(X_train, y_train) # Hacer predicciones y_pred_knn = knnClassifier.predict(X_test) # Evaluar precisión knn_accuracy = accuracy_score(y_pred_knn, y_test) print(f"KNN Accuracy: {knn_accuracy:.2f}") |
Salida:
1 |
KNN Accuracy: 0.68 |
Modelo de Regresión Logística
La Regresión Logística se extiende aquí para manejar clasificación multiclase utilizando el enfoque multinomial.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
from sklearn.linear_model import LogisticRegression # Inicializar Regresión Logística con iteraciones incrementadas LRM = LogisticRegression(random_state=0, max_iter=1000, multi_class='multinomial', solver='lbfgs') # Entrenar el modelo LRM.fit(X_train, y_train) # Hacer predicciones y_pred_lr = LRM.predict(X_test) # Evaluar precisión lr_accuracy = accuracy_score(y_pred_lr, y_test) print(f"Logistic Regression Accuracy: {lr_accuracy:.2f}") |
Salida:
1 |
Logistic Regression Accuracy: 0.65 |
Análisis Comparativo
Al evaluar ambos modelos, el clasificador K-Nearest Neighbors supera a la Regresión Logística en este escenario particular.
- Precisión de KNN: 67.9%
- Precisión de Regresión Logística: 65.0%
Sin embargo, es esencial notar las siguientes observaciones:
- Advertencia de Límite de Iteraciones: Inicialmente, la regresión logística enfrentó problemas de convergencia, los cuales se resolvieron incrementando el parámetro
max_iter
de 300 a 1000. - Rendimiento del Modelo: Aunque KNN mostró mayor precisión, la Regresión Logística ofrece mejor interpretabilidad y puede ser más escalable con conjuntos de datos más grandes.
Mejoras Futuras:
- Ajuste de Hiperparámetros: Ajustar parámetros como
C
,penalty
y otros en la Regresión Logística puede llevar a un rendimiento mejorado. - Validación Cruzada: Implementar técnicas de validación cruzada puede proporcionar una evaluación más robusta del rendimiento del modelo.
- Ingeniería de Características: Crear o seleccionar características más informativas puede mejorar la precisión de la clasificación.
Conclusión
Esta guía integral demuestra la implementación de la Regresión Logística para clasificación multiclase en Python, destacando todo el proceso desde el preprocesamiento de datos hasta la evaluación del modelo. Aunque KNN mostró mejor precisión en este caso, la Regresión Logística sigue siendo una herramienta poderosa, especialmente cuando la interpretabilidad es una prioridad. Al seguir un preprocesamiento estructurado, selección de características y entrenamiento de modelos reflexivo, uno puede abordar efectivamente problemas de clasificación multiclase en diversos dominios.
Implementación Completa en Python
Abajo está el código completo en Python que encapsula todos los pasos discutidos:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# Importar bibliotecas necesarias import pandas as pd import numpy as np import seaborn as sns from sklearn.impute import SimpleImputer from sklearn.compose import ColumnTransformer from sklearn.preprocessing import OneHotEncoder, LabelEncoder, StandardScaler, MinMaxScaler from sklearn.feature_selection import SelectKBest, chi2 from sklearn.model_selection import train_test_split from sklearn.neighbors import KNeighborsClassifier from sklearn.linear_model import LogisticRegression from sklearn.metrics import accuracy_score # Cargar el conjunto de datos data = pd.read_csv('bangla.csv') # Separar características y objetivo X = data.iloc[:, :-1] y = data.iloc[:, -1] # Manejo de datos faltantes - Tipo numérico numerical_cols = list(np.where((X.dtypes == np.int64) | (X.dtypes == np.float64))[0]) imp_mean = SimpleImputer(missing_values=np.nan, strategy='mean') imp_mean.fit(X.iloc[:, numerical_cols]) X.iloc[:, numerical_cols] = imp_mean.transform(X.iloc[:, numerical_cols]) # Manejo de datos de texto faltantes string_cols = list(np.where((X.dtypes == object))[0]) imp_freq = SimpleImputer(missing_values=np.nan, strategy='most_frequent') imp_freq.fit(X.iloc[:, string_cols]) X.iloc[:, string_cols] = imp_freq.transform(X.iloc[:, string_cols]) # Métodos de codificación def OneHotEncoderMethod(indices, data): columnTransformer = ColumnTransformer( [('encoder', OneHotEncoder(), indices)], remainder='passthrough' ) return columnTransformer.fit_transform(data) def LabelEncoderMethod(series): le = LabelEncoder() le.fit(series) return le.transform(series) def EncodingSelection(X, threshold=10): string_cols = list(np.where((X.dtypes == object))[0]) one_hot_encoding_indices = [] for col in string_cols: length = len(pd.unique(X[X.columns[col]])) if length == 2 or length > threshold: X[X.columns[col]] = LabelEncoderMethod(X[X.columns[col]]) else: one_hot_encoding_indices.append(col) X = OneHotEncoderMethod(one_hot_encoding_indices, X) return X # Aplicar selección de codificación X = EncodingSelection(X) print(f"Forma de características codificadas: {X.shape}") # Selección de características MMS = MinMaxScaler() K_features = 12 x_temp = MMS.fit_transform(X) kbest = SelectKBest(score_func=chi2, k=10) x_temp = kbest.fit(x_temp, y) best_features = np.argsort(x_temp.scores_)[-K_features:] features_to_delete = np.argsort(x_temp.scores_)[:-K_features] X = np.delete(X, features_to_delete, axis=1) print(f"Forma de características reducidas: {X.shape}") # División de entrenamiento y prueba X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.20, random_state=1 ) print(f"Forma del conjunto de entrenamiento: {X_train.shape}") # Escalado de características sc = StandardScaler(with_mean=False) sc.fit(X_train) X_train = sc.transform(X_train) X_test = sc.transform(X_test) print(f"Forma del conjunto de entrenamiento escalado: {X_train.shape}") print(f"Forma del conjunto de prueba escalado: {X_test.shape}") # Construcción del modelo KNN knnClassifier = KNeighborsClassifier(n_neighbors=8) knnClassifier.fit(X_train, y_train) y_pred_knn = knnClassifier.predict(X_test) knn_accuracy = accuracy_score(y_pred_knn, y_test) print(f"Precisión de KNN: {knn_accuracy:.2f}") # Construcción del modelo de Regresión Logística LRM = LogisticRegression(random_state=0, max_iter=1000, multi_class='multinomial', solver='lbfgs') LRM.fit(X_train, y_train) y_pred_lr = LRM.predict(X_test) lr_accuracy = accuracy_score(y_pred_lr, y_test) print(f"Precisión de Regresión Logística: {lr_accuracy:.2f}") |
Nota: Asegúrate de que el conjunto de datos bangla.csv
esté correctamente colocado en tu directorio de trabajo antes de ejecutar el código.
Palabras Clave
- Regresión Logística
- Clasificación Multiclase
- Tutorial de Python
- Aprendizaje Automático
- Preprocesamiento de Datos
- Selección de Características
- K-Nearest Neighbors (KNN)
- Scikit-learn
- Ciencia de Datos
- Aprendizaje Automático en Python