Muchas aplicaciones de ingeniería se derivan de construir modelos para:
Hasta hace unos quince años, la construcción de dichos modelos se hacía mayoritariamente con base en leyes basadas en una fuerte evidencia de la naturaleza (leyes de Newton, ecuaciones de Maxwell, leyes de la termodinámica, entre otras).
Sin embargo, en los últimos años, la gran cantidad de información disponible junto con el avance tecnológico en capacidad de procesamiento han llevado a que se construyan modelos con base en simplemente datos.
Ejemplos:
Si lo anterior no les resulta sorprendente, los invito a que saquen veinte minutos y lean la siguiente entrevista.
Bueno, todo lo anterior es el poderoso alcance que tienen las tecnologías de la información. Hoy veremos un abrebocas: construir un modelo de clasificación binaria con base en datos únicamente.
Presentamos la idea básica de clasificación binaria mediante un ejemplo.
Tenemos como entrada una imagen digital y como salida una etiqueta que identifica a esta imagen como el logo del ITESO (en cuyo caso la etiqueta toma el valor de uno '1') o no (en cuyo caso la etiqueta toma el valor de cero '0').
A la salida la denotaremos $y$.
¿Cómo guarda las imágenes un computador? Código de colores RGB.
$$R=\left[\begin{array}{cccc}255 & 124 & \dots & 45\\ 235 & 224 & \dots & 135\\ \vdots & \vdots & & \vdots\\ 23 & 12 & \dots & 242\end{array}\right]$$ $$G=\left[\begin{array}{cccc}255 & 154 & \dots & 42\\ 215 & 24 & \dots & 145\\ \vdots & \vdots & & \vdots\\ 0 & 112 & \dots & 232\end{array}\right]$$ $$B=\left[\begin{array}{cccc}255 & 231 & \dots & 145\\ 144 & 234 & \dots & 35\\ \vdots & \vdots & & \vdots\\ 5 & 52 & \dots & 42\end{array}\right]$$
Cada matriz tiene tamaño correspondiente con los pixeles de la imagen. Si la imagen se de $64px\times 64px$, cada matriz será de $64\times 64$.
¿Cómo podemos convertir entonces una imagen en una entrada? Ponemos cada valor de cada matriz en un vector de características $\boldsymbol{x}$:
$$\boldsymbol{x}=\left[\begin{array}{ccc} \text{vec}R & \text{vec}G & \text{vec}B \end{array}\right]^T=\left[\begin{array}{ccccccccc} 255 & 124 & \dots & 255 & 154 & \dots & 255 & 231 & \dots \end{array}\right]^T$$Entonces el problema de clasificación se puede resumir como dado un vector de entrada $\boldsymbol{x}$ (en este caso un vector con las intensidades de rojo, verde y azul por pixel de una imagen), predecir si la etiqueta correspondiente $y$ toma el valor de $1$ o $0$ (si es logo del ITESO o no).
En adelante seguiremos la siguiente notación.
Un ejemplo de entrenamiento se representa por la pareja ordenada $(\boldsymbol{x},y)$, donde $\boldsymbol{x}\in\mathbb{R}^n$ y $y\in\left\lbrace0,1\right\rbrace$.
Tendremos $m$ ejemplos de entrenamiento, de modo que nuestro conjunto de entrenamiento será $\left\lbrace(\boldsymbol{x}^1,y^1),(\boldsymbol{x}^2,y^2),\dots,(\boldsymbol{x}^m,y^m)\right\rbrace$.
Por otra parte, para presentar de forma más compacta las entradas de entrenamiento, definimos la matriz
$$\boldsymbol{X}=\left[\begin{array}{c} {\boldsymbol{x}^1}^T \\ {\boldsymbol{x}^2}^T \\ \vdots \\ {\boldsymbol{x}^m}^T \end{array}\right]\in\mathbb{R}^{m\times n},$$cuyas filas son los vectores de entrenamiento de entrada transpuestos, y el vector
$$\boldsymbol{Y}=\left[\begin{array}{c} y^1 \\ y^2 \\ \vdots \\ y^m \end{array}\right]\in\mathbb{R}^{m},$$cuyas componentes son las etiquetas (salidas) de entrenamiento.
La idea entonces es, dado un vector de características $\boldsymbol{x}$ (quizá correspondiente a una imagen que queramos identificar como el logo del ITESO o no), queremos obtener una predicción $\hat{y}$ que es nuestro estimado de $y$.
Formalmente $\hat{y}=P(y=1|\boldsymbol{x})\in\left[0,1\right]$...
Los parámetros de regresión serán $\boldsymbol{\beta}=\left[\beta_0\quad \beta_1\quad \dots\quad \beta_n \right]^T\in\mathbb{R}^{n+1}.$
Primera idea: usar una regresor lineal
$$\hat{y}=\beta_0+\beta_1x_1+\beta_2x_2+\dots+\beta_nx_n=\left[1\quad \boldsymbol{x}^T\right]\boldsymbol{\beta}=\boldsymbol{x}_a^T\boldsymbol{\beta},$$donde $\boldsymbol{x}_a=\left[1\quad \boldsymbol{x}^T \right]^T\in\mathbb{R}^{n+1}$.
¿Cuál es el problema? Que el producto punto $\boldsymbol{\beta}^T\boldsymbol{x}_a$ no está entre $0$ y $1$.
Entonces, pasamos el regresor lineal por una sigmoide (función logística)
$$\sigma(z)=\frac{1}{1+e^{-z}}$$
In [1]:
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
In [2]:
def fun_log(z):
return 1/(1+np.exp(-z))
In [3]:
z = np.linspace(-5, 5)
plt.figure(figsize = (8,6))
plt.plot(z, fun_log(z), lw = 2)
plt.xlabel('$z$')
plt.ylabel('$\sigma(z)$')
plt.grid()
plt.show()
Notamos que:
Finalmente...
Regresor logístico: $\hat{y}=\sigma(\boldsymbol{x}_a^T\boldsymbol{\beta})$.
Para manejar todos los datos de entrenamiento, se define la matriz
$$\boldsymbol{X}_a=\left[\boldsymbol{1}_{m\times 1}\quad \boldsymbol{X}\right]=\left[\begin{array}{cc} 1 & {\boldsymbol{x}^1}^T \\ 1 & {\boldsymbol{x}^2}^T \\ \vdots & \vdots \\ 1 & {\boldsymbol{x}^m}^T \end{array}\right]\in\mathbb{R}^{m\times (n+1)}.$$Así,
$$\hat{\boldsymbol{Y}}=\left[\begin{array}{c} \hat{y}^1 \\ \hat{y}^2 \\ \vdots \\ \hat{y}^m \end{array}\right]=\sigma(\boldsymbol{X}_a\boldsymbol{\beta})$$
In [4]:
def reg_log(B,Xa):
return fun_log(Xa.dot(B))
Ya que tenemos definida la forma de nuestro modelo clasificador, debemos entrenar los parámetros $\boldsymbol{\beta}$ con los ejemplos de entrenamiento.
Es decir, dados $\left\lbrace(\boldsymbol{x}^1,y^1),(\boldsymbol{x}^2,y^2),\dots,(\boldsymbol{x}^m,y^m)\right\rbrace$, queremos encontrar parámetros $\boldsymbol{\beta}$ tales que $\hat{y}^i=\sigma({\boldsymbol{x}_a^i}^T\boldsymbol{\beta})\approx y^i$ 'lo mejor posible'.
Esto lo plantearemos como un problema de optimización.
Primera idea: minimizar error cuadrático $\min_{\boldsymbol{\beta}} \frac{1}{m}\sum_{i=1}^m (\hat{y}^i-y^i)^2$. Problema de optimización no convexo (explicar).
Alternativa: entonces, se buscó una función de modo que el problema de optimización fuera convexo. Esta es:
$$\min_{\boldsymbol{\beta}} \frac{1}{m}\sum_{i=1}^m -\left(y^i\log(\hat{y}^i)+(1-y^i)\log(1-\hat{y}^i)\right)$$No pretendemos explicar toda esta función. Pero sí podemos ganar algo de intuición de porqué la usamos. Fijemos un $i$ dentro del sumatorio y consideremos el término $-\left(y^i\log(\hat{y}^i)+(1-y^i)\log(1-\hat{y}^i)\right)$.
En cualquier caso, esta función objetivo cumple con lo requerido.
In [5]:
data_file = 'ex2data1.txt'
data = pd.read_csv(data_file, header=None)
X = data.iloc[:,0:2].values
Y = data.iloc[:,2].values
In [6]:
X
Out[6]:
In [7]:
Y
Out[7]:
In [8]:
plt.figure(figsize = (8,6))
plt.scatter(X[:,0], X[:,1], c=Y)
plt.show()
Diseñar un clasificador binario con regresión logística.
El paquete pyomo_utilities.py
fue actualizado y contiene ahora la función logreg_clas(X, Y)
.
In [9]:
import pyomo_utilities
In [10]:
B = pyomo_utilities.logreg_clas(X, Y)
Los parámetros del clasificador son entonces:
In [11]:
B
Out[11]:
In [12]:
x = np.arange(20, 110, 0.5)
y = np.arange(20, 110, 0.5)
Xm, Ym = np.meshgrid(x, y)
m,n = np.shape(Xm)
Xmr = np.reshape(Xm,(m*n,1))
Ymr = np.reshape(Ym,(m*n,1))
In [13]:
Xa = np.append(np.ones((len(Ymr),1)), Xmr, axis=1)
Xa = np.append(Xa,Ymr,axis=1)
In [14]:
Yg = reg_log(B,Xa)
Z = np.reshape(Yg, (m,n))
Z = np.round(Z)
In [15]:
plt.figure(figsize=(10,10))
plt.contour(Xm, Ym, Z)
plt.scatter(X[:, 0],X[:, 1], c=Y, edgecolors='w')
plt.show()
Considere los siguientes datos y diseñe un clasificador binario por regresión logística.
Mostrar el gráfico de la división del clasificador con los puntos de entrenamiento.
Abrir un nuevo notebook, llamado Tarea8_ApellidoNombre
y subirlo a moodle en el espacio habilitado. Si no terminan esto en clase, tienen hasta el miércoles a las 23:00.
La tarea de la clase pasada es hasta el miercoles también (se me olvidó habilitar el espacio)
In [27]:
X = 10*np.random.random((100, 2))
Y = (X[:, 1] > X[:, 0]**2)*1
In [28]:
plt.figure(figsize = (8,6))
plt.scatter(X[:,0], X[:,1], c=Y)
plt.show()