Fotografía con gatitos. Fuente: GFDL, https://gl.wikipedia.org/w/index.php?curid=31951

Ahora vamos a usar una red neuronal para poder clasificar objetos o fenómenos (en nuestro ejemplo van a ser fotos con gatos) en dos clases diferentes. Esto lo lograremos tomando un conjunto de entrenamiento que está marcado como clase uno o como clase dos y lo probaremos sobre datos que no conocemos con antelación. De esta manera podemos ver si nuestro modelo funciona sobre estos datos. Los resultados los comparamos con las predicciones hasta el final. Para ello usaremos regresión logística.

Notación y problema

En este ejemplo vamos a hacer la clasificación sobre el problema: ¿aparece en una foto un(os) gato(s)? (nótese que son adorables). Para ello usaremos la clase 1 para indicar que si existen gatos en la fotografía y 0 para aquellas sin gatos. Si x es el valor que se desea obtener en la clasificación, entonces:

\[ y= \begin{cases} 1 & \text{gatos en fotografía} \\ 0 & \text{fotografía sin gatos} \end{cases} \]

Ahora que hemos definido las clases, debemos tomar en cuenta representar de forma matemática las características de la foto. Vamos a representar en forma de vector los pixeles en una división RGB de la imagen y la vamos a concatenar. Esto nos arrojará un gigantesco vector que contendrá todos los valores de los pixeles de la imagen en una dimensión. Con estos valores definamos nuestra notación.

Cada ejemplo es un par ordenado

\[ (x,y), x\in \mathbb{R}^{n_x}, y\in\{0,1\} \]

 donde x es un vector n dimensional de características y y es uno o cero. Para nuestro conjunto de entrenamiento se definirán m ejemplos entrenamientos tal que onbtendremos los siguientes ejemplos de entrenamiento:

\[M=\{(x^1,y^1), (x^2,y^2), \dots, (x^m,y^m)\} \]

Para facilitar el trabajo con redes neuronales, y recordando que cada x es un vector, podemos unir estos vectores en una matriz, que llamaremos X, y que tiene la forma:

\[X=[x^1,x^2,\dots,x^m], \text{ donde } X\in\mathbb{R}^{n_x\times m}\]

Ahora, las clases también se guardarán en un vector. Si recordamos, que cada x tiene asociado una y escalar, entonces el vector de todos los y es:

\[Y=[y^1,y^2,\dots,y^m], \text{ donde } Y\in\mathbb{R}^{1\times m}\]

Ahora que hemos definido la notación que vamos a usar, es hora de plantear el problema. Nosotros queremos encontrar una función que data una entrada x nos pueda generar una estimación de y, tal que:

 

\[\hat{y}=P(y=1|x) \text{ y los parámetros } w\in\mathbb{R}^{n_x}, b\in\mathbb{R}\]
 

La Regresión Logística

 

 ¿Pero qué función logrará definir mejor el comportamiento de nuestra salida para definir la probabilidad de y? Es posible generar una función lineal con la multiplicación de wTx+b , pero esto tendría algunos problemas. El primero de ellos es que al ser lineal puede adquirir valores negativos y positivos superiores a 1. Pero al ser una probabilidad la que necesitamos regresar, esto no tendría sentido. La función que necesitamos generar debe encontrarse entre 0<=y<=0, por lo que usaremos una función sigmoide. Esta se comporta de la siguiente manera:

Como se puede ver nunca llega a tocar el eje de las y a 0 o 1, y se mueve entre estos dos valores. Lo cual la hace perfecta para expresar una probabilidad para nuestra decisión binaria. Veamos ahora cómo es la forma de una función sigmoide:

\[S(z) = \frac{1}{1+e^{-z}} \text{ donde } z=w^Tx+b\]
 

Como ya tenemos la función que nos permitirá clasificar correctamente nuestras fotografías, nuestro modelo debe encontrar los valores correctos de w y b que nos permitan encontrar el valor correcto de la función S. 

 La función de costo!

Ahora bien, en nuestros estimadores W y b se escogen en un inicio de manera aleatoria, pero esto no parece ser muy útil. ¿Cómo saber qué tan bien o mal logran predecir nuestros estimadoras la clase de nuestra foto? Para ellos requerimos una función de error o loss function. Definir es una función así no es trivial. Por ejemplo, hay que tomar en cuenta que nuestro problema no es convexo.  Para este problema se utilizará la función de error:

\[\mathscr{L}(\hat{y},y) = - \big(y \log \hat{y} + (l-y) \log (1-\hat{y})\big)\]

 Esta función únicamente se usará sobre una entrada del conjunto de datos. Ahora, para obtener una imagen general sobre el error de los parámetros con respecto al total de los datos, usaremos la función de costo, que es definida cómo:

\[\begin{align}J(W,b)&=\frac{1}{m}\sum^m_{i=1}\mathscr{L}(\hat{y}^i,y^i)\\ &=-\frac{1}{m}\sum^m_{i=1}\big[ y^i \log \hat{y}^i + (1-y^i) \log (1-\hat{y}^i)\big] \end{align}\]

El objetivo de nuestra red neuronal va a ser minimizar el costo total del modelo, para así acercarnos lo más posible a nuestras clases dadas y. Si logramos ajustar los parámetros de tal forma que predigan y, entonces estaremos entrenando un modelo bastante bueno para el uso con otros datos no vistos. ¿Cómo hacerlo? Lo vemos a continuación. 

El algoritmo de la gradiente descendiente. 

Ya que hemos explicado bien nuestra función de predicción y nuestra función de costo queda claro el problema para resolver el modelo: buscamos los parámetros w y b que minimicen J(w,b) . Lo que queremos lograr es descender en nuestro mundo hasta un mínimo que esperemos sea el mínimo global. El espacio definido por la función de costo y el cual queremos descender tendrá una figura como a continuación se muestra:

 

 Tendremos dos ejes donde theta 1 representa los valores de W y theta 0 a los valores de b, y la altura es el valor que adquiere la función de costo J con esta combinación de valores. La función de costo que se escogió es buena para este problema por que es convexa y esto nos ayudará a encontrar la solución global al problema. 

¿Cuál es la idea detrás de este algoritmo? La idea central es en cada paso del algoritmo ir descendiendo por el relieve de la función. Sabremos cuantos pasos y en qué dirección descender por la derivada de J respecto a w y b.  Esto se expresa en las siguientes ecuaciones:

\[\begin{align}w&=w-\alpha \frac{\partial J(w,b)}{\partial w}\\ b&=b-\frac{\partial J(w,b)}{\partial b}\end{align}\]

 Cada una de estas actualizaciones se realizará en cada ciclo, hasta llegar a la convergencia. La derivada de J(w,b) en cada función es la pendiente de la función de costo, y nos indicará en qué dirección bajar y cuanto. El alfa que multiplica la derivada es un valor dado que permite acelerar o decrecer esos pasos. Es útil poder modificar este valor, ya que para cada problema vamos a necesitar diferentes velocidades de descenso. Si bien este tema es complejo lo hemos abordado de una manera sencilla. Si quieren más información quiero recomendar leer el artículo sobre la gradiente descendiente aquí

 

Share This