Autoencoders para comprimir señales EEG

FabioBci IA
Ciencia y Datos
Published in
7 min readJun 22, 2019

En este artículo presentaré una forma de comprimir señales electroencefalográficas- EEG — mediante autoencoders.

Es probable que usted querido lector ahora mismo se esté haciendo varias preguntas, como por ejemplo que son las señales EEG?, para que son interesantes estas señales? y para qué querría comprimirlas?

Pues bien vayamos por pasos, intentaremos contestar las preguntas y luego mostraremos un ejemplo de creación de autoencoder para la compresión de las señales EEG.

Las señales EEG son señales producidas por las células nerviosas que se encuentran en la corteza cerebral — bien esto es simplificar mucho la cosa, pero nos basta para darnos una idea aproximada del problema -, estas células más comúnmente llamadas neuronas, producen una serie de reacciones electroquímicas, que a su vez producen diferencias de potencial. Estas diferencias de potencial pueden ser medidas mediante distintas técnicas, algunas técnicas son invasivas y otras no, nosotros básicamente nos centraremos en las técnicas no invasivas, mediante la colocación de un electrodo, que no es nada más que una pequeña placa metálica encima del cuero cabelludo, de esta forma podemos obtener una serie de números, es decir una serie temporal como la que podemos observar en la figura Fig 1.

Esta señal se ha obtenido de forma no invasiva utilizando un casco con distintos electrodos que captan las señales de las neuronas del cerebro, como las señales son muy débiles estas deben ser amplificadas mediante amplificadores electrónicos.

Fig 1: Señal EEG

Las señales EEG son una suma de distintas señales generadas por todo el conjunto de neuronas de la corteza cerebral, por lo tanto las señales EEG contiene distintos espectros frecuenciales, para estudiar dichas señales, estas bandas de frecuencia se han separado en las distintos rangos de frecuencia que son: Delta de 0–4 Hz, Theta de 4–8 Hz , Alfa de 8–12 Hz, Beta 13–35 Hz y Gamma > 35 Hz. En esta entrada no entraremos a explicar qué significa cada rango de frecuencia o a qué actividad cognitiva está asociada, si el lector desea podemos hacer otra entrada y explicar con más detalles las características de las señales EEG, pero a mi entender para empezar creo que tenemos suficiente. Así que resumiendo tenemos que las señales EEG son series temporales de voltaje que se produce en la corteza cerebral, bien, con esto hemos podido contestar a la pregunta qué son las señales EEG, ahora vayamos a contestar la pregunta para qué son interesantes estas señales?, pues bien, estas señales son interesantes en un primer término para la medicina, ya que estudiando las características de las señales EEG pueden los profesionales de la medicina detectar ciertas patologías y estudiar sus causas y efectos, también son interesantes desde un punto de vista tecnológico, ya que al asociar ciertas señales EEG a actividades cognitivas podemos crear interfaces que conectan directamente el cerebro con el mundo exterior sin necesidad de utilizar los músculos y esto es de gran interés para aquellas personas que puedan tener algún problema de movilidad.

Pero también es de gran interés en el mundo del Deep Learning, ya que las señales EEG se caracterizan por ser señales no estacionarias y de gran complejidad, y por lo tanto pueden ser unos datos muy valiosos para construir y estudiar sistemas Deep Learning de clasificación o de regresión.

Bien, ya hemos podido contestar las dos primeras preguntas, ahora bien, para que necesitaríamos poder comprimir la información proveniente de las señales EEG?, pues como todos sabemos los bits son oro, es decir si yo puedo utilizar menos bits para transmitir una cantidad de información, estaré utilizando mejor los recursos tanto de memoria como de ancho de banda del canal de comunicación, es decir imaginemos que queremos enviar en tiempo real las señales EEG de un paciente que está en su casa, y queremos enviarlas al despacho del médico vía internet para que este pueda monitorizar en tiempo real dichas señales, imaginemos que el dispositivo EEG es un casco de 64 canales, con una resolución de 16 bits por canal y a una frecuencia de muestreo de 512 Hz, estaremos enviada cada segundo 65536 bytes, es decir 65KB, es verdad que hoy en día esto no son cantidades alarmantes con las conexiones que tenemos, pero si pensamos en memoria igual la cosa ya cambia, imaginemos que queremos guardar el registro EEG de un paciente que ha estado monitorizado durante 24 horas con el mismo dispositivo descrito anteriormente, pues el fichero ocuparía aproximadamente 2.7GB de memoria, claro imaginemos que podemos comprimir este archivo en un archivo de 150Mb, aquí podemos observar el beneficio de comprimir la información.

Por lo tanto vamos a ponernos manos a la obra y vayamos a ver como utilizar el Deep Learning para comprimir señales EEG y de esta forma poder ayudar a mejorar los sistemas de telemedicina.

En Deep Learning existe una arquitectura neuronal que se llama Autoencoder, estas arquitecturas están formadas por una capa de entrada, una capa oculta y una capa de salida, este tipo de autoencoder, como podrá intuir el lector es el más básico, pero todo y siendo el básico tiene grandes capacidades, bien, el autoencoder tiene una única misión, reproducir en la capa de salida lo mismo que tiene en la capa de entrada, uno puede pensar que esto es una tontería, pero no, si imponemos que la capa oculta deba tener menos neuronas que la capa de entrada, si hacemos esto y conseguimos reproducir en la salida lo mismo que en la entrada estaremos realizando una compresión de la información ya que necesitaremos menos datos para representar una entrada que contiene más datos.

A Veces vale más una imagen que mil palabras, en la siguiente Figura 2 se puede observar el esquema básico de un autoencoder.

Figura 2 : Representación de un autoencoder, en la entrada tenemos la imagen original que se

Intenta reproducir en la capa de salida.

Fuente: https://towardsdatascience.com/deep-autoencoders-using-tensorflow-c68f075fd1a3

Como podemos observar el autoencoder se compone de dos partes bien diferenciadas, el encoder y el decoder, la primera el encode realiza una codificación y el decoder la decodifica, y en la capa del medio la oculta es donde se guarda la información comprimida.

Bien ya hemos visto un poco de teoría sobre autoencoders, ahora parece natural que si tenemos una señal EEG de por ejemplo 2000 valores podamos compartirla mediante un autoencoder, pero cuantas neuronas necesitaremos para comprimir dicha información?, bueno vamos a ver mediante un ejemplo como usar los autoencoders para realizar dicha tarea, y de paso contestar la pregunta que nos acabamos de hacer.

Primero de todo debemos cargar nuestros datos — existen distintas webs que ofrecen datos de señales EEG, yo utilizare una simulación de señales EEG, pero existen distintos repositorios donde podemos encontrar distinto tipo de señales EEG.

Para empezar cargaremos los datos utilizando la librería pandas de python.

import pandas as pd

import numpy as np

x_train = pd.read_csv(‘./x_train.csv’)

Una vez tenemos los datos cargados, tenemos que normalizarlos, ya que las redes neuronales trabajan con funciones de activación que normalmente tienen rangos entre [-1,1] y [0,1], por lo tanto debemos normalizar la señal, yo he observado que la función que trabaja bien para la compresión de señales EEG es la función hiperbólica — tanh — que tiene un rango [-1,1], por lo tanto deberemos pasar la señal EEG al intervalo [-1,1].

Figura 3: Función hiperbólica

Fuente: http://mathworld.wolfram.com/HyperbolicTangent.html

Se utiliza la función :

Donde a = -1 y b = 1.

Una vez normalizada las señales EEG entre -1 y 1 ya podemos pasar a construir nuestro autoencoder, que consta simplemente de tres capas, una capa de entrada, una capa oculta y una capa de salida.

Neurons = 80

shape_input = np.shape(x_train)

input_data = Input(shape = (shape_input[1], ))

last_layer = shape_input[1]

neurons = neurons_input

modelo = Sequential()

encoder = Dense(neurons, activation = ‘tanh’)(input_data)

decoder = Dense(neurons, activation = ‘tanh’)(encoder)

decoder = Dense(last_layer, activation = ‘tanh’)(decoder)

autoencoder = Model(input_data, decoder)

#autoencoder.summary()

autoencoder.compile(optimizer = ‘adam’, loss = ‘mean_squared_error’, metrics=[‘accuracy’])

autoencoder.fit(x_train, x_train, epochs = 100, batch_size = 16, verbose = 2)

encoder = Model(input_data, encoder)

Como se puede observar este es un sistema no supervisado, y hemos utilizado 80 neuronas en la capa oculta, nuestros datos de entrada son de dimensión 2000 por lo tanto nuestro autoencoder comprimira la información unas 25 veces, es decir, una vez tengamos el encoder podremos obtener las señales utilizando 25 veces menos de información.

Veamos la salida cuando estamos entrenando y la red y la salida final del autoencoder a la hora de reconstruir las señales EEG.

Figura 4: Entrenamiento y correlación final

Como se puede observar la correlación final entre las señales reales y las señales reconstruidas es del 88.44 %, es decir comprimiendo la señal EEG de entrada 25 veces obtenemos un 88% de correlación, parece ser un método sencillo y fiable de comprimir señales EEG, esto no solamente abre la ventana a la transmisión y almacenamiento más eficiente de señales biomédicas, también abre la ventana a la utilización de nuevos algoritmos de clasificación ya que podemos ver la compresión como una extracción de características de las señales, pero estoy ya es otra historia.

Figura 5: Señal en azul es la señal original y la señal en naranja es la señal reconstruida por el autoencoder.

Dejo para el lector la experimentación, que prueba distintas cantidades de neuronas, épocas, métodos de optimización y de loss, y también probar lo explicado en este artículo para imágenes u otro tipo de datos.

--

--