sábado, 7 de diciembre de 2019

Artificial Neural Nets con Keras Framework. Functional API


En artículos anteriores mostramos como programar de forma sencilla redes neuronales (MLP, CNN y RNN) basándose en el API secuencial de Keras sobre un backend Tensorflow. 

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,))
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)
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).

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.

miércoles, 21 de agosto de 2019

Artificial Neural Nets con Keras Framework



En el siguiente articulo mostraremos como programar de forma sencilla redes neuronales (MLP, CNN y RNN) basándose en el API secuencial de Keras sobre un backend Tensorflow.

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.

Todo el código completo se puede encontrar en github - https://github.com/e2its/Neural-Nets-practica

Requisitos

  • Python 3.6
  • Jupyter notebooks
  • Pandas 0.25
  • numpy 1.16.4
  • scikit-learn 0.21.2
  • keras 2.2.4
  • tensorflow 1.14

Descripción

Para los experimentos usaremos un conjunto de datos orientados al reconocimiento de la actividad. Estos se basan en la información aportada por 3 sensores de forma que podamos realizar un análisis de patrones (5 series temporales consecutivas en intervalos de 250 ms) para detectar la actividad física que se esta realizando (sitting, bending, cycling, lying, walking, standing) mediante tres tipos de redes neuronales MLP (Multi-Layer Perceptron), CNN (Convolutional Neural Nets) y RNN (Recurrent Neural Nets).

En cada archivo, cada fila corresponde a 5 mediciones (en orden temporal con una diferencial de 250 ms) conteniendo la siguiente información: 


No hay texto alternativo para esta imagen
Add caption
(0) avg_rss12, var_rss12, avg_rss13, var_rss13, avg_rss23, var_rss23

(+250ms) avg_rss12_1, var_rss12_1, avg_rss13_1, var_rss13_1, avg_rss23_1, var_rss23_1

(+500ms) avg_rss12_2, var_rss12_2, avg_rss13_2, var_rss13_2, avg_rss23_2, var_rss23_2

(+750ms) avg_rss12_3, var_rss12_3, avg_rss13_3, var_rss13_3, avg_rss23_3, var_rss23_3

(+1000ms) avg_rss12_4, var_rss12_4, avg_rss13_4, var_rss13_4, avg_rss23_4, var_rss23_4

donde avg y var son la media y los valores de varianza respectivamente.



La descripción y los datasets originales pueden ser encontrados en el siguiente enlace Activity Recognition system based on Multisensor data fusion (AReM) Data Set


Lo primero que tenemos que hacer es cargar los datasets de entrenamiento y test desde github.


No hay texto alternativo para esta imagen
Tras esto codificaremos los datos de actividad, nuestras Labels (ATYPE), como valores numéricos aptos para los modelos de Redes Neuronales.


No hay texto alternativo para esta imagen
Normalizamos los datos para que los modelos trabajen de forma más óptima con media a 0 y desviación estándar a 1.


No hay texto alternativo para esta imagen

Y finalmente convertimos nuestros datasets a arrays Numpy ('x_' para características e 'y_' para labels) :


No hay texto alternativo para esta imagen

En este punto ya estamos listos para operar con las distintas redes a través del API Secuencial de Keras.


Multilayer Perceptron (MLP)


Una red multilayer perceptron (MLP) es una clase de red neuronal artificial que consta de al menos tres capas de nodos: una capa de entrada, una capa oculta y una capa de salida.
A excepción de los nodos de entrada, cada nodo es una neurona que utiliza una función de activación no lineal. MLP utiliza una técnica de aprendizaje supervisado llamada backpropagation para el entrenamiento.

Para implementar una red MLP lo primero que tenemos que hacer es adaptar los arrays Numpy a las estructuras de datos que espera el modelo. En nuestro caso no hay que hacer ningún cambio ya que el modelo espera exactamente la estructura base definida anteriormente.

(41888,30)

Para localizar el mejor modelo implementamos un análisis de varias configuraciones basadas en iteraciones sobre distintos valores de los parámetros clave del modelo.

No hay texto alternativo para esta imagen

Y ejecutamos los modelos.

No hay texto alternativo para esta imagen

Tras esto seleccionamos el mejor modelo

No hay texto alternativo para esta imagen

siendo la estructura de dicho modelo:

No hay texto alternativo para esta imagen

y los resultados obtenidos tras la re-ejecución del modelo:

No hay texto alternativo para esta imagen

Convolutional Neural Nets (CNN)


Una red neuronal convolucional es un tipo de red neuronal artificial donde las neuronas corresponden a campos receptivos de una manera muy similar a las neuronas en la corteza visual primaria (V1) de un cerebro biológico.Este tipo de red es una variación de un perceptron multicapa, sin embargo, debido a que su aplicación es realizada en matrices bidimensionales, son muy efectivas para tareas de visión artificial, como en la clasificación y segmentación de imágenes
Como redes de clasificación, al principio se encuentra la fase de extracción de características, compuesta de neuronas convolucionales y de reducción de muestreo. Al final de la red se encuentran neuronas de perceptron sencillas para realizar la clasificación final sobre las características extraídas. La fase de extracción de características se asemeja al proceso estimulante en las células de la corteza visual. Esta fase se compone de capas alternas de neuronas convolucionales y neuronas de reducción de muestreo.

Las redes convolucionales asemejan el proceso de reconocimiento visual cerebral, pero ¿es aplicable a nuestros experimento?. Para ello solo tenemos que transformar nuestro conjunto de datos en una estructura bidimensional con sentido, esto es, convertirla en una estructura similar a un array de imágenes. Esto lo conseguimos modificando la dimensionalidad de nuestro dataset de la siguiente forma.

No hay texto alternativo para esta imagen

consiguiendo una estructura de este tipo

(41888, 6, 5, 1)

Implementando la misma secuencia de pasos que para las redes MLP pero adaptados a una modelo de extracción de características (convolución) y reducción (pooling).


No hay texto alternativo para esta imagen
No hay texto alternativo para esta imagen

Seleccionamos el mejor modelo

No hay texto alternativo para esta imagen
siendo la estructura de dicho modelo


No hay texto alternativo para esta imagen

y los resultados obtenidos tras la re-ejecución del modelo:

No hay texto alternativo para esta imagen

Recurrent Neural Nets (RNN)


Red neuronal que integra bucles de realimentación, permitiendo a través de ellos que la información persista durante algunos pasos ó épocas de entrenamiento, (epochs) a través conexiones desde las salidas de las capas, que “incrustan” (embedding) sus resultados en los datos de entrada. Las conexiones entre nodos forman un gráfico dirigido a lo largo de una secuencia temporal. Funciona como una red con múltiples copias de sí misma, cada una con un mensaje a su sucesor. Cuanto más larga sea la secuencia temporal a analizar, mayor será el número de capas debe desenrollar, puede aparecer el problema de desvanecimiento del gradiente (Vanishin Gradient). Esto se soluciona incorporando capas de tipo LSTM o GRU que permiten el backpropagation through time conectando eventos que aparezcan muy alejados en los datos de entrada, sin que su peso se diluye entre las capas.

Al igual que ocurría con las redes neuronales convolucionales, para trabajar con las redes RNN, también tenemos que adaptar la estructura y dimensionalidad de los datos a la requerida para este tipo de modelos.

(41888, 6, 5)


No hay texto alternativo para esta imagen

Implementando la misma secuencia de pasos que para las redes MLP pero adaptados a una modelo de recurrente basado en unidades LSTM.

No hay texto alternativo para esta imagen

No hay texto alternativo para esta imagen

Seleccionamos el mejor modelo

No hay texto alternativo para esta imagen

siendo la estructura de dicho modelo

No hay texto alternativo para esta imagen


y los resultados obtenidos tras la re-ejecución del modelo:

No hay texto alternativo para esta imagen

Como hemos presentado en este articulo, la implementación de Redes Neuronales con el API secuencial de Keras es tan sencilla como útil, sin embargo, esta limitada. En próximos artículos introduciremos nuevos tipos de redes Neuronales más complejas junto con el API funcional de Keras, de mayor versatilidad y potencia.

Todo el código completo de los experimentos se pueden encontrar en github.