Las neuronas artificiales clasifican conjuntos de valores encontrando fronteras de decisión sobre dichos conjuntos. Sabiendo que las fronteras de decisión son siempre ortogonales (perpendiculares) a los vectores de pesos, se puede afirmar que el problema de encontrar una frontera de decisión es el mismo que el de encontrar un vector de pesos. Dado uno se conoce el otro.
Aprendizaje Automático
Imaginemos que queremos clasificar un conjunto de valores en dos clases. Los valores representados como cruces rojas en una clase y los valores representados como guiones verdes en la otra clase.
Es evidente que el conjunto de datos es linealmente separable. Se puede trazar una línea recta que separe el conjunto en dos. Las cruces a un lado y los guiones al otro. Es decir, se puede trazar una frontera de decisión. O lo que es lo mismo, se puede encontrar un vector de pesos que determine dicha frontera. El propósito de un algoritmo de Aprendizaje Automático es precisamente encontrar dicho vector de manera automática.
Uno de los algoritmos más sencillos es el que propuso originalmente junto con el diseño del Perceptron. Dicho algoritmo puede resumirse en los siguientes pasos:
1. Generar una frontera de decisión de forma aleatoria
2. Por cada valor del conjunto de valores siendo clasificado:
a. Comprobar si el valor está correctamente clasificado respecto a la frontera
b. Si no está correctamente clasificado variar la frontera para clasificarlo correctamente
3. Repetir el paso 2 hasta que todos los valores estén correctamente clasificados
Algoritmo que puede reformularse utilizando las características conocidas del producto escalar aplicado al vector de pesos y todos los posibles vectores de entrada:
1. Generar un vector de pesos aleatorios W
2. Por cada vector de entrada X :
a. Calcular el producto escalar W \cdot X
b. Si el producto escalar es negativo, y el valor no está correctamente clasificado:
Sumar X a W
c. Si el producto escalar es positivo, y el valor no está correctamente clasificado:
Restar X de W
3. Repetir el paso 2 hasta que no se produzca ningún cambio en W
Estos pasos se pueden representar de forma gráfica. Siendo el primer paso el de generar un vector de pesos aleatorios, lo que permite trazar una primera frontera de decisión, perpendicular a dicho vector.
El segundo paso es iterar por todos los valores, comprobando el signo del producto escalar entre el vector de pesos y el vector definido por cada valor. Suponiendo que se quiere clasificar las cruces rojas en el lado de la frontera de decisión donde el producto escalar es positivo, y los guiones verdes en el otro lado, donde es negativo.
En este caso la mayoría de los valores están bien clasificados, sin embargo, una cruz roja está incorrectamente clasificada. Está en el lado equivocado de la frontera. El producto escalar es negativo cuando debería ser positivo.
Para corregir la frontera de decisión se suma el vector del valor incorrectamente clasificado al vector de pesos. Esto tiene sentido en la medida que se mueve el vector de pesos hacia la dirección a la que apunta el vector del valor, haciendo que sean más similares que antes. Es decir, reduciendo el ángulo entre ambos, aumentando el producto escalar.
La nueva frontera de decisión ahora clasifica correctamente la cruz roja, pero también clasifica incorrectamente otros valores, entre ellos un guión verde. El producto escalar es positivo cuando debería ser negativo.
Para corregir la frontera de decisión se resta el vector del valor incorrectamente clasificado del vector de pesos. Lo que tiene sentido en la medida que mueve el vector de pesos en dirección contraria a la que apunta el vector del valor, aumenta el ángulo entre ambos, reduciendo el producto escalar.
Finalmente todos los valores quedan correctamente clasificados.
Notar que si en el paso anterior se hubiera corregido la frontera utilizando las cruces rojas incorrectamente clasificadas en vez del guión verde el resultado hubiera sido el mismo, aunque la frontera de decisión pudiera haber sido otra un poco distinta.
Puerta AND
Se puede comprobar la efectividad del algoritmo haciendo que encuentre el vector de pesos que modela una puerta lógica AND. O dicho de otra forma, entrenando de forma automática una neurona artificial para que encuentre por si misma los valores de configuración que modelan una puerta AND.
Para ello primero se debe decidir la topología de la red neuronal a utilizar, que en este caso estará compuesta por una única neurona, con dos entradas, una salida, y la función escalón unitario como función de activación:
X = [x_1, x_2, 1]
W = [w_1, w_2, b]
f(W \cdot X) = \begin{cases} 0 & \quad \text{if } W \cdot X < 0 \\ 1 & \quad \text{if } W \cdot X \geq 0 \end{cases}
Para aplicar el algoritmo se necesita también recopilar un conjunto de valores de entrada a utilizar para el entrenamiento, y el resultado deseado d , del inglés «desired», para cada una de dichas entradas. Lo que en este caso se corresponde básicamente con la tabla de la verdad de la puerta lógica AND:
\begin{matrix} & \mathbf{x_1} & \mathbf{x_2} & & \mathbf{d} \\ X_1 = & [0, & 0, & 1] & 0 \\ X_2 = & [0, & 1, & 1] & 0 \\ X_3 = & [1, & 0, & 1] & 0 \\ X_4 = & [1, & 1, & 1] & 1 \end{matrix}
Información que habitualmente se representa de forma combinada de la siguiente forma:
[X_1, d_1] = [0, 0, 1, 0]
[X_2, d_2] = [0, 1, 1, 0]
[X_3, d_3] = [1, 0, 1, 0]
[X_4, d_4] = [1, 1, 1, 1]
En este punto ya se puede empezar a aplicar el algoritmo, cuyo primer paso es generar un vector de pesos aleatorio:
W = [0.8, -0.1, -2.5]
A continuación se comprueba la salida de la neurona contra la salida deseada, para cada uno de los valores de entrada, hasta que se encuentre una salida que no corresponda con la deseada:
f(W \cdot X_1) = f(0.8*0 -0.1*0 -2.5*1) = f(-2.5) = 0
f(W \cdot X_2) = f(0.8*0 -0.1*1 -2.5*1) = f(-2.6) = 0
f(W \cdot X_3) = f(0.8*1 -0.1*0 -2.5*1) = f(-1.7) = 0
f(W \cdot X_4) = f(0.8*1 -0.1*1 -2.5*1) = f(-1.8) = 0
La salida de la neurona para el vector de entrada X_4 no se corresponde con la salida deseada d_4 . El deseado es 1 y se obtiene un 0. En consecuencia se suma el vector X_4 al vector de pesos W :
W = W + X_4 = [0.8, -0.1, -2.5] + [1, 1, 1] = [1.8, 0.9, -1.5]
Y se vuelve a realizar la comprobación de las salidas con los nuevos pesos:
f(W \cdot X_1) = f(1.8*0 + 0.9*0 -1.5*1) = f(-1.5) = 0
f(W \cdot X_2) = f(1.8*0 + 0.9*1 -1.5*1) = f(-0.6) = 0
f(W \cdot X_3) = f(1.8*1 + 0.9 *0 -1.5*1) = f(0.3) = 1
El valor deseado para X_3 es 0, pero se obtiene 1, por lo que se resta dicha entrada de los pesos y se vuelve a iterar:
W = W - X_3 = [1.8, 0.9, -1.5] - [1, 0, 1] = [0.8, 0.9, -2.5]
f(W \cdot X_1) = f(0.8*0 + 0.9*0 -2.5*1) = f(-2.5) = 0
f(W \cdot X_2) = f(0.8*0 + 0.9*1 -2.5*1) = f(-1.6) = 0
f(W \cdot X_3) = f(0.8*1 + 0.9*0 -2.5*1) = f(-1.7) = 0
f(W \cdot X_4) = f(0.8*1 + 0.9*1 -2.5*1) = f(-0.8) = 0
El valor deseado para X_4 es 1, pero se obtiene 0, por lo que se suma dicha entrada a los pesos y se vuelve a iterar:
W = W + X_4 = [0.8, 0.9, -2.5] + [1, 1, 1] = [1.8, 1.9, -1.5]
f(W \cdot X_1) = f(1.8*0 + 1.9*0 -1.5*1)= f(-1.5) = 0
f(W \cdot X_2) = f(1.8*0 + 1.9*1 -1.5*1) = f(0.4) = 1
El valor deseado para X_2 es 0, pero se obtiene 1, por lo que se resta dicha entrada de los pesos y se vuelve a iterar:
W = W - X_2 = [1.8, 1.9, -1.5] - [0, 1, 1] = [1.8, 0.9, -2.5]
f(W \cdot X_1) = f(1.8*0 + 0.9*0 -2.5*1)= f(-2.5) = 0
f(W \cdot X_2) = f(1.8*0 + 0.9*1 -2.5*1) = f(-1.6) = 0
f(W \cdot X_3) = f(1.8*1 + 0.9*0 -2.5*1) = f(-0.7) = 0
f(W \cdot X_4) = f(1.8*1 + 0.9*1 -2.5*1) = f(0.2) = 1
Finalmente la red retorna el valor deseado para cada entrada y el algoritmo termina.
Convergencia
Se puede demostrar matemáticamente que el algoritmo converge (encuentra una solución) en un número finito de pasos cuando se aplica sobre un conjunto de valores linealmente separables. Donde el número máximo de pasos dados será siempre igual o menor que:
\bigg(\cfrac{R}{\gamma}\bigg)^2
Siendo R la distancia al valor más alejado del centro de coordenadas, y \gamma (gamma) la distancia al valor más cercano a la frontera de decisión.
También se puede demostrar que el algoritmo tiene las mismas limitaciones que tiene el Perceptron. Es decir, que sólo puede clasificar conjuntos de valores linealmente separables. Siendo el ejemplo paradigmático de esta limitación el problema de tratar de implementar una puerta XOR con una única neurona artificial.
El algoritmo no converge para este caso. No existe ningún vector de pesos que defina una frontera de decisión que separe los valores en dos clases. El algoritmo siempre estaría oscilando entre una clase y otra. Clasificaría un valor de una clase a un lado. A continuación detectaría que hay un valor de la otra clase mal clasificado, y vuelta a empezar.
También es importante notar que el algoritmo no resulta práctico de aplicar en redes neuronales con varias capas. Ya que ello implica que el error en cada neurona de cada capa debe corregirse de forma individual. Es decir, que es necesario disponer de antemano de la salida esperada en todas y cada una de las neuronas de la red. Información de la que habitualmente no se dispone, ya que lo habitual es tener un conjunto de entradas y el resultado esperado a la salida de la red, no la salida esperada en cada neurona de la red.
Función de Activación Revisitada
Las funciones de activación determinan la salidas de las neuronas, es decir, como varían en función de las entradas y los pesos. Las funciones de activación de tipo escalón, como la función escalón unitario, resultan útiles para implementar sistemas de clasificación, pero a costa de transicionar de forma muy brusca de un valor a otro. Lo que desde un punto de vista matemático quiere decir que no son continuas, y por tanto no derivables en todos sus puntos.
Este comportamiento de las funciones de tipo escalón tiene una gran influencia en los algoritmos de Aprendizaje Automático basados en proponer una configuración inicial de pesos, probar dicha configuración contra una serie de entradas cuya salida esperada se conoce de antemano, y corregir la configuración en función del error cometido.
Utilizando una función escalón es posible cambiar el valor de los pesos de una neurona de forma significativa y que su salida siga siendo la misma. Lo que quiere decir que la salida no es proporcional a la magnitud del error cometido que ha motivado el cambio de los pesos. Las neuronas de una capa no reciben ninguna información acerca del error cometido en la capa previa. El error no se propaga a través de la red.
Una mejor opción por tanto es utilizar funciones de activación continuas y derivables en todos sus puntos. La derivada de una función permite cuantificar el efecto que tiene en la salida la variación de la entrada. Al utilizar funciones de activación derivables se puede obtener su derivada, y consecuentemente, se puede cuantificar el efecto que tiene en la salida variaciones en las entradas o en los pesos.
Función Sigmoide
Un ejemplo de función activación derivable y continua en todos sus puntos es la función sigmoide, también conocida como función logística simple:
\sigma(x) = \cfrac{1}{1 + e^{-x}}
Esta función \sigma (sigma) convierte los valores negativos en 0 y los positivos en 1, de forma brusca en los extremos, y de forma más suave en las proximidades del centro del eje de coordenadas, siendo derivable en todo el intervalo.
La salida de esta función puede interpretarse como un cálculo de probabilidades. La probabilidad de que una entrada pertenezca a la clase 1. Los valores netos positivos tienen una mayor probabilidad de pertenecer a la clase 1, de activar la neurona, y los valores negativos una menor probabilidad de pertenecer a la clase 1, de inhibir la neurona. Característica por la que la función sigmoide se utiliza habitualmente para construir sistemas de regresión, que realizan predicciones en vez de clasificaciones.
La función escalón unitario condiciona la clasificación de las entradas en función única y exclusivamente del signo del producto escalar. Si es negativo la entrada se clasifica como perteneciente a la clase 0, en caso contrario como perteneciente a la clase 1. Es decir, una entrada tiene un cincuenta por ciento de probabilidad de pertenecer a una clase u otra.
La función sigmoide en cambio realiza una predicción en función del signo y la magnitud del producto escalar. Las entradas tienen una probabilidad de pertenecer a una clase u otra que varía en función del valor del producto escalar en las proximidades de cero.
Utilizar la función sigmoide no cambia el hecho de que el algoritmo de aprendizaje no converge si el conjunto de datos en estudio no es linealmente separable. Pero permite construir una red neuronal que retorne la probabilidad de que una entrada pertenezca a una clase u otra, frente a la función escalón que retorna siempre una clase sin ninguna otra información que permita cuantificar la exactitud de dicha clasificación.
En el siguiente diagrama está representada una frontera de decisión sobre un conjunto de valores que no es linealmente separable.
Cuando se introduce una entrada en la neurona la función de activación sigmoide retorna la probabilidad de que dicha entrada esté correcta o incorrectamente clasificada en función de su posición con respecto a la frontera de decisión. De esta forma, la red informa de que los puntos A y B tienen una alta probabilidad de que estén correctamente clasificados en sus respectivas clases, mientras que los puntos C y D tienen una probabilidad de que no lo estén, pequeña para C y grande para D.
Existen otras funciones de activación más populares hoy en día que la función sigmoide, pero es importante en la medida que fue la función que se introdujo originalmente cuando se desarrollaron los algoritmos de Aprendizaje Automático.
Derivada
La derivada de la función sigmoide presenta la característica de que puede escribirse haciendo referencia a la propia función sin derivar de la siguiente forma:
\sigma'(x) = \sigma(x)(1 − \sigma(x))
Expresión que puede obtenerse partiendo de las siguientes reglas generales del cálculo de derivadas:
\big(u(x)^{-1}\big)' = -u(x)^{-2} u'(x)
\big(a u(x) + b v(x)\big)' = a u'(x) + b v'(x)
\big(e^{u(x)}\big)' = e^{u(x)} u'(x)
Desarrollando la expresión de la derivada:
\sigma'(x) = \cfrac{d}{dx} \left( \cfrac{1}{1 + e^{-x}} \right) = \cfrac{d}{dx} (1 + e^{-x})^{-1} = -(1 + e^{-x})^{-2} \cfrac{d}{dx} (1 + e^{-x})
= -(1 + e^{-x})^{-2} \left( \cfrac{d}{dx} (1) + \cfrac{d}{dx} (e^{-x}) \right) = -(1 + e^{-x})^{-2} \left( 0 + \cfrac{d}{dx} (e^{-x}) \right)
= -(1 + e^{-x})^{-2} \left( e^{-x} \cfrac{d}{dx} (-x) \right) = -(1 + e^{-x})^{-2} (-e^{-x}) = (1 + e^{-x})^{-2} e^{-x}
= \cfrac{e^{-x}}{(1 + e^{-x})^{2}}
Y simplificando la ecuación obtenida:
\sigma'(x) = \cfrac{e^{-x}}{(1 + e^{-x})(1 + e^{-x})} = \cfrac{1}{1 + e^{-x}} \cfrac{e^{-x}}{1 + e^{-x}} = \cfrac{1}{1 + e^{-x}} \cfrac{e^{-x} + 1 - 1}{1 + e^{-x}}
= \cfrac{1}{1 + e^{-x}} \left( \cfrac{1 + e^{-x}}{1 + e^{-x}} - \cfrac{1}{1 + e^{-x}} \right) = \cfrac{1}{1 + e^{-x}} \left( 1 - \cfrac{1}{1 + e^{-x}} \right)
=\sigma(x)(1 − \sigma(x))
Aprendizaje Automático Supervisado
Es importante entender en este punto que las técnicas de Aprendizaje Automático representan un cambio de paradigma. En el desarrollo tradicional de aplicaciones las reglas que resuelven un problema se escriben de manera explícita. Sin embargo, utilizando técnicas de Aprendizaje Automático, las reglas se infieren de forma automática. Una vez inferidas las reglas se puede introducir cualquier conjunto de datos de entrada en la red neuronal, incluso datos no utilizados originalmente para inferir las reglas, y obtener una respuesta como en cualquier aplicación tradicional.
Cuando el algoritmo utilizado para inferir las reglas necesita un conjunto de datos previamente clasificado se define como Aprendizaje Automático Supervisado, debido a que los datos de entrada deben ser supervisados manualmente antes de poder ser utilizados para entrenar la red neuronal.
La necesidad de dicho conjunto de datos es uno de los inconvenientes de estas técnicas. Ya que si se quiere entrenar una red neuronal para que distinga si una imagen contiene una mesa o una silla hay que proporcionar al algoritmo imágenes indicando para cada una de ellas si contiene una mesa o una silla.
Otro inconveniente es la necesidad de diseñar manualmente la topología de la red neuronal. Es decir, decidir el número de capas, el número de neurona por capa y la función de activación en cada capa. Esto es más importante de lo que pueda parecer a priori, ya que si la red no tiene la capacidad suficiente no podrá resolver el problema. Por ejemplo, no se puede modelar una puerta XOR con una única neurona.