Sin embargo dicho API se queda corto a la hora de programar redes más complejas como Ensemble NN, Autoencoders, GAN o Reinforce Learning donde múltiples inputs/outputs y Neural Nets tienen que combinarse entre si para la consecución el objetivo de aprendizaje.
Recordemos que Keras es Keras es una API de redes neuronales de alto nivel, escrita en Python y capaz de funcionar sobre TensorFlow, CNTK o Theano. Fue desarrollado con el objetivo de permitir una rápida experimentación.
Retomado el caso de experimentación anterior, que podreis encontrar en el artículo Artificial Neural Nets con Keras Framework compararemos la diferencia en la estructura del código utilizando el API Sequential y el Functional del framework para después ver su aplicación en el ensamblado de modelos neuronales.
Vamos a ver las diferencias de implementación de una red simple MLP en ambos modelos para analizar las diferencias.
Codificación de una Red MLP basado en el API secuencial.
model = Sequential()
model.add(Dense(best_model['conf'][0], input_shape=(input_dimension,)))
model.add(Activation('relu'))
model.add(Dropout(best_model['conf'][4]))
model.add(Dense(best_model['conf'][1]))
model.add(Activation('relu'))
model.add(Dropout(best_model['conf'][4]))
model.add(Dense(output_dimension))
model.add(Activation('softmax'))
Codificación de una Red MLP basado en el API Funcional.
input_1 = Input(shape=(input_dimension,))Como podemos comprobar el modelo secuencial se comporta como un a lista a la que vamos añadiendo elementos, capas al modelo, que se ejecutarán de forma lineal, mientras que en el enfoque funcional actúan como una formulación matemática o programática y = F(x).
x = input_1
x = Dense(best_model['conf'][0])(x)
x = Activation('relu')(x)
x = Dropout(best_model['conf'][4])(x)
x = Dense(best_model['conf'][1])(x)
x = Activation('relu')(x)
x = Dropout(best_model['conf'][4])(x)
output = Dense(output_dimension, activation = 'softmax' )(x)
model = Model([input_1], output)
Pero si ambos APIs obtienen al final el mismo resultado, ¿para que necesitamos el API funcional?
La respuesta la encontramos en los modelos complejos que no tienen solución en la implementación secuencial del Framework.
Para ello vamos a utilizar el siguiente ejemplo.
¿Como implementaríamos la siguiente ANN sin el API Functional?
La respuesta es sencilla, no se puede, ya que contradice el principio de linealidad de la agregación en las listas.
Implementación de un Modelo Ensamblado con Functional API.
Los modelos ensamblados se basan en aprovechar la combinación de modelos sub-óptimos para conseguir modelos optimizados minimizando el consumo de recursos y maximizando la capacidad aprendizaje de cada modelo esperando que cada modelo aprenda sobre elementos no cubiertos del otro complementándose entre sí.
Para ello lo primero que necesitamos es importar las clases que van a sustituir a Sequential Class.
from keras.models import Model
from keras.layers import Dense, Activation, Dropout, Input, Conv2D, MaxPooling2D, Flatten
from keras.layers.merge import concatenate
Tras esto compondremos nuestro modelo tras generar las adaptaciones en los datos necesarias para compatibilizar los dataframes con las input de redes MPL y CNN.
Esta información como el código ejecutable con todos los parámetros está disponible en github en formato .ipynb.
Primero crearemos el modelo MLP:
input_1 = Input(shape=(input_dimension,))
x = input_1
x = Dense(best_model['conf'][0][0])(x)
x = Activation('relu')(x)
x = Dropout(best_model['conf'][4])(x)
x = Dense(best_model['conf'][0][1])(x)
x = Activation('relu')(x)
x = Dropout(best_model['conf'][4]) (x)Tras esto creamos el modelo CNN:
input_2 = Input(shape=cinput_dimension)
y = input_2
y = Conv2D(filters = best_model['conf'][1][0], kernel_size = best_model['conf'][1][1],activation = 'relu', data_format = 'channels_last',padding='same')(y)
y = MaxPooling2D(best_model['conf'][1][2])(y)
y = Flatten()(y)y = Dense(cdense)(y)
y = Activation('relu')(y)Y finalmente concatenamos las salidas en un modelo único:
y = concatenate([x,y])
output = Dense(output_dimension, activation='softmax')(y)
model = Model([input_1, input_2], output)Una vez que tenemos esto solo nos faltaría seleccionar el optimizador y la función de perdida y ejecutar el entrenamiento del modelo. en nuestro caso utilizamos un optimizador Adam, crossentropy como función de pérdida y como medida de validación usaremos la "accuracy" o porcentaje de aciertos.
# loss function for one-hot vector
# use of adam optimizer
# accuracy is a good metric for classification tasks
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])# train the network
model_history = model.fit(x = [x_train, c_train], y = y_train, batch_size = best_model['conf'][2], epochs = best_model['bepoch'])Finalmente comprobaremos los resultados obtenidos con los datos de entrenamiento y de test (no usados durante el entrenamiento del modelo) y comprobaremos su adecuación al problema.
print ('Train : Loss(%s) - Accuracy: (%s)' %(model_history.history['loss'][-1], model_history.history['acc'][-1]))
Train : Loss(0.48775133260613274) - Accuracy: (0.787648013750955)
print ('Train : Loss(%s) - Accuracy: (%s)' %(model_history.history['loss'][-1], model_history.history['acc'][-1]))Test : Loss(0.5097890445164271) - Accuracy: (0.8085714343615941)
Siguientes pasos
Una vez que ya conocemos el uso del API Funcional de Keras con Tensorflow lo que os queda es analizar cada una de los tipos de redes existente y decidir cuál es la necesaria para resolver cada problema concreto y lanzarse a disfrutar de la experimentación.
- Autoencoders: se usan para validar la adecuación de un conjunto de datos contra un patrón de comportamiento. Aplica a problemas de detección de anomalías en procesos, sensorización o fraude.
- Generative Adversarial Networks: Se basa en aprender a "falsificar" datos. Esto es, la generación de Fake Data. Si bien puede sonar raro, su aplicación es muy potente ya que permite generar conjuntos de datos validados para entornos de simulación para test de carga y stress de sistemas y aplicaciones tan conocidas como el coloreados de imágenes o el "DeepFake".
- Reinforce Deep Learning: Si bien está en sus estadíos iniciales las Redes DQNN permiten la resolución de problemas, principalmente en el espacio continuo, imposibles o muy complicados de modelar por sistemas de Q-Learning tradicionales.
Como siempre, todo el código completo de los experimentos se pueden encontrar en github.