====== 12 - Modelos clasificación 1: Regresión logística ======
La regresión logística es un clasificador binario derivado de la regresión lineal.
El modelo de regresión lineal es:
;#;
$\displaystyle y = \beta_{0} + \beta_{1}x_{1} + \beta_{2}x_{2} + \beta_{3}x_{3}+ ... + \beta_{i}x_{i}$
;#;
Si nuestra variable respuesta sólo puede tener 2 posibles valores (0 o 1) como en un clasificador, podemos ajustar un modelo de regresión lineal con el método de mínimos cuadrados. El problema es que, al generar una recta, podemos obtener valores por encima del 1 o por debajo del 0, con lo que no se cumpliría la condición que toda probabilidad tiene que estar en el intervalo [0,1].
Para solucionarlo, la regresión logística transforma esos valores que devuelve la regresión lineal mediante una función cuyo resultado siempre está comprendido entre 0 y 1. Esta función es la **función sigmoide** (también llamada //función logística//):
;#;
$\displaystyle sigmoide = \sigma(y) = \frac{1}{1 + e^{-y}}$
;#;
Al darnos resultados entre 0 y 1, podemos interpretar la ecuación anterior como la probabilidad que una instancia x pertenezca a la clase positiva (1).
Sustituimos la //y// de la ecuación anterior por el modelo de regresión lineal:
;#;
$\displaystyle P(y=1|X=x) = \frac{1}{1 + e^{-y}} = \frac{1}{1 + \frac{1}{e^{y}}} = \frac{1}{\frac{1 + e^{y}}{e^{y}}} = \frac{e^{y}}{1 + e^{y}} = \frac{e^{\beta_{0} + \beta_{1}x_{1} + ... + \beta_{i}x_{i}}}{1 + e^{\beta_{0} + \beta_{1}x_{1} + ... + \beta_{i}x_{i}}}$
;#;
**P(y=1|X=x)** es la probabilidad de que la variable respuesta //y// sea igual a 1 dado los predictores x1, x2...xp
La fórmula resultante tiene los coeficientes de regresión en el exponente, con lo que no se puede ajustar con el método de mínimos cuadrados. Para solucionarlo, podemos usar el logaritmo sobre la razón de la probabilidad positiva y la negativa.
La probabilidad positiva es:
;#;
$\displaystyle P(y=1|X=x) = \frac{e^{y}}{1 + e^{y}}$
;#;
La probabilidad negativa es 1 - probabilidad positiva (recordad que la suma de probabilidades debe dar 1):
;#;
$\displaystyle P(y=0|X=x) = 1 - P(y=1|X=x) = 1 - \frac{e^{y}}{1 + e^{y}} = \frac{1 + e^{y} - e^{y}}{1 + e^{y}} = \frac{1}{1 + e^{y}}$
;#;
Razón entre ambas probabilidades:
;#;
$\displaystyle \frac{P(y=1|X=x)}{P(y=0|X=x} = \frac{\frac{e^{y}}{1 + e^{y}}}{\frac{1}{1 + e^{y}}} = \frac{(e^{y})(1 + e^{y})}{1+e^{y}} = e^{y} = e^{\beta_{0} + \beta_{1}x_{1} + ... + \beta_{i}x_{i}}$
;#;
Aplicamos el logaritmo neperiano:
;#;
$\displaystyle ln(\frac{P(y=1|X=x)}{P(y=0|X=x}) = ln(e^{\beta_{0} + \beta_{1}x_{1} + ... + \beta_{i}x_{i}}) = \beta_{0} + \beta_{1}x_{1} + ... + \beta_{i}x_{i}$
;#;
Como vemos, el logaritmo de la razón de probabilidades nos da la ecuación de un modelo lineal, con lo que podemos convertir un problema de clasificación no lineal en un problema de regresión lineal que podemos ajustar con los métodos convencionales.
El logaritmo de la razón de probabilidades se conoce como **log of odds**. Los **odds** (razón de probabilidades) se definen como el ratio entre la probabilidad de evento verdadero y la probabilidad de evento falso.
Por ejemplo, si un evento tiene un probabilidad de ser verdadero de 0.8, la probabilidad de ser falso será de 1 - 0.8 = 0.2. En este caso los odds son $\frac{0.8}{0.2} = 4$, lo que equivale a decir que se esperan 4 eventos verdaderos por cada evento falso.
===== Límites de decisión =====
Vamos a utilizar el dataset //iris// de //sklearn// para predecir si una flor es de tipo //virgínica// en función de la anchura del pétalo.
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
# Configuración warnings
# ==============================================================================
import warnings
warnings.filterwarnings('ignore')
Cargamos el dataset y definimos nuestra X e y:
iris = load_iris()
X = iris.data[:, 3:]
y = (iris.target == 2).astype(np.int)
Entrenamos un modelo de regresión logística:
log_reg = LogisticRegression()
log_reg.fit(X, y)
Vemos las probabilidades estimadas del modelo para flores con anchuras de pétalos que vayan de 0 cm a 3 cm:
X_new = np.linspace(0, 3, 1000).reshape(-1, 1)
y_proba = log_reg.predict_proba(X_new)
X_not_virg = X[0:100, :]
y_not_virg = y[0:100]
X_virg = X[100:, :]
y_virg = y[100:]
figure=plt.figure(figsize=(15, 5))
axes = figure.add_subplot()
axes.plot(X_new, y_proba[:, 1], "b-", label = "Iris virgínica")
axes.plot(X_new, y_proba[:, 0], "g--", label = "Not Iris virgínica")
axes.scatter(X_not_virg, y_not_virg)
axes.scatter(X_virg, y_virg, marker = "^")
axes.legend(fontsize=15,facecolor='#CDCDCD',labelcolor="#000000")
axes.set_xlabel('Petal width (cm)', fontsize=15,labelpad=20,color="#003B80")
axes.set_ylabel('Probability', fontsize=15,labelpad=20,color="#003B80")
axes.set_title("Probabilidades estimadas y límites de decisión", fontsize=20,pad=30,color="#003B80")
{{ :clase:ia:saa:7_sml_clasificacion:log_reg.png?600 |}}
Como vemos, la anchura de las flores //iris virgínica// va desde 1.4 hasta 2.5 cm, mientras que las otras flores tienen, por lo general, una anchura de pétalo más pequeña. Hay un cierto solapamiento en los datos: por encima de 2cm, el modelo está bastante seguro que es //virgínica//, mientras que por debajo de 1 cm está bastante seguro que no lo es. En medio de estos extremos, el clasificador no está del todo seguro. Hay un límite de decisión alrededor de 1.6 cm donde ambas probabilidades son iguales al 50%.
===== Ejercicio =====
Usar el dataset {{ :clase:ia:saa:7_sml_clasificacion:spam.zip |}} para hacer un clasificador de correo basura. Este dataset contiene información sobre 4601 correos electrónicos clasificados como spam y no spam.
Para cada correo electrónico se dispone de 58 variables: las 48 primeras contienen la frecuencia con la que aparecen en el texto del email determinadas palabras. Las variables 49-54 indican la frecuencia con la que aparecen los caracteres ;’, ‘(’, ‘[’, ‘!’, ‘$’, ‘#’. Las variables 55-57 contienen la media, a longitud máxima y el número total de letras mayúsculas.
===== Referencias =====
[[https://www.cienciadedatos.net/documentos/py17-regresion-logistica-python.html|Regresión logística con Python by Joaquín Amat Rodrigo, available under a Attribution 4.0 International (CC BY 4.0)]]