Una red neuronal es un clasificador. Su funcionamiento se basa en la combinación de hiperplanos que acotan regiones de activación del espacio de muestras.
En cada ciclo de actualización de los pesos de la red no es necesario calcular el gradiente de descenso para cada muestra. Basta con escoger un lote variado de muestras (mini-batch) y calcular el gradiente resultante de éste.
La pérdida o loss es el valor o error resultante de comparar las predicciones de la red con las etiquetas de las muestras.
Cuando se clasifica en más de dos categorías es necesario que la red tenga tantas neuronas en la capa de salida como clases haya. Por tanto, la activación de cada una de estas neuronas de salida corresponderá con una clase. Por ejemplo, si la red tiene cuatro salidas y se activa la tercera, el vector resultante podría ser algo como: [0.002,0.008,0.95,0.04]. Como normalmente las etiquetas de las muestras están en un formato numérico entero (0,1,2,3...), no podremos realizar la comparación de las salidas con las etiquetas. Así que transformamos la etiqueta en un vector de todo ceros excepto el lugar correspondiente a la etiqueta, el cual tendrá un valor de 1. Por ejemplo: 2→[0,0,1,0]. (Recordemos que las etiquetas comienzan en 0). Esta función de transformación se denomina One-hot.
Cada vez que entrenamos una red con todos los lotes o mini-batches de nuestro dataset de entrenamiento decimos que hemos completado una época. Durante el proceso de entrenamiento de una red se suelen completar múltiples épocas.
La función softmax es parecida a la sigmoide, ésta también convierte un valor entre menos infinito y más infinito en un valor entre cero y uno. La diferencia está en que la función softmax no trabaja sobre un valor sino sobre un vector. De esta forma, convierte todas las componentes de un vector en valores entre cero y uno, pero, además, garantiza que la suma de todos estos valores sea uno. La función softmax se emplea en la capa de salida de una red, y convierte de esta forma sus salidas en una distribución de probabilidades.
Softmax(v)i=evi∑nj=1evjEl dataset iris corresponde a un conjunto de 150 muestras pertenecientes a 3 categorías de flor del iris distintas (versicolor, virgínica y setosa). Estas 3 especies se pueden diferenciar por el ancho y alto de su pétalo y su sépalo. Vamos a construir una red que nos permita clasificar este dataset. Para ello utilizaremos 5 neuronas en una capa oculta y 3 neuronas en la capa de salida, ya que son 3 clases.
Keras es una API de redes neuronales de alto nivel, escrita en Python y capaz de ejecutarse sobre TensorFlow, CNTK o Theano. Fue desarrollado con la idea de permitir la experimentación rápida, poder pasar de la idea al resultado en el menor tiempo posible.
Instala Tensorflow y Keras y veamos cómo montar una red en Keras para clasificar el dataset Iris. En primer lugar importamos el dataset. La función LabelBinarizer
nos convertirá las etiquetas numéricas enteras a codificación one-hot. La función train_test_split() nos divide el dataset con un 75% para el entrenamiento y un 25% para el test.
import numpy as np
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelBinarizer
#load the iris dataset
iris = load_iris()
X = iris.data
encoder = LabelBinarizer()
y = encoder.fit_transform(iris.target) # We transform to one-hot
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25)
Creamos la red con la capa de entrada correspondiente a los cuatro valores de cada muestra. Una capa oculta de cinco neuronas y una capa de salida de tres neuronas. Aplicamos la función de activación sigmoide para la capa oculta y, dado que tenemos más de dos clases, softmax para la salida. Utilizamos Stochastic Gradient Descent como método optimizador con un learning rate de 0.1.
import keras
from keras.layers import Input, Dense
from keras.models import Model
from keras.optimizers import SGD #Stochastic Gradient Descent Optimizer
inputs = Input(shape=(4,)) # We have four inputs
x = Dense(5, activation='sigmoid')(inputs) # five neurons and sigmoid as activation function
predictions = Dense(3, activation='softmax')(x) # Output layer with three neurons, one for each class
# This creates a model
model = Model(inputs=inputs, outputs=predictions)
sgd = SGD(lr=0.1)
model.compile(optimizer=sgd,
loss='mse', # Mean Squared Error
metrics=['accuracy'])
print(model.summary())
_________________________________________________________________ Layer (type) Output Shape Param # ================================================================= input_9 (InputLayer) (None, 4) 0 _________________________________________________________________ dense_16 (Dense) (None, 5) 25 _________________________________________________________________ dense_17 (Dense) (None, 3) 18 ================================================================= Total params: 43 Trainable params: 43 Non-trainable params: 0 _________________________________________________________________ None
Ahora ya solo queda entrenar nuestra red y ver qué resultados nos devuelve.
model.fit(X_train, y_train, epochs=500) # starts training with 500 epochs
Vamos a ver qué valores de salida tenemos para algunas muestras.
predictions = model.predict(X_test)
for p, l in zip(predictions, y_test):
print(p,"->", l)
Basándote en el ejercicio anterior, construye una red que clasifique el conjunto MNIST. En el siguiente código ya tenemos el dataset preparado para introducirlo en nuestra red. Recuerda que el conjunto de entrenamiento del MNIST está formado por 60000 imágenes de dígitos manuscritos de 28x28 pixels.
from keras.datasets import mnist
batch_size = 128
num_classes = 10
epochs = 5
# the data, split between train and test sets
(X_train, y_train), (X_test, y_test) = mnist.load_data()
X_train = X_train.reshape(60000, 784) # 28x28=784
X_test = X_test.reshape(10000, 784)
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
X_train /= 255 # We normalize to have values between 0 and 1
X_test /= 255
# convert class vectors to binary class matrices
y_train = keras.utils.to_categorical(y_train, num_classes) # onehot encoding
y_test = keras.utils.to_categorical(y_test, num_classes)
# To do...