Regresión Logística Intuición e Implementación
'Logistic Regression Intuition and Implementation' in English.
Las matemáticas detrás del algoritmo de Regresión Logística y su implementación desde cero usando Numpy.

Introducción
La Regresión Logística es un algoritmo fundamental de clasificación binaria que puede aprender un límite de decisión entre dos conjuntos de atributos de datos diferentes. En este artículo, comprendemos el aspecto teórico detrás del modelo de clasificación e implementamos usando Python.
Intuición
Conjunto de Datos
La Regresión Logística es un algoritmo de aprendizaje supervisado, por lo que tenemos atributos de características de datos y sus etiquetas correspondientes. Las características son variables independientes, representadas por X, y se representan en un arreglo unidimensional. Las etiquetas de clase, representadas por y, son 0 o 1. Por lo tanto, la Regresión Logística es un algoritmo de clasificación binaria.
Si el conjunto de datos tiene d-características:
Función de Costo
Similar a la Regresión Lineal, tenemos pesos asociados para los atributos de características y un valor de sesgo.
- Investigadores de UC Santa Cruz y Samsung presentan ESC un agente d...
- Tutorial de IA Cómo lanzar la aplicación de chat de IA en Streamlit...
- Conoce a CLAMP una nueva herramienta de IA para la predicción de la...
Nuestro objetivo es encontrar los valores óptimos para los pesos y el sesgo, para ajustar mejor nuestros datos.
Tenemos un valor de peso asociado con cada atributo de características y un solo valor de sesgo.
Inicializamos estos valores aleatoriamente y los optimizamos usando Descenso del Gradiente. Durante el entrenamiento, tomamos el producto punto entre los pesos y las características y agregamos el término de sesgo.
Pero debido a que nuestras etiquetas objetivo son 0 y 1, usamos una función Sigmoide no lineal, representada por g, que empuja nuestros valores entre el rango requerido.
La función sigmoide graficada es la siguiente:

La Regresión Logística tiene como objetivo aprender los pesos y el sesgo de manera que los valores pasados a la función sigmoide sean positivos para etiquetas positivas y negativos para etiquetas negativas.
Para predecir valores en la Regresión Logística, pasamos nuestras predicciones a la función sigmoide. Por lo tanto, la función de predicción es:
Ahora que tenemos las predicciones de nuestro modelo, podemos compararlas con las etiquetas objetivo originales. El error entre las predicciones se calcula usando la Pérdida de Entropía Cruzada Binaria. La función de pérdida es la siguiente:
donde y es la etiqueta objetivo original, y p es el valor predicho entre [0,1]. La función de pérdida tiene como objetivo acercar los valores predichos a las etiquetas objetivo reales. Si la etiqueta es 0 y el modelo predice 0, la pérdida es 0. De manera similar, si tanto las etiquetas predichas como las objetivo son 1, la pérdida es 0. De lo contrario, el modelo intenta converger a estos valores.
Descenso del Gradiente
Usamos la función de costo y obtenemos la derivada con respecto a los pesos y el sesgo. Usando la regla de la cadena y la derivación matemática, las derivadas son las siguientes:
Obtenemos un valor escalar que podemos usar para actualizar los pesos y sesgos.
Esto actualiza los valores en función del gradiente de pérdida, por lo que después de múltiples iteraciones, convergemos gradualmente hacia los valores óptimos de los pesos y sesgos.
Durante la inferencia, podemos utilizar los valores de los pesos y sesgos para obtener predicciones.
Implementación
Utilizamos las fórmulas matemáticas mencionadas anteriormente para codificar el modelo de Regresión Logística y evaluaremos su rendimiento en algunos conjuntos de datos de referencia.
Primero, inicializamos la clase y los parámetros.
class LogisticRegression(): def __init__( self, learning_rate:float=0.001, n_iters:int=10000 ) -> None: self.n_iters = n_iters self.lr = learning_rate self.weights = None self.bias = None
Requerimos los valores de los pesos y sesgos que se optimizarán, por lo que los inicializamos aquí como atributos del objeto. Sin embargo, no podemos establecer el tamaño aquí ya que depende de los datos pasados durante el entrenamiento. Por lo tanto, los configuramos como None por ahora. La tasa de aprendizaje y el número de iteraciones son hiperparámetros que se pueden ajustar para mejorar el rendimiento.
Entrenamiento
def fit( self, X : np.ndarray, y : np.ndarray ): n_samples, n_features = X.shape # Inicializar los Pesos y Sesgo con Valores Aleatorios # El tamaño de la matriz de pesos se basa en el número de características de los datos # El sesgo es un valor escalar self.weights = np.random.rand(n_features) self.bias = 0 for iteration in range(self.n_iters): # Obtener predicciones del modelo linear_pred = np.dot(X, self.weights) + self.bias predictions = sigmoid(linear_pred) loss = predictions - y # Descenso del Gradiente basado en la Pérdida dw = (1 / n_samples) * np.dot(X.T, loss) db = (1 / n_samples) * np.sum(loss) # Actualizar los Parámetros del Modelo self.weights = self.weights - self.lr * dw self.bias = self.bias - self.lr * db
La función de entrenamiento inicializa los valores de los pesos y sesgos. Luego iteramos sobre el conjunto de datos varias veces, optimizando estos valores hasta la convergencia, de manera que la pérdida se minimice.
Basándonos en las ecuaciones anteriores, la función sigmoidal se implementa de la siguiente manera:
def sigmoid(x): return 1 / (1 + np.exp(-x))
Luego usamos esta función para generar predicciones usando:
linear_pred = np.dot(X, self.weights) + self.biaspredictions = sigmoid(linear_pred)
Calculamos la pérdida sobre estos valores y optimizamos nuestros pesos:
loss = predictions - y # Descenso del Gradiente basado en la Pérdidadw = (1 / n_samples) * np.dot(X.T, loss)db = (1 / n_samples) * np.sum(loss)# Actualizar los Parámetros del Modeloself.weights = self.weights - self.lr * dwself.bias = self.bias - self.lr * db
Inferencia
def predict( self, X : np.ndarray, threshold:float=0.5 ): linear_pred = np.dot(X, self.weights) + self.bias predictions = sigmoid(linear_pred) # Convertir a Etiqueta 0 o 1 y_pred = [0 if y <= threshold else 1 for y in predictions] return y_pred
Una vez que hemos ajustado nuestros datos durante el entrenamiento, podemos usar los pesos y sesgos aprendidos para generar predicciones de manera similar. La salida del modelo está en el rango [0, 1], según la función sigmoidal. Luego podemos usar un valor de umbral, como 0.5. Todos los valores por encima de esta probabilidad se etiquetan como etiquetas positivas y todos los valores por debajo de este umbral se etiquetan como etiquetas negativas.
Código Completo
import numpy as npdef sigmoid(x): return 1 / (1 + np.exp(-x))class LogisticRegression(): def __init__( self, learning_rate:float=0.001, n_iters:int=10000 ) -> None: self.n_iters = n_iters self.lr = learning_rate self.weights = None self.bias = None def fit( self, X : np.ndarray, y : np.ndarray ): n_samples, n_features = X.shape # Inicializar los Pesos y Sesgo con Valores Aleatorios # El tamaño de la matriz de pesos se basa en el número de características de los datos # El sesgo es un valor escalar self.weights = np.random.rand(n_features) self.bias = 0 for iteration in range(self.n_iters): # Obtener predicciones del modelo linear_pred = np.dot(X, self.weights) + self.bias predictions = sigmoid(linear_pred) loss = predictions - y # Descenso del Gradiente basado en la Pérdida dw = (1 / n_samples) * np.dot(X.T, loss) db = (1 / n_samples) * np.sum(loss) # Actualizar los Parámetros del Modelo self.weights = self.weights - self.lr * dw self.bias = self.bias - self.lr * db def predict( self, X : np.ndarray, threshold:float=0.5 ): linear_pred = np.dot(X, self.weights) + self.bias predictions = sigmoid(linear_pred) # Convertir a Etiqueta 0 o 1 y_pred = [0 if y <= threshold else 1 for y in predictions] return y_pred
Evaluación
import numpy as npimport matplotlib.pyplot as pltfrom sklearn.model_selection import train_test_splitfrom sklearn.datasets import load_breast_cancerfrom sklearn.metrics import accuracy_scorefrom model import LogisticRegressionif __name__ == "__main__": data = load_breast_cancer() X, y = data.data, data.target X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle=True) model = LogisticRegression() model.fit(X_train, y_train) y_pred = model.predict(X_test) score = accuracy_score(y_pred, y_test) print(score)
Podemos usar el script anterior para probar nuestro modelo de Regresión Logística. Utilizamos el conjunto de datos de Cáncer de Mama de Scikit-Learn para el entrenamiento. Luego podemos comparar nuestras predicciones con las etiquetas originales.
Ajustando cuidadosamente algunos de los hiperparámetros, obtuve una puntuación de precisión por encima del 90%.
Podemos utilizar diferentes técnicas de reducción de dimensionalidad, como PCA, para visualizar el límite de decisión. Después de reducir nuestras características a dos dimensiones, obtenemos el siguiente límite de decisión.

Conclusión
En conclusión, este artículo explora la intuición matemática de la Regresión Logística y demuestra su implementación utilizando NumPy. La Regresión Logística es un valioso algoritmo de clasificación que utiliza la función sigmoide y el descenso de gradiente para encontrar un límite de decisión óptimo para la clasificación binaria.
Para el código y la implementación, consulte este repositorio de GitHub. Síganme para obtener más artículos sobre arquitecturas de aprendizaje profundo y avances en investigación.