INTRODUCCIÓN AL
DEEP LEARNING
MICROSOFT OFFICE
USER
[Link]/es
ÍNDICE
1. ¿Qué es Deep Learning? ____________________________________________ 2
2. Fundamentos de las redes neuronales artificiales ________________________ 2
3. Ejemplo de aplicación (con perceptrón multicapa) _______________________ 9
4. Deep Learning en imágenes. Redes convolucionales. ____________________ 15
5. Deep Learning en series temporales. Redes recurrentes. _________________ 22
6. Conclusión ______________________________________________________ 29
INTRODUCCIÓN AL DEEP LEARNING 1
1. ¿QUÉ ES DEEP LEARNING?
Puede entenderse el aprendizaje profundo o deep learning como un enfoque situado
dentro del machine learning, cuyos modelos se caracterizan por ser capaces de
aprender conceptos complejos a partir de otros más simples y de una forma
jerarquizada. El término “deep” hace referencia a la profundidad que se da en esta
jerarquía de conceptos cuando los modelos constan de múltiples capas, donde los
conceptos más simples se aprenden en las primeras capas y los más complejos en las
últimas.
Gracias a los avances tecnológicos y los volúmenes de datos cada vez mayores, existe
una tendencia a añadir cada vez más capas a estos modelos para modelar realidades
cada vez más complejas, con aplicaciones tales como: predicción de sucesos,
reconocimiento de voz, conducción autónoma, sistemas de recomendación,
prevención del fraude o generación de texto, entre muchos otros.
Las redes neuronales artificiales son el conjunto de algoritmos que definen el estado
del arte del deep learning, debido a su potencia, su escalabilidad y motivadas por
cierta similitud con el sistema neuronal biológico.
En este curso se van a presentar las redes neuronales, estudiando sus fundamentos y
conceptos generales, y las tareas que pueden desempeñar en función del tipo de red.
Se desarrollará un ejemplo práctico para cada tipo de red presentada: un perceptrón
multicapa, una red convolucional y una red recurrente; con el objetivo de obtener una
visión general de sus posibles aplicaciones.
2. FUNDAMENTOS DE LAS REDES NEURONALES ARTIFICIALES
2.1. La neurona
Las unidades fundamentales de procesamiento de las redes neuronales son las
neuronas (McCulloch y Pitts, 1943). Estas unidades reciben la información procedente
de las conexiones con unidades anteriores o con las entradas, procesan esa
información aplicando una función y generan una (única) respuesta que recibirán las
unidades posteriores o la salida de la red.
En concreto, las conexiones de entrada llevan asociado un valor que indica el peso de
cada entrada anterior, de forma que la neurona recibe una combinación de las
entradas con sus pesos asociados. Esta combinación viene dada por la función de
entrada, siendo la suma ponderada la función más ampliamente utilizada, cuya
expresión es:
𝑛
𝑓(𝑥) = ∑ 𝑥𝑗 𝜔𝑗𝑖
𝑗=1
INTRODUCCIÓN AL DEEP LEARNING 2
También es habitual añadir a la suma un sesgo b (bias) que no lleva ningún dato
asociado pero que puede modificar el valor de la salida. Puede interpretarse el sesgo
como una conexión con un peso de b asociado a un valor de entrada 1, que rige la
predisposición de la neurona hacia una salida con mayor o menor independencia de
los pesos del resto de entradas.
2.2. Función de activación
Una vez que la neurona recibe la información combinada por la función de entrada,
esta información se procesa para generar la salida mediante la función de activación.
Estas funciones son capaces de aportar “no linealidad” a la red y dar la posibilidad de
modelar conceptos más complejos.
Actualmente, la función de activación más utilizada es la función rectificadora, debido
principalmente a que puede mejorar el entrenamiento de las redes neuronales
profundas y es útil en problemas de regresión. Esta función toma la parte positiva de
su argumento y viene dada por la expresión:
𝑓(𝑥) = 𝑚𝑎𝑥(0, 𝑥)
También es habitual encontrar otras funciones de activación a la salida, como la
función sigmoide para problemas de clasificación binaria o la función softmax para
problemas de clasificación múltiple, cuyas expresiones son, respectivamente:
1
𝑓(𝑥) =
1 + 𝑒 −𝑥
𝑒 𝑥𝑖
𝑓(𝑥𝑖 ) =
∑𝑗 𝑒 𝑥𝑗
En el caso de que la función de entrada sea la suma ponderada y la función de
activación sea la función rectificadora, la neurona resultante recibe el nombre de
unidad lineal rectificada (ReLU). Este tipo de neurona es muy popular y genera una
(única) salida continua de valores positivos.
Con estos conceptos, se puede representar el esquema general de una neurona:
INTRODUCCIÓN AL DEEP LEARNING 3
2.3. Arquitectura de las redes neuronales
Las neuronas de las redes neuronales se organizan en capas, y cada neurona de cada
capa estará conectada a todas las neuronas de las capas anteriores y/o posteriores. En
las redes multicapa, las primeras capas se encargarán de las transformaciones más
simples y las últimas se encargarán de las más complejas.
La arquitectura de una red neuronal se refiere tanto a esta organización como a la
configuración de los parámetros que definen cada capa. Se pueden distinguir tres tipos
de capas:
● Capa de entrada: se refiere a los datos de entrada, que tendrá tantas neuronas o
dimensiones como atributos contenga el conjunto de datos. Todas las redes
neuronales constan de una capa de entrada.
● Capas ocultas: estas capas caracterizan las redes neuronales profundas. Reciben
este nombre debido a que tanto sus entradas como sus salidas no pueden ser
observadas. El número de capas ocultas y de neuronas en estas capas no tiene una
solución única y deberán buscarse las dimensiones óptimas para cada problema.
● Capa de salida: es el resultado observable de la red, cuyo número de neuronas
dependerá del problema a resolver. Por ejemplo, si tenemos un problema de
clasificación en n clases necesitaremos n neuronas en la capa de salida, asociadas
cada una a la pertenencia a una clase.
Es habitual encontrar en la bibliografía que se definan como capas únicamente las que
tienen entradas o neuronas, ignorando entonces la capa de entrada.
Dependiendo de su complejidad, la arquitectura de una red neuronal puede constar
desde una única neurona conectada a todas las entradas y que produce una salida,
hasta una red con múltiples capas ocultas y múltiples salidas, que puede representarse
como:
INTRODUCCIÓN AL DEEP LEARNING 4
Al añadir más neuronas y más capas a la red, normalmente aumenta la capacidad
predictiva de ésta, aunque también su coste computacional y la posibilidad de sufrir
sobreajuste. Serán la naturaleza del problema a resolver, el conjunto de datos y la
evaluación de resultados los que guíen el proceso de selección de una arquitectura
óptima.
Las redes neuronales con múltiples capas, que pueden estar total o parcialmente
conectadas y que son capaces de resolver problemas con soluciones no lineales,
reciben el nombre de perceptrón multicapa (Rumelhart, Hinton, y Williams, 1986), por
su herencia histórica con el perceptrón simple (Rosenblatt, 1958).
2.4. Función de coste
La función de coste o función de pérdidas (loss function) mide la diferencia entre el
valor real y el valor predicho por el modelo. Esa diferencia (o error) servirá como dato
de entrada en el proceso de aprendizaje, de tal modo que irá variando para cada
configuración de parámetros del modelo. Como veremos a continuación, el proceso de
entrenamiento busca minimizar esta función mediante un ajuste iterativo de los
parámetros del modelo hasta llegar a una configuración óptima.
El tipo de función de coste empleada para el entrenamiento dependerá del tipo de
problema a resolver y de la función de activación de las neuronas de la capa de salida.
Para problemas de regresión puede emplearse el conocido error cuadrático medio
(MSE), su raíz cuadrada (RMSE) o el error absoluto medio (MAE).
Para problemas de clasificación es más habitual utilizar funciones de entropía cruzada.
Por ejemplo, para un problema donde la salida son las probabilidades de pertenencia a
cierta clase, es habitual utilizar la función de entropía cruzada (CE), que viene dada por
la expresión:
INTRODUCCIÓN AL DEEP LEARNING 5
𝑁
𝐶𝐸 = − ∑ 𝑦𝑖 𝑙𝑜𝑔(𝑦̂𝑖 )
𝑖
Esta función mide la diferencia entre distribuciones de probabilidad y acelera el
proceso de aprendizaje en las primeras etapas.
2.5. Entrenamiento de redes neuronales
El entrenamiento de las redes neuronales tiene por objetivo ir ajustando los pesos y
bias de la red hacia una configuración donde la función de coste sea mínima. Esto se
consigue mediante un algoritmo de optimización, también llamado optimizador,
donde el método del descenso del gradiente es el más importante método empleado
en algoritmos de deep learning.
2.5.1 Método de descenso del gradiente
Este método forma la base del proceso de aprendizaje iterativo que tiene lugar
durante el entrenamiento y sirve para describir cómo deben configurarse los
parámetros en cada paso para minimizar la función de coste. Se puede describir el
método como:
Si 𝑓(𝜔𝑖 ) es la función de coste asociada a los parámetros 𝜔𝑖 en el paso i-ésimo y
𝛻𝑓(𝜔𝑖 ) es el gradiente de dicha función (resultado del cálculo de las derivadas
parciales para cada parámetro en ese punto) que índica la dirección y sentido hacia
donde la pendiente es mayor; como lo que se busca es minimizar la función, se debe
cambiar el signo del gradiente (el sentido del vector) para que la pendiente sea
descendente y quedar más cerca del mínimo. Así, la configuración de parámetros del
siguiente paso (𝜔𝑖+1) a partir de la configuración conocida del paso previo, vendrá
dada por la expresión:
𝜔𝑖+1 = 𝜔𝑖 − 𝜇𝑖 · 𝛻𝑓(𝜔𝑖 )
donde 𝜇𝑖 se denomina tasa de aprendizaje (learning rate) e indica cuánto debe
desplazarse el punto en la dirección indicada. Dicha tasa de aprendizaje puede ser
fijada inicialmente (𝜇𝑖 = 𝜇), aunque habitualmente se hace uso de nuevos
optimizadores que aceleran el método del descenso del gradiente y que tienen una
tasa de aprendizaje adaptativa, cuyo valor suele reducirse gradualmente.
Posteriormente se presentarán algunos de los optimizadores más relevantes.
2.5.2 Épocas y lotes
Los conceptos de época (epoch) y lote (batch) son importantes para poder presentar
una de las versiones más utilizadas del método del descenso del gradiente para el
entrenamiento de redes neuronales.
Una época es un ciclo para el cuál se utilizan todos los datos de entrenamiento una
sola vez. Para entrenar correctamente una red neuronal se necesita pasar todo el
INTRODUCCIÓN AL DEEP LEARNING 6
conjunto de entrenamiento varias veces, de forma que la red procesará todos esos
datos tantas veces como número de épocas.
El lote (batch) es el conjunto de datos que pasa por la red en una iteración. Es útil
dividir el conjunto de entrenamiento en lotes pequeños (mini-batch) de cierto número
de muestras (batch size) para acelerar la velocidad de procesamiento. Cada mini-batch
se procesará en una iteración y cuando se completen todas las iteraciones (todos los
mini-batch) se habrá procesado todo el conjunto de entrenamiento y se habrá
completado una época.
2.5.3 Método de descenso del gradiente estocástico (SGD) por mini-lotes
Para poder evitar estancamientos (caer en mínimos locales, puntos de silla…), es útil
añadir algo de aleatoriedad en el entrenamiento. Este método selecciona un mini-
batch de muestras aleatorias de datos de entrenamiento para cada iteración. La
aleatoriedad dificultará ese estancamiento y el uso de mini-lotes mejorará la eficiencia
al permitir paralelizar procesos y acelerar el entrenamiento. Esta variante del método
de descenso del gradiente es la empleada en la actualidad. En esencia, los pasos que se
llevan a cabo con este método son:
1. Se parte con una inicialización aleatoria de los pesos y sesgos de la red, en
base a una distribución gaussiana. Esto puede agilizar el proceso de
aprendizaje.
2. Propagación hacia adelante (feedforward): se alimenta la red con un mini-
batch de datos de entrada aleatorios, se procesa hacia adelante por todas
las capas de la red y se obtiene la salida.
3. Se evalúa la función de coste asociada a esa salida y se prepara el cálculo
del gradiente.
4. Propagación hacia atrás (backpropagation): para poder propagar el error
proporcionalmente al impacto que ha tenido cada neurona de las capas
ocultas en el error de la capa de salida, se emplea el método de
retropropagación (Werbos, 1974). Este método consiste en calcular, en
primer lugar, las derivadas parciales de la función de coste con respecto a
los parámetros de la capa de salida, después se calcularán las derivadas
asociadas a los parámetros de la capa anterior, y así sucesivamente hasta
llegar a la primera capa.
5. Se adaptan los parámetros gracias al gradiente de la función de coste
obtenido en el paso previo (como resultado de todas las derivadas parciales
de los parámetros de todas las capas) y de acuerdo con la expresión que
define el método del descenso del gradiente, vista anteriormente.
INTRODUCCIÓN AL DEEP LEARNING 7
2.5.4 Algoritmos de optimización del SGD
Con el objetivo de acelerar el proceso de aprendizaje y mejorar el rendimiento del
método de descenso del gradiente, surgen optimizadores como:
● Momentum: este algoritmo acelera el avance del gradiente en la dirección
correcta “amortiguando” las oscilaciones que puedan producirse. Esto se
consigue mediante un gradiente con una media móvil ponderada
exponencial y con el valor del gradiente en la iteración anterior.
● Adadelta: se basa en una tasa de aprendizaje adaptativa en función de una
ventana móvil de actualizaciones de gradientes. Es una extensión de otro
optimizador conocido como Adagrad y similar a otro llamado RMSProp.
● Adam: combina la base de optimización de Momentum con la tasa de
aprendizaje adaptativa de Adadelta. Suele ser de los más rápidos para
tareas generales.
2.6. Regularización: Early Stopping & Dropout
Como es habitual en machine learning, uno de los mayores problemas que se
presentan en el entrenamiento de los modelos es el overfitting y el underfitting, y más
aún en modelos de redes neuronales profundas que constan de multitud de
parámetros para ajustar. Una posible solución a estos problemas pasa por aumentar el
conjunto de datos de entrenamiento (con técnicas como data augmentation, entre
otros) o ajustar las dimensiones de la red (número de neuronas y/o capas ocultas). Sin
embargo, en ocasiones no será posible generar más datos o variar el tamaño de la red,
ya sea por costes computacionales, por alterar su capacidad de aprendizaje…, por lo
que sería conveniente contar con ciertas técnicas que ayuden a detectar o evitar el
overfitting cuando se tiene un conjunto de datos o tamaño de red fijos.
Estas técnicas, que forman parte del paradigma del deep learning, reciben el nombre
de técnicas de regularización. Dos de las más conocidas son:
● Early Stopping: esta técnica consiste en parar el entrenamiento en el momento
en el que las pérdidas (o error) del conjunto de validación dejan de disminuir y
comienzan a aumentar, mientras que las del conjunto de entrenamiento siguen
disminuyendo, de forma que la diferencia entre los errores de ambos conjuntos
es cada vez mayor y el modelo estaría perdiendo capacidad de generalizar.
Se deberá entrenar la red un número de épocas suficiente para poder observar
ese cambio en la tendencia y aplicar esta técnica, lo que también implica que se
evitará el subajuste (underfitting) que se produciría si paramos el
entrenamiento demasiado pronto. Se puede visualizar esta técnica
representando las curvas de las pérdidas de ambos conjuntos durante el
entrenamiento:
INTRODUCCIÓN AL DEEP LEARNING 8
● Dropout: esta técnica consiste en ir desactivando aleatoriamente cierta
fracción de neuronas en cada capa de la red (menos en la capa de salida)
durante el proceso de entrenamiento. Esto evita que se produzcan algunas de
las conexiones y configuraciones de parámetros que puedan ser fruto del
aprendizaje del ruido de los datos de entrenamiento, es decir, fruto del
overfitting. Cabe destacar que cuando finaliza el entrenamiento todas las
neuronas permanecerán activas.
3. EJEMPLO DE APLICACIÓN (CON PERCEPTRÓN MULTICAPA)
Para estos ejemplos hacemos uso del lenguaje de programación Python, de la librería
Keras para la implementación de redes neuronales artificiales, así como otras librerías
habituales en data science y la herramienta Jupyter Notebook. Para ver el código más
en detalle, ver los vídeos de ejemplo.
3.1. Objetivo
Construir una red neuronal completamente conectada (perceptrón multicapa) que sea
capaz de clasificar teléfonos móviles en rangos de precios, en base a sus características
(memoria interna, ram, dimensiones…)
3.2. Carga de datos
Cargamos el conjunto de datos, que tiene 2000 registros y 21 columnas. Las 20
primeras columnas son las características de los teléfonos móviles y la última columna
es la variable objetivo (el rango de precios)
INTRODUCCIÓN AL DEEP LEARNING 9
df = pd.read_csv("[Link]")
print([Link])
features = [Link][:,:20].values
labels = [Link][:,20:21].values
[Link](5)
(2000, 21)
Imprimimos el número de clases de la variable objetivo
print("Número de clases del rango de precios: ",
len(df["price_range"].unique()))
Número de clases del rango de precios: 4
3.3. Preprocesamiento
Las redes neuronales requieren que los datos de entrada se encuentren en formato
numérico y en el mismo rango, normalmente [0, 1] o [-1, 1]. De esta forma todas las
variables tendrán el mismo "peso". Para ello, escalamos a ese rango todas las variables
características. También se requiere binarizar la variable objetivo cuando existen más
de dos clases, para lo que utilizamos One Hot Encoder.
sc = MinMaxScaler()
features = sc.fit_transform(features)
ohe = OneHotEncoder()
labels = ohe.fit_transform(labels).toarray()
Hacemos la separación en conjuntos de entrenamiento y test, reservando un 25% de
los datos del conjunto original para los datos del test
X_train, X_test, y_train, y_test = train_test_split(features, labels,
test_size=0.25)
3.4. Diseño de la red neuronal
Debemos especificar las dimensiones del conjunto de entrada (20 columnas) y el
número de clases a la salida de la red (4 clases)
INTRODUCCIÓN AL DEEP LEARNING 10
input_dim = len([Link])-1
output_dim = len(df["price_range"].unique())
A continuación, se diseña la arquitectura de la red. Para realizar este diseño se debe
tener en cuenta el volumen de datos y la complejidad de los conceptos que se desean
aprender, así como encontrar una configuración de hiperparámetros (nº de neuronas,
nº de capas ocultas, tasa de aprendizaje, épocas...) óptima. Esto último se conoce
como tuning y pueden utilizarse técnicas como GridSearch para encontrar la mejor
configuración entre todas las posibles combinaciones.
Para este problema, tenemos la siguiente arquitectura (como resultado del tuning): La
capa de entrada (dada por las dimensiones del conjunto de entrada), dos capas ocultas
completamente conectadas (densas), con 3 y 5 neuronas respectivamente y la capa de
salida densa con las 4 neuronas correspondientes a las 4 clases a predecir. Además, se
utiliza la función de activación ReLu para las capas ocultas y la función softmax para a
la salida (ya que se trata de un problema de clasificación múltiple).
model = Sequential()
[Link](Dense(3, input_shape=(input_dim,), activation='relu'))
[Link](Dense(5, activation='relu'))
[Link](Dense(output_dim, activation='softmax'))
[Link]()
Model: "sequential_1"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
dense_3 (Dense) (None, 3) 63
_________________________________________________________________
dense_4 (Dense) (None, 5) 20
_________________________________________________________________
dense_5 (Dense) (None, 4) 24
=================================================================
Total params: 107
Trainable params: 107
Non-trainable params: 0
_________________________________________________________________
Se van a entrenar 107 parámetros, que no son demasiados, por lo que el modelo no
debe tardar demasiado en entrenar.
Compilamos el modelo y especificamos como función de pérdidas la función de
entropía cruzada, el optimizador Adam, una tasa de aprendizaje (lr) de 0.001 y la
métrica accuracy para evaluar la calidad del modelo al final del entrenamiento.
[Link](loss='categorical_crossentropy',
optimizer=Adam(lr=0.001), metrics=['accuracy'])
INTRODUCCIÓN AL DEEP LEARNING 11
3.5. Entrenamiento
Añadimos un contador del tiempo para ver cuánto tarda el modelo en entrenar.
Finalmente ejecutamos el entrenamiento, especificando los últimos hiperparámetros:
500 épocas (como máximo) y un batch size de 64. Además, utilizamos early stopping
como técnica de regularización, especificando un valor mínimo de mejora (min_delta),
el número de épocas máximo sin mejoras para parar el entrenamiento (patience) y
restaurar los valores de los pesos en la época con mejores resultados.
start_time = timeit.default_timer()
history = [Link](X_train, y_train,
epochs=500,
batch_size=64,
callbacks=[EarlyStopping(min_delta=0.001,
patience=20,
restore_best_weights=
True)],
validation_data = (X_test, y_test),
verbose=0)
elapsed = timeit.default_timer() - start_time
3.6. Evaluación
Representamos el histórico del entrenamiento (los resultados para cada época) de la
precisión y las pérdidas, para los conjuntos de entrenamiento y validación
[Link]([Link]['accuracy'])
[Link]([Link]['val_accuracy'])
[Link]('Model accuracy')
[Link]('Accuracy')
[Link]('Epoch')
[Link](['Train_acc', 'Test_acc'], loc='upper left')
[Link]()
[Link]([Link]['loss'])
[Link]([Link]['val_loss'])
[Link]('Model loss')
[Link]('Loss')
[Link]('Epoch')
[Link](['Train_loss', 'Test_loss'], loc='upper left')
[Link]()
INTRODUCCIÓN AL DEEP LEARNING 12
Vemos en las gráficas que el entrenamiento se ha realizado durante un número
suficiente de épocas para que caigan las pérdidas de forma notable, evitando así el
underfitting; y que las curvas de ambos conjuntos van muy parejas, lo que indica que el
modelo generaliza y evita el overfitting. Llega un momento en el que el modelo apenas
mejora y se para el entrenamiento gracias al early stopping.
INTRODUCCIÓN AL DEEP LEARNING 13
print("Tiempo de entrenamiento (en s): ",elapsed)
print("Accuracy: ",[Link]('val_accuracy')[-1]*100,"%")
Tiempo de entrenamiento (en s): 5.1758676
Accuracy: 97.39999771118164 %
La red ha entrenado en unos 5 segundos y alcanza en torno al 97.4% de precisión (muy
alta) a la hora de clasificar nuevos teléfonos móviles en rangos de precios según sus
características.
3.7. Predicción
Podemos ver cómo la red clasifica nuevas observaciones (nuevos teléfonos móviles)
seleccionando los cinco primeros registros del conjunto de prueba
predictions = [Link](X_test)
for i in range(5):
print("Móvil", i+1)
print("Clase real:", [Link](y_test[i]), "| Clase predicha:",
[Link](predictions[i]),
"con una probabilidad del", [Link](predictions[i]),"%")
print("-----------------------------------------------------------
------------")
Móvil 1
Clase real: 3 | Clase predicha: 3 con una probabilidad del 0.9997116 %
----------------------------------------------------------------------
Móvil 2
Clase real: 1 | Clase predicha: 1 con una probabilidad del 0.9999583 %
----------------------------------------------------------------------
Móvil 3
Clase real: 3 | Clase predicha: 3 con una probabilidad del 0.999987 %
----------------------------------------------------------------------
Móvil 4
Clase real: 0 | Clase predicha: 0 con una probabilidad del 0.9983012 %
----------------------------------------------------------------------
Móvil 5
Clase real: 0 | Clase predicha: 0 con una probabilidad del 0.9998516 %
----------------------------------------------------------------------
Vemos que en todos los casos la clase real coincide con la predicha con una
probabilidad muy elevada, por lo que la red obtiene muy buenos resultados y
generaliza para nuevas observaciones.
INTRODUCCIÓN AL DEEP LEARNING 14
4. DEEP LEARNING EN IMÁGENES. REDES CONVOLUCIONALES.
4.1. Introducción y conceptos generales
Gracias al uso del Deep Learning en imágenes se está avanzando muy rápidamente en
el área de la inteligencia artificial que es capaz de reconocer imágenes: la visión
artificial (computer vision). Los modelos de Deep Learning aplicados a las imágenes son
capaces de resolver problemas como clasificar imágenes y detectar objetos, con
aplicaciones tales como el reconocimiento facial, los vehículos autónomos, los
diagnósticos de salud o la monitorización de procesos industriales, entre muchos
otros.
Para este tipo de tareas se utiliza un tipo concreto de redes neuronales profundas: las
redes neuronales convolucionales (LeCun, 1989) o CNN por sus siglas en inglés. Este
tipo de redes tienen una arquitectura y unas características especiales que las hacen
idóneas para trabajar con datos en forma de cuadrícula, como las imágenes.
Una imagen contiene un número concreto de píxeles de ancho y de alto, dependiendo
de su resolución. El valor de cada píxel va entre 0 y 255 según su intensidad, aunque se
normalizan entre 0 y 1 para entrar en la red. Si la imagen es en color, el número de
píxeles se multiplica por tres, debido a los tres canales del color: rojo, verde y azul. Así,
si consideramos una imagen en color en alta resolución, por ejemplo, en 4K, ésta
contendría 3840 * 2160 * 3 píxeles, lo que supondría un vector de casi 25 millones de
neuronas de entrada sólo para almacenar la imagen. Procesar esta imagen mediante
una gran red neuronal completamente conectada podría suponer un procesamiento
de miles de millones de parámetros, por lo que este tipo de arquitectura puede
acarrear enormes costes computacionales, además de no ser apta para reconocer
dependencias espaciales.
Para que el procesamiento pueda ser asequible y que la red pueda aprender ciertos
patrones espaciales, necesitamos entonces alguna operación capaz de reducir esta
dimensionalidad pero que pueda conservar al máximo la información contenida en las
imágenes. Esta operación es la operación de convolución, que es la operación
fundamental de las redes convolucionales.
La operación de convolución es capaz de extraer las características propias de una
imagen de entrada. En concreto, lo que extrae esta operación se conoce como mapa
de características (𝑆), resultado de aplicar un filtro o kernel (𝐾) a una imagen de
entrada (𝐼):
INTRODUCCIÓN AL DEEP LEARNING 15
El mapa de características, resultado de la convolución, vendrá dado por la expresión:
Los kernels suelen tener un tamaño mucho más reducido que la entrada y dar como
resultado una salida más reducida que la entrada. Se aplicarán tantas convoluciones
(con sus respectivos kernels) como mapas de características se quieran obtener.
Los mapas de características contienen los patrones detectados en las imágenes, de
forma que podrán activar los píxeles en los lugares donde se encuentran dichos
patrones. Los mapas de características irán siendo cada vez más específicos a medida
que la red avanza en profundidad.
4.2. Descripción de propiedades
Junto a la convolución, las CNN también tienen otras propiedades únicas que las
diferencian del resto, y que hacen que el entrenamiento sea más rápido y mejor
adaptado al trabajo con imágenes:
● Conexión dispersa
Como hemos dicho, en las CNN se trabaja con un kernel con unas
dimensiones mucho más reducidas que las dimensiones de la
capa de entrada, y de forma que un subconjunto de neuronas de
cierta capa, que define cierta característica local en el espacio, se
conecta a un subconjunto más reducido de neuronas de la capa
siguiente, que a su vez podrá conectarse a un subconjunto aún
menor. Estos filtros (o kernels) que definen los subconjuntos
también se conocen como campos receptivos locales. El tamaño
de los campos receptivos locales irá aumentando su tamaño a
medida que aumentamos la profundidad de la red, para captar
características cada vez más específicas en áreas cada vez más amplias .
● Parámetros compartidos
INTRODUCCIÓN AL DEEP LEARNING 16
Las CNN utilizan los mismos parámetros (pesos y sesgos) en cada una de las
neuronas de una misma capa oculta, que dependerán de las dimensiones del
campo receptivo local definidas por las diferentes características que se desean
detectar.
En esencia, lo que se hace es identificar una característica y desplazarla por
diferentes puntos del espacio, de forma que se comparten los parámetros para
poder detectar un mismo patrón en cualquier parte de la imagen. Estos
parámetros compartidos definen los diferentes kernels y mapas de características,
y hacen que las redes convolucionales mantengan la propiedad de invariancia
mediante movimientos de traslación. La salida de las neuronas viene dada
entonces por una expresión como la siguiente:
𝑛−1 𝑛−1
𝑓 (𝑏 + ∑ ∑ 𝜔𝑙,𝑚 𝑝𝑗+𝑙,𝑘+𝑚 )
𝑙=0 𝑚=0
donde 𝑓 es la función de activación, 𝑏 es el valor del sesgo compartido, 𝜔𝑙,𝑚 son
los pesos compartidos y 𝑝𝑥,𝑦 son las entradas en cada posición.
Habrá tantos mapas de características como patrones se quieran detectar en las
imágenes.
● Pooling
Además de las capas convolucionales, otra capa muy habitual y propia de las CNN
es la capa de agrupamiento (pooling) que suelen encontrarse a continuación de las
capas de convolución. Estas capas tienen por objetivo aglutinar la información
extraída por las capas convolucionales, reduciendo el número de parámetros que
deberá procesar la red pero manteniendo la información de las características
aprendidas.
El max-pooling es la función más utilizada en las capas de agrupamiento de las
CNN, que selecciona el valor más alto de cada subconjunto de entrada:
4.3. Ejemplo de clasificador de imágenes con CNN
4.3.1 Objetivo
Construir una CNN que sea capaz de "ver e identificar" imágenes de prendas de vestir.
INTRODUCCIÓN AL DEEP LEARNING 17
4.3.2 Carga de datos
En concreto, vamos a trabajar sobre el conjunto de datos fashion_mnist que puede ser
importado directamente desde con Keras.
(x_train_orig, y_train_orig), (x_test_orig, y_test_orig) =
fashion_mnist.load_data()
Este conjunto de datos consta de imágenes de 10 tipos de prendas de vestir, con
60000 imágenes para entrenar y 10000 para evaluar. Sin entrar en detalles en el
código (ver vídeo de ejemplo), veamos algunas de las imágenes:
4.3.3 Preprocesamiento
Especificamos que las dimensiones de cada conjunto y las dimensiones de las
imágenes, que vienen dadas en 28x28 píxeles y escala de grises (1 canal).
X_train = x_train_orig.reshape(60000,28,28,1)
X_test = x_test_orig.reshape(10000,28,28,1)
INTRODUCCIÓN AL DEEP LEARNING 18
y_train = to_categorical(y_train_orig, 10) #OneHotEncoding
y_test = to_categorical(y_test_orig, 10)
4.3.4 Diseño de la arquitectura
Implementamos la siguiente arquitectura de CNN, sin entrar en detalles en su
selección (proceso similar al ejemplo del perceptrón multicapa):
model = Sequential()
[Link](Conv2D(32, kernel_size=3, strides=(1,1), activation="relu",
input_shape=(28,28,1)))
[Link](Conv2D(64, kernel_size=3, strides=(1,1), activation="relu"))
[Link](MaxPooling2D(pool_size=(2,2), strides=(2,2)))
[Link](Dropout(0.25))
[Link](Flatten())
[Link](Dense(128, activation="relu"))
[Link](Dropout(0.5))
[Link](Dense(10, activation="softmax"))
[Link]()
Model: "sequential_4"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d_8 (Conv2D) (None, 26, 26, 32) 320
_________________________________________________________________
conv2d_9 (Conv2D) (None, 24, 24, 64) 18496
_________________________________________________________________
max_pooling2d_7 (MaxPooling2 (None, 12, 12, 64) 0
_________________________________________________________________
dropout_11 (Dropout) (None, 12, 12, 64) 0
_________________________________________________________________
flatten_4 (Flatten) (None, 9216) 0
_________________________________________________________________
dense_7 (Dense) (None, 128) 1179776
_________________________________________________________________
dropout_12 (Dropout) (None, 128) 0
_________________________________________________________________
dense_8 (Dense) (None, 10) 1290
=================================================================
Total params: 1,199,882
Trainable params: 1,199,882
Non-trainable params: 0
_________________________________________________________________
Se van a entrenar más de un millón de parámetros, por lo que el modelo entrenará
durante un tiempo notable. Esto puede acelerarse mediante el entrenamiento con
GPU’s, muy utilizadas en problemas con redes convolucionales.
INTRODUCCIÓN AL DEEP LEARNING 19
4.3.5 Entrenamiento
[Link](loss='categorical_crossentropy',
optimizer=Adadelta(), metrics=['accuracy'])
start_time = timeit.default_timer()
history = [Link](X_train, y_train,
epochs=50,
batch_size=128,
callbacks=[EarlyStopping(min_delta=0.001,
patience=10,
restore_best_weights=True)],
validation_data = (X_test, y_test),
verbose=0)
elapsed = timeit.default_timer() - start_time
4.3.6 Evaluación
Según el gráfico de pérdidas, nada parece indicar que se esté produciendo underfitting
ni overfitting. Quizás se pueda entrenar el modelo durante más épocas para mejorar el
resultado (no se ha producido early stopping) o adaptar el valor mínimo de mejora
para que se produzca early stopping y entrenar menos épocas (en detrimento de la
precisión).
Tiempo de entrenamiento (en s): 1243.0883327000001
Accuracy: 78.67000102996826 %
INTRODUCCIÓN AL DEEP LEARNING 20
El modelo ha tardado unos 20 minutos en entrenar y alcanza una precisión del 78.67%
al clasificar las nuevas imágenes del conjunto de validación.
4.3.7 Predicción
Sin entrar en detalles en el código, veamos qué tal predice el modelo la clase de las
primeras nueve imágenes del conjunto de validación.
predictions = [Link](X_test)
En verde aparecen las imágenes clasificadas correctamente y en rojo las incorrectas,
junto al porcentaje de probabilidad asociada a la clase mayoritaria predicha por el
modelo. Vemos que predice correctamente la mayoría de las imágenes excepto dos,
debido probablemente a que los jerséis, camisas… son clases con patrones muy
similares que la red identifica peor. Sin embargo, los pantalones los identifica con un
100% de probabilidad, ya que son prendas con una forma única, muy diferente al
resto.
Podemos decir entonces que la red predice y generaliza correctamente y que los
resultados tienen bastante sentido.
INTRODUCCIÓN AL DEEP LEARNING 21
5. DEEP LEARNING EN SERIES TEMPORALES. REDES
RECURRENTES.
5.1. Introducción y conceptos generales
Las series temporales representan un conjunto de observaciones ordenadas
secuencialmente en el tiempo, donde tanto los valores más cercanos al presente como
los del pasado pueden tener un impacto a la hora de pronosticar el futuro.
Podemos encontrar series temporales en muchos ámbitos: la banca, la meteorología,
el comercio… cualquier variable cuyas observaciones se distribuyen secuencialmente a
lo largo del tiempo puede interpretarse como una serie temporal. Con modelos de
predicción de series temporales seríamos capaces de extraer los patrones contenidos
en los datos y predecir los valores futuros de una variable observada, algo que puede
otorgar un gran valor informativo en todos esos ámbitos.
A diferencia de otros problemas de aprendizaje supervisado, donde se elaboran
modelos a partir de ciertas observaciones de una variable sin importar el orden en que
se reciban; en el caso de las series temporales existe una dependencia explícita del
orden de los datos debida a la dependencia temporal y ciertas estructuras internas
como tendencia, estacionariedad, estacionalidad, heterocedasticidad… que hacen que
la modelización predictiva de series temporales sea una tarea relativamente más
compleja.
Dentro del paradigma del deep learning existen algunas arquitecturas de redes
neuronales capaces de trabajar con series temporales, haciendo que los modelos
puedan aprender dependencias del pasado teniendo en cuenta el orden temporal para
intervenir en la predicción del futuro. Este tipo de arquitectura son las redes
neuronales recurrentes (Jordan, 1986) o RNN por sus siglas en inglés, dentro de las
cuales las long short-term memory (Hochreiter y Schmidhuber, 1997) son muy
populares.
● Recurrencia
La recurrencia es una forma de conexión propia de las RNN, que consiste en que las
neuronas de cierta capa estarán conectadas tanto a los datos de entrada como a la
salida de la propia capa, haciendo que la red pueda aprender información de los
pasos inmediatamente anteriores y adaptar sus resultados en base a esa
información. De este modo la información podrá fluir de forma recurrente, hacia
adelante y hacia atrás.
INTRODUCCIÓN AL DEEP LEARNING 22
● Celda
Para este tipo de redes neuronales se define el concepto de celda, que es una
operación que tiene lugar para cada paso de tiempo y cuya representación más
genérica suele constar de dos entradas y dos salidas. Las entradas se corresponden
al estado de la red en el paso anterior y a los valores de la secuencia en cada paso,
y las salidas serán el estado de la red en el paso actual y la correspondiente
respuesta de la red.
Podemos entender el concepto de recurrencia como si la red estuviera
“enrollándose” sobre sí misma un número específico de celdas, correspondiente a
los pasos de tiempo, donde se comparten los parámetros internos y sólo
cambiarán las entradas y los estados de la red.
● Estado de la red
El estado de la red es la configuración interna que procesa una respuesta para cada
entrada. En el caso de la RNN, este estado puede variar según las entradas
INTRODUCCIÓN AL DEEP LEARNING 23
anteriores. Por eso, el estado de las RNN puede interpretarse como una “memoria”
artificial, que determinará la respuesta de la red en base a estados anteriores.
5.2. Descripción de las Long Short-Term Memory (LSTM)
La LSTM es la arquitectura de celda más habitual para tareas de predicción de series
temporales, ya que puede aprender sobre acontecimientos lejanos y cercanos en el
tiempo, y dar una respuesta en base a ambos según su importancia. Este tipo de celda
se caracteriza por tener un canal para la memoria y un control sobre la información
que fluye por la red, de forma que puede decidir qué parte de la información es
importante “memorizar” y qué parte se emite como respuesta.
Para poder llevar a cabo la decisión sobre el flujo de información, las LSTM constan de
un conjunto de puertas (de entrada, de salida y de olvido) que serán las encargadas de
filtrar la información que no se considera útil y dejar pasar la que sí puede serlo,
modificando el estado (o “memoria”) de la red en cada paso de tiempo.
El esquema general de una celda LSTM es:
INTRODUCCIÓN AL DEEP LEARNING 24
5.3. Ejemplo de predicción de series temporales con LSTM
5.3.1 Objetivo
Construir una RNN tipo LSTM que sea capaz de predecir series temporales. En
concreto, para cierta compañía aérea, se quiere predecir el número de pasajeros que
viajarán en cada mes del año siguiente.
5.3.2 Carga de datos
Este conjunto tiene datos mensuales del número de pasajeros desde 1949 a 1960
df = pd.read_csv('air_passengers.csv')
print([Link])
[Link](5)
Month AirPassengers
0 1949-01 112
1 1949-02 118
2 1949-03 132
3 1949-04 129
4 1949-05 121
5.3.3 Preprocesamiento
Debemos indicar cuál es la variable temporal
[Link] = pd.to_datetime([Link])
df = df.set_index("Month")
Es habitual para este tipo de tareas transformar la serie temporal a la forma de
aprendizaje supervisado, sin variar el orden temporal y reescalar los datos
train = df[:-12]
test = df[-12:]
sc = MinMaxScaler()
[Link](train)
train = [Link](train)
test = [Link](test)
También deben prepararse los datos para ser leídos en la forma adecuada por la red
LSTM, indicando: el nº de muestras (batch_size), la ventana temporal utilizada para
predecir (X) y la ventana temporal objetivo (y) en cada paso. En este caso indicamos
una ventana de entrada de 12 meses con el objetivo del mes siguiente
n_input = 12
n_features = 1
tsgen = TimeseriesGenerator(train, train,
length=n_input, batch_size=6)
INTRODUCCIÓN AL DEEP LEARNING 25
5.3.4 Diseño de la arquitectura
model = Sequential()
[Link](LSTM(200, activation='relu',
input_shape=(n_input, n_features)))
[Link](Dropout(0.2))
[Link](Dense(1))
[Link]()
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
lstm (LSTM) (None, 200) 161600
dropout (Dropout) (None, 200) 0
dense (Dense) (None, 1) 201
=================================================================
Total params: 161,801
Trainable params: 161,801
Non-trainable params: 0
_________________________________________________________________
5.3.5 Entrenamiento
[Link](optimizer=Adam(), loss='mse')
history = model.fit_generator(tsgen, epochs=150, verbose=0)
INTRODUCCIÓN AL DEEP LEARNING 26
5.3.6 Evaluación y predicción
Las pérdidas caen rápidamente y se estabilizan en las últimas épocas, por lo que
probablemente el modelo no puede mejorarse mucho más.
Hacemos predicciones para el último año de datos y la visualizamos junto al registro
histórico.
preds = []
batch = train[-n_input:].reshape((1, n_input, n_features))
for i in range(n_input):
[Link]([Link](batch)[0])
batch = [Link](batch[:,1:,:],[[preds[i]]],axis=1)
df_pred = [Link](sc.inverse_transform(preds),
index=df[-n_input:].index,
columns=['Prediction'])
df_tot = [Link]([df,df_pred], axis=1)
INTRODUCCIÓN AL DEEP LEARNING 27
Vemos que la predicción tiene sentido en relación con los datos reales.
Se puede evaluar esta predicción tomando como métrica, por ejemplo, el RMSE. Se
debe comparar el RMSE de esta predicción con el RMSE de otro modelo que sirva de
base para poder interpretar sus valores y la calidad del modelo. Tomamos el valor
medio de pasajeros en un año como modelo predictor de referencia.
pred_rmse = rmse(df_tot.iloc[-n_input:, [0]],
df_tot.iloc[-n_input:, [1]])
mean_rmse = rmse(df_tot.iloc[-n_input:, [0]],
df[-n_input:].mean())
print("rmse_pred: ", pred_rmse)
print("rmse_mean: ", mean_rmse)
rmse_pred: [34.95544681]
rmse_mean: [74.42763077]
En base al RMSE, la predicción con LSTM mejora notablemente a la obtenida con el
valor medio.
5.3.7 Pronóstico del futuro
Para hacer pronósticos reales (sin datos conocidos) se debe reentrenar la red con
todos los datos disponibles
train = df
[Link](train)
train = [Link](train)
tsgen = TimeseriesGenerator(train, train, length=n_input,
batch_size=6)
history = model.fit_generator(tsgen, epochs=150, verbose=0)
preds = []
batch = train[-n_input:].reshape((1, n_input, n_features))
for i in range(n_input):
[Link]([Link](batch)[0])
batch = [Link](batch[:,1:,:],[[preds[i]]],axis=1)
INTRODUCCIÓN AL DEEP LEARNING 28
add_months = [[Link][-1] + DateOffset(months=x)
for x in range(0,13) ]
future_months = [Link](index=add_months[1:],
columns=[Link])
df_pred = [Link](sc.inverse_transform(preds),
index=future_months[-n_input:].index,
columns=['Forecasting'])
df_tot = [Link]([df,df_pred], axis=1)
Vemos que el pronóstico para 1961 tiene bastante sentido y puede decirse que la red
tiene buena capacidad predictiva para esta serie temporal.
6. CONCLUSIÓN
En este curso hemos visto, de forma introductoria, los fundamentos básicos de las
redes neuronales artificiales, de qué se componen y qué funciones y métodos emplean
para aprender conceptos complejos durante su entrenamiento.
Se han presentado las redes neuronales convolucionales y las recurrentes, para tareas
con imágenes y series temporales, respectivamente.
También, hemos desarrollado varios ejemplos prácticos, para cada tipo de red
presentada, empleando el lenguaje Python y la librería Keras.
El objetivo ha sido obtener una primera visión general del paradigma del deep
learning, presentando las redes neuronales “tradicionales” que pueden desempeñar
tareas complejas. Sin embargo, se debe tener en cuenta que este paradigma se
encuentra en constante evolución, ya que gracias a los avances tecnológicos y en
investigación, surgen nuevos modelos de aprendizaje profundo capaces de resolver
problemas aún más complejos.
INTRODUCCIÓN AL DEEP LEARNING 29