1. Descripción general
En este lab, aprenderás a ensamblar una capa convolucional en un modelo de red neuronal que pueda reconocer flores. Esta vez, crearás el modelo desde cero y usarás la potencia de las TPU para entrenarlo en segundos y iterar en su diseño.
Este lab incluye las explicaciones teóricas necesarias sobre las redes neuronales convolucionales y es un buen punto de partida para los desarrolladores que aprenden sobre el aprendizaje profundo.
Este lab es la parte 3 de la serie “Keras en TPU”. Puedes hacerlo en el siguiente orden o de forma independiente.
- Canalizaciones de datos con velocidades de TPU: tf.data.Dataset y TFRecords
- Tu primer modelo de Keras, con aprendizaje transferible
- [ESTE LAB] Redes neuronales convolucionales, con Keras y TPU
- Convnets modernos, squeezenet, Xception, con Keras y TPU
Qué aprenderás
- Compilar un clasificador de imágenes convolucional mediante un modelo secuencial de Keras
- Para entrenar tu modelo de Keras en TPU
- Para ajustar tu modelo con una buena elección de capas convolucionales.
Comentarios
Si detectas que falta algo en este codelab, comunícate con nosotros. Los comentarios se pueden enviar a través de los problemas de GitHub [ vínculo de comentarios].
2. Inicio rápido de Google Colaboratory
En este lab, se usa Google Colaboratory y no requiere configuración de tu parte. Colaboratory es una plataforma de notebooks en línea con fines educativos. Ofrece entrenamiento gratuito sobre CPU, GPU y TPU.
Puedes abrir este notebook de muestra y ejecutar algunas celdas para familiarizarte con Colaboratory.
Selecciona un backend de TPU
En el menú de Colab, selecciona Entorno de ejecución > Cambiar tipo de entorno de ejecución y, luego, selecciona TPU. En este codelab, usarás una potente TPU (unidad de procesamiento tensorial) respaldada para el entrenamiento acelerado por hardware. La conexión al entorno de ejecución se realizará automáticamente en la primera ejecución, o bien puedes usar el botón "Conectar" en la esquina superior derecha.
Ejecución del notebook
Para ejecutar celdas una a la vez, haz clic en una celda y usa Mayúsculas + Intro. También puedes ejecutar todo el notebook con Runtime > Run all.
Índice
Todos los notebooks tienen un índice. Puedes abrirlo con la flecha negra de la izquierda.
Celdas ocultas
Algunas celdas solo mostrarán su título. Esta es una función de notebook específica de Colab. Puedes hacer doble clic en ellos para ver el código que contiene, pero, por lo general, no es muy interesante. Por lo general, admiten funciones de visualización. Aún debes ejecutar estas celdas para que se definan las funciones que contienen.
Autenticación
Colab puede acceder a tus buckets privados de Google Cloud Storage, siempre que te autentiques con una cuenta autorizada. El fragmento de código anterior activará un proceso de autenticación.
3. [INFO] ¿Qué son las unidades de procesamiento tensorial (TPU)?
En resumen
El código para entrenar un modelo en TPU en Keras (y recurrir a GPU o CPU si no hay TPU disponible):
try: # detect TPUs
tpu = tf.distribute.cluster_resolver.TPUClusterResolver.connect()
strategy = tf.distribute.TPUStrategy(tpu)
except ValueError: # detect GPUs
strategy = tf.distribute.MirroredStrategy() # for CPU/GPU or multi-GPU machines
# use TPUStrategy scope to define model
with strategy.scope():
model = tf.keras.Sequential( ... )
model.compile( ... )
# train model normally on a tf.data.Dataset
model.fit(training_dataset, epochs=EPOCHS, steps_per_epoch=...)
Hoy usaremos TPU para crear y optimizar un clasificador de flores a velocidades interactivas (minutos por ejecución de entrenamiento).
¿Por qué usar TPU?
Las GPU modernas se organizan en torno a "núcleos" programables, una arquitectura muy flexible que les permite controlar una variedad de tareas, como la renderización en 3D, el aprendizaje profundo, las simulaciones físicas, etcétera. Por otro lado, las TPU combinan un procesador vectorial clásico con una unidad de multiplicación de matrices dedicada y se destacan en cualquier tarea en la que predominan las multiplicaciones de matrices grandes, como las redes neuronales.
Ilustración: una capa de red neuronal densa como una multiplicación de matrices, con un lote de ocho imágenes procesadas a través de la red neuronal a la vez. Analiza la multiplicación de una línea por una columna para verificar que efectivamente se realice una suma ponderada de todos los valores de píxeles de una imagen. Las capas convolucionales también se pueden representar como multiplicaciones de matrices, aunque es un poco más complicado ( aquí se explica en la sección 1).
El hardware
MXU y VPU
Un núcleo de TPU v2 consta de una unidad de multiplicación de matrices (MXU) que ejecuta multiplicaciones de matrices y una unidad de procesamiento vectorial (VPU) para todas las demás tareas, como activaciones, softmax, etc. La VPU controla los cálculos de float32 y int32. Por otro lado, la MXU opera en un formato de punto flotante de precisión mixta de 16 a 32 bits.
Punto flotante de precisión mixto y bfloat16
La MXU calcula las multiplicaciones de matrices con entradas bfloat16 y salidas float32. Las acumulaciones intermedias se realizan con precisión de float32.
El entrenamiento de redes neuronales suele ser resistente al ruido que introduce una precisión de punto flotante reducida. Hay casos en los que el ruido incluso ayuda a la convergencia del optimizador. Tradicionalmente, la precisión de punto flotante de 16 bits se ha usado para acelerar los cálculos, pero los formatos float16 y float32 tienen rangos muy diferentes. Reducir la precisión de float32 a float16 suele generar un exceso y subdesbordamiento. Las soluciones existen, pero normalmente se requiere trabajo adicional para que float16 funcione.
Por eso, Google introdujo el formato bfloat16 en las TPU. bfloat16 es un número de punto flotante truncado con exactamente los mismos bits de exponente y rango que el número de punto flotante. Esto, sumado al hecho de que las TPU calculan multiplicaciones de matrices en precisión mixta con entradas bfloat16 pero resultados float32, significa que, por lo general, no se necesitan cambios en el código para beneficiarse de las mejoras en el rendimiento de la precisión reducida.
Array sistólico
La MXU implementa multiplicaciones de matrices en hardware usando una arquitectura llamada “array sistólico” en la que los elementos de datos fluyen por un array de unidades de procesamiento de hardware. (En medicina, "sistólica" hace referencia a las contracciones del corazón y al flujo sanguíneo, y aquí al flujo de datos).
El elemento básico de una multiplicación de matrices es un producto escalar entre una línea de una matriz y una columna de la otra (consulta la ilustración en la parte superior de esta sección). Para una multiplicación de matrices Y=X*W, un elemento del resultado sería el siguiente:
Y[2,0] = X[2,0]*W[0,0] + X[2,1]*W[1,0] + X[2,2]*W[2,0] + ... + X[2,n]*W[n,0]
En una GPU, se programaría este producto punto en un "núcleo" de GPU y, luego, se ejecutaría en tantos "núcleos" como estén disponibles en paralelo para intentar calcular todos los valores de la matriz resultante a la vez. Si la matriz resultante es de 128 × 128 grande, eso requeriría que haya 128 × 128=16,000 “núcleos” disponibles, lo cual generalmente no es posible. Las GPU más grandes tienen alrededor de 4,000 núcleos. Por otro lado, una TPU usa el mínimo de hardware para las unidades de procesamiento en la MXU: solo bfloat16 x bfloat16 => float32
multiplicadores-acumuladores, nada más. Son tan pequeños que una TPU puede implementar 16,000 de ellos en una MXU de 128 x 128 y procesar esta multiplicación de matrices de una sola vez.
Ilustración: Array sistólico de MXU. Los elementos de procesamiento son acumuladores de multiplicación. Los valores de una matriz se cargan en el array (puntos rojos). Los valores de la otra matriz fluyen a través del array (puntos grises). Las líneas verticales propagan los valores hacia arriba. Las líneas horizontales propagan las sumas parciales. Queda como ejercicio para el usuario verificar que, a medida que los datos fluyen a través del array, se obtiene el resultado de la multiplicación de matrices que sale del lado derecho.
Además, mientras se calculan los productos escalares en una MXU, las sumas intermedias simplemente fluyen entre unidades de procesamiento adyacentes. No es necesario que se almacenen y recuperen en la memoria o incluso desde un archivo de registro. El resultado final es que la arquitectura del array sistólico de TPU tiene una ventaja significativa de densidad y potencia, así como una ventaja de velocidad no despreciable sobre una GPU, cuando se calculan multiplicaciones de matrices.
Cloud TPU
Cuando solicitas una "Cloud TPU v2" en Google Cloud Platform, obtienes una máquina virtual (VM) que tiene una placa TPU conectada a PCI. La placa de TPU tiene cuatro chips TPU de doble núcleo. Cada núcleo de TPU cuenta con una VPU (unidad de procesamiento vectorial) y una MXU (unidad de multiplicación de matriz) de 128 x 128. Por lo general, esta “Cloud TPU” se conecta a través de la red a la VM que la solicitó. Por lo tanto, la imagen completa se ve de la siguiente manera:
Ilustración: tu VM con un acelerador "Cloud TPU" conectado a la red. “La Cloud TPU” en sí está hecha de una VM con una placa de TPU conectada a PCI y cuatro chips TPU de doble núcleo.
Pods de TPU
En los centros de datos de Google, las TPU se conectan a una interconexión de procesamiento de alto rendimiento (HPC), lo que puede hacer que aparezcan como un acelerador muy grande. Google los llama Pods, que pueden abarcar hasta 512 núcleos TPU v2 o 2,048 núcleos TPU v3.
Ilustración: un pod de TPU v3. Placas y bastidores de TPU conectados a través de la interconexión de HPC
Durante el entrenamiento, los gradientes se intercambian entre los núcleos de TPU con el algoritmo de reducción total (aquí hay una buena explicación de la reducción total). El modelo que se está entrenando puede aprovechar el hardware entrenando con tamaños de lotes grandes.
Ilustración: sincronización de gradientes durante el entrenamiento con el algoritmo de reducción total en la red de HPC de malla toroidal 2D de Google TPU.
El software
Capacitación con un tamaño de lote grande
El tamaño de lote ideal para las TPU es de 128 elementos de datos por núcleo de TPU, pero el hardware ya puede mostrar una buena utilización a partir de 8 elementos de datos por núcleo de TPU. Recuerda que una Cloud TPU tiene 8 núcleos.
En este codelab, usaremos la API de Keras. En Keras, el lote que especifiques será el tamaño del lote global para toda la TPU. Tus lotes se dividirán automáticamente en 8 y se ejecutarán en los 8 núcleos de la TPU.
Para obtener más sugerencias sobre el rendimiento, consulta la Guía de rendimiento de TPU. En el caso de los tamaños de lote muy grandes, puede ser necesario tener especial cuidado en algunos modelos. Consulta LARSOptimizer para obtener más detalles.
Detrás de escena: XLA
Los programas de TensorFlow definen grafos de procesamiento. La TPU no ejecuta directamente el código de Python, sino el grafo de procesamiento definido por tu programa de TensorFlow. En el fondo, un compilador llamado XLA (compilador de álgebra lineal acelerada) transforma el grafo de nodos de procesamiento de TensorFlow en código máquina de TPU. Este compilador también realiza muchas optimizaciones avanzadas en el código y el diseño de la memoria. La compilación se realiza automáticamente a medida que el trabajo se envía a la TPU. No es necesario que incluyas XLA en tu cadena de compilación de forma explícita.
Ilustración: Para ejecutarse en TPU, el grafo de cómputo definido por tu programa de Tensorflow primero se traduce a una representación de XLA (compilador de álgebra lineal acelerado) y, luego, XLA lo compila en código máquina de TPU.
Usa TPU en Keras
Las TPU son compatibles con la API de Keras a partir de TensorFlow 2.1. La compatibilidad con Keras funciona en TPU y pods de TPU. A continuación, te mostramos un ejemplo que funciona con TPU, GPU y CPU:
try: # detect TPUs
tpu = tf.distribute.cluster_resolver.TPUClusterResolver.connect()
strategy = tf.distribute.TPUStrategy(tpu)
except ValueError: # detect GPUs
strategy = tf.distribute.MirroredStrategy() # for CPU/GPU or multi-GPU machines
# use TPUStrategy scope to define model
with strategy.scope():
model = tf.keras.Sequential( ... )
model.compile( ... )
# train model normally on a tf.data.Dataset
model.fit(training_dataset, epochs=EPOCHS, steps_per_epoch=...)
En este fragmento de código:
TPUClusterResolver().connect()
encuentra la TPU en la red. Funciona sin parámetros en la mayoría de los sistemas de Google Cloud (trabajos de AI Platform, Colaboratory, Kubeflow y VMs de aprendizaje profundo creadas a través de la utilidad "TextView up"). Estos sistemas saben dónde está su TPU gracias a una variable de entorno TPU_NAME. Si creas una TPU de forma manual, establece la variable de entorno TPU_NAME en la VM desde la que la usas o llama aTPUClusterResolver
con parámetros explícitos:TPUClusterResolver(tp_uname, zone, project)
TPUStrategy
es la parte que implementa la distribución y el algoritmo de sincronización de gradientes "todos los reduce".- La estrategia se aplica a través de un alcance. El modelo se debe definir dentro del alcance de la estrategia().
- La función
tpu_model.fit
espera un objeto tf.data.Dataset como entrada para el entrenamiento de TPU.
Tareas comunes de portabilidad de TPU
- Si bien existen muchas formas de cargar datos en un modelo de TensorFlow, para las TPU, es necesario usar la API de
tf.data.Dataset
. - Las TPU son muy rápidas y la transferencia de datos a menudo se convierte en un cuello de botella cuando se ejecutan en ellas. En la Guía de rendimiento de TPU, encontrarás herramientas que puedes usar para detectar cuellos de botella de datos y otras sugerencias de rendimiento.
- Los números int8 o int16 se tratan como int32. La TPU no tiene hardware de números enteros que funcione en menos de 32 bits.
- Algunas operaciones de TensorFlow no son compatibles. Consulta la lista aquí. La buena noticia es que esta limitación solo se aplica al código de entrenamiento, es decir, al paso hacia adelante y hacia atrás a través de tu modelo. Aún puedes usar todas las operaciones de TensorFlow en tu canalización de entrada de datos, ya que se ejecutarán en la CPU.
tf.py_func
no es compatible con TPU.
4. [INFO] Conceptos básicos del clasificador de redes neuronales
En resumen
Si ya conoces todos los términos en negrita del siguiente párrafo, puedes pasar al siguiente ejercicio. Si recién estás comenzando en el aprendizaje profundo, entonces bienvenido y sigue leyendo.
Para los modelos creados como una secuencia de capas, Keras ofrece la API secuencial. Por ejemplo, un clasificador de imágenes que usa tres capas densas se puede escribir en Keras de la siguiente manera:
model = tf.keras.Sequential([
tf.keras.layers.Flatten(input_shape=[192, 192, 3]),
tf.keras.layers.Dense(500, activation="relu"),
tf.keras.layers.Dense(50, activation="relu"),
tf.keras.layers.Dense(5, activation='softmax') # classifying into 5 classes
])
# this configures the training of the model. Keras calls it "compiling" the model.
model.compile(
optimizer='adam',
loss= 'categorical_crossentropy',
metrics=['accuracy']) # % of correct answers
# train the model
model.fit(dataset, ... )
Red neuronal densa
Esta es la red neuronal más simple para clasificar imágenes. Está formada por "neuronas" dispuestas en capas. La primera capa procesa los datos de entrada y envía sus resultados a otras capas. Se llama “densa” porque cada neurona está conectada a todas las neuronas en la capa anterior.
Para ingresar una imagen en una red de este tipo, aplana los valores RGB de todos sus píxeles en un vector largo y úsalo como entrada. No es la mejor técnica para el reconocimiento de imágenes, pero la mejoraremos más adelante.
Neuronas, activaciones y ReLU
Una “neurona” calcula una suma ponderada de todas sus entradas, agrega un valor llamado “sesgo” y alimenta el resultado a través de una llamada “función de activación”. Al principio, se desconocen los pesos y el sesgo. Se inicializarán al azar y se “aprenderán” a través del entrenamiento de la red neuronal con muchos datos conocidos.
La función de activación más popular se denomina RELU para la unidad lineal rectificada. Es una función muy simple, como puedes ver en el gráfico anterior.
Activación de softmax
La red anterior termina con una capa de 5 neuronas porque clasificamos las flores en 5 categorías (rosa, tulipán, diente de león, margarita y girasol). Las neuronas de las capas intermedias se activan con la función de activación RELU clásica. Sin embargo, en la última capa, queremos calcular números entre 0 y 1 que representen la probabilidad de que esta flor sea una rosa, un tulipán, etcétera. Para ello, usaremos una función de activación llamada "softmax".
Para aplicar softmax a un vector, se toma el exponencial de cada elemento y, luego, se normaliza el vector, por lo general, con la norma L1 (suma de valores absolutos) para que los valores sumen 1 y se puedan interpretar como probabilidades.
Pérdida de entropía cruzada
Ahora que nuestra red neuronal produce predicciones a partir de imágenes de entrada, debemos medir qué tan buenas son, es decir, la distancia entre lo que nos dice la red y las respuestas correctas, que a menudo se denominan "etiquetas". Recuerda que tenemos etiquetas correctas para todas las imágenes del conjunto de datos.
Cualquier distancia funcionaría, pero para los problemas de clasificación, la llamada "distancia de entropía cruzada" es la más eficaz. La llamaremos nuestra función de error o “pérdida”:
Descenso de gradientes
En realidad, “entrenar” la red neuronal significa usar imágenes y etiquetas de entrenamiento para ajustar las ponderaciones y los sesgos de modo que se minimice la función de pérdida de entropía cruzada. Así es como funciona.
La entropía cruzada es una función de pesos, sesgos, píxeles de la imagen de entrenamiento y su clase conocida.
Si calculamos las derivadas parciales de la entropía cruzada con respecto a todos los pesos y todos los sesgos, obtenemos un “gradiente”, calculado para una determinada imagen, etiqueta y valor actual de pesos y sesgos. Recuerda que podemos tener millones de pesos y sesgos, por lo que calcular el gradiente parece ser un trabajo muy arduo. Afortunadamente, Tensorflow lo hace por nosotros. La propiedad matemática de un gradiente es que apunta "hacia arriba". Como queremos ir donde la entropía cruzada es baja, vamos en la dirección opuesta. Actualizamos los pesos y los sesgos por una fracción del gradiente. Luego hacemos lo mismo una y otra vez con los siguientes lotes de imágenes de entrenamiento y etiquetas, en un bucle de entrenamiento. Se espera que esto converja en un lugar donde la entropía cruzada sea mínima, aunque nada garantiza que este mínimo sea único.
Minilotes y momento
Puedes calcular tu gradiente en una sola imagen de ejemplo y actualizar los pesos y sesgos de inmediato, pero hacerlo en un lote de, por ejemplo, 128 imágenes, proporciona un gradiente que representa mejor las restricciones que imponen diferentes imágenes de ejemplo y, por lo tanto, es probable que converja hacia la solución más rápido. El tamaño del minilote es un parámetro ajustable.
Esta técnica, a veces llamada "descenso estocástico del gradiente", tiene otro beneficio más pragmático: trabajar con lotes también significa trabajar con matrices más grandes, que suelen ser más fáciles de optimizar en GPUs y TPU.
Sin embargo, la convergencia puede ser un poco caótica y puede detenerse si el vector de gradiente es todo ceros. ¿Eso significa que encontramos un mínimo? No en todos los casos. Un componente de gradiente puede ser cero en un mínimo o máximo. En un vector gradiente con millones de elementos, si todos son ceros, la probabilidad de que cada cero corresponda a un mínimo y ninguno de ellos a un punto máximo es bastante pequeña. En un espacio de muchas dimensiones, los puntos silla son bastante comunes y no queremos detenernos en ellos.
Ilustración: un punto silla. El gradiente es 0, pero no es un mínimo en todas las direcciones. (Atribución de imagen Wikimedia: de Nicoguaro - trabajo propio, CC BY 3.0)
La solución es agregar algo de impulso al algoritmo de optimización para que pueda navegar más allá de la silla de montar sin detenerse.
Glosario
lote o minilote: el entrenamiento siempre se realiza en lotes de datos de entrenamiento y etiquetas. Eso ayuda a que el algoritmo converja. La dimensión “lote” suele ser la primera de los tensores de datos. Por ejemplo, un tensor de forma [100, 192, 192, 3] contiene 100 imágenes de 192 x 192 píxeles con tres valores por píxel (RGB).
pérdida de entropía cruzada: Es una función de pérdida especial que se usa con frecuencia en los clasificadores.
Capa densa: Es una capa de neuronas en la que cada neurona está conectada a todas las neuronas de la capa anterior.
atributos: A veces, las entradas de una red neuronal se denominan "atributos". El arte de descubrir qué partes de un conjunto de datos (o combinaciones de partes) alimentar a una red neuronal para obtener buenas predicciones se denomina “ingeniería de atributos”.
Etiquetas: Otro nombre para las "clases" o respuestas correctas en un problema de clasificación supervisada.
tasa de aprendizaje: fracción del gradiente por la cual se actualizan los pesos y los sesgos en cada iteración del ciclo de entrenamiento
Logits: Las salidas de una capa de neuronas antes de que se aplique la función de activación se denominan "logits". El término proviene de la "función logística", también conocida como "función sigmoidea", que solía ser la función de activación más popular. Se acortó "Neuron outputs before logistic function" a "logits".
pérdida: la función de error que compara las salidas de la red neuronal con las respuestas correctas
neuron: Calcula la suma ponderada de sus entradas, agrega un sesgo y alimenta el resultado a través de una función de activación.
Codificación one-hot: La clase 3 de 5 se codifica como un vector de 5 elementos, todos ceros, excepto el tercero, que es 1.
relu: unidad lineal rectificada. Es una función de activación popular para las neuronas.
sigmoidea: otra función de activación que solía ser popular y que aún es útil en casos especiales.
softmax: Es una función de activación especial que actúa sobre un vector, aumenta la diferencia entre el componente más grande y todos los demás, y también normaliza el vector para tener una suma de 1 de modo que pueda interpretarse como un vector de probabilidades. Se usa como el último paso en los clasificadores.
tensor: Un "tensor" es como una matriz, pero con una cantidad arbitraria de dimensiones. Un tensor unidimensional es un vector. Un tensor de 2 dimensiones es una matriz. Y, luego, puedes tener tensores con 3, 4, 5 o más dimensiones.
5. [NEW INFO] Redes neuronales convolucionales
En resumen
Si ya conoces todos los términos en negrita del siguiente párrafo, puedes pasar al siguiente ejercicio. Si recién comienzas a usar redes neuronales convolucionales, sigue leyendo.
Ilustración: Filtrado de una imagen con dos filtros sucesivos compuestos por pesos aprendebles de 4x4x3=48 cada uno.
Así es como se ve una red neuronal convolucional simple en Keras:
model = tf.keras.Sequential([
# input: images of size 192x192x3 pixels (the three stands for RGB channels)
tf.keras.layers.Conv2D(kernel_size=3, filters=24, padding='same', activation='relu', input_shape=[192, 192, 3]),
tf.keras.layers.Conv2D(kernel_size=3, filters=24, padding='same', activation='relu'),
tf.keras.layers.MaxPooling2D(pool_size=2),
tf.keras.layers.Conv2D(kernel_size=3, filters=12, padding='same', activation='relu'),
tf.keras.layers.MaxPooling2D(pool_size=2),
tf.keras.layers.Conv2D(kernel_size=3, filters=6, padding='same', activation='relu'),
tf.keras.layers.Flatten(),
# classifying into 5 categories
tf.keras.layers.Dense(5, activation='softmax')
])
model.compile(
optimizer='adam',
loss= 'categorical_crossentropy',
metrics=['accuracy'])
Introducción a las redes neuronales convolucionales
En una capa de una red convolucional, una "neurona" realiza una suma ponderada de los píxeles que se encuentran sobre ella, solo en una pequeña región de la imagen. Agrega un sesgo y alimenta la suma a través de una función de activación, tal como lo haría una neurona en una capa densa normal. Luego, esta operación se repite en toda la imagen con los mismos pesos. Recuerda que en las capas densas, cada neurona tenía sus propios pesos. Aquí, una sola "parcha" de pesos se desliza a través de la imagen en ambas direcciones (una "convolución"). La salida tiene tantos valores como píxeles en la imagen (aunque se necesita algo de relleno en los bordes). Es una operación de filtrado que utiliza un filtro de pesos 4x4x3=48.
Sin embargo, 48 pesos no serán suficientes. Para agregar más grados de libertad, repetimos la misma operación con un nuevo conjunto de pesos. Esto produce un nuevo conjunto de resultados de filtro. Llamemos a esto un “canal” de salidas por analogía con los canales R, G y B de la imagen de entrada.
Los dos (o más) conjuntos de pesos se pueden sumar como un tensor si se agrega una dimensión nueva. Esto nos da la forma genérica del tensor de pesos para una capa convolucional. Dado que la cantidad de canales de entrada y salida son parámetros, podemos comenzar a apilar y encadenar capas convolucionales.
Ilustración: una red neuronal convolucional transforma "cubos" de datos en otros "cubos" de datos.
Convolución con paso, reducción máxima
Si realizamos las convolución con un paso de 2 o 3, también podemos reducir el cubo de datos resultante en sus dimensiones horizontales. Existen dos formas comunes de hacerlo:
- Convolución con paso: Un filtro deslizante como el anterior, pero con un paso superior a 1.
- Reducción máxima: una ventana deslizante que aplica la operación MAX (generalmente en parches de 2 x 2, que se repite cada 2 píxeles)
Ilustración: Deslizar la ventana de procesamiento 3 píxeles da como resultado menos valores de salida. Las contracciones con paso o la reducción máxima (máximo en una ventana de 2 × 2 que se desliza con un paso de 2) son una forma de reducir el cubo de datos en las dimensiones horizontales.
Clasificador convolucional
Por último, adjuntamos una cabeza de clasificación aplanando el último cubo de datos y pasándolo a través de una capa densa activada por softmax. Un clasificador de convoluciones típico puede verse de la siguiente manera:
Ilustración: un clasificador de imágenes que usa capas convolucionales y softmax. Usa filtros de 3 × 3 y 1 × 1. Las capas maxpool toman el máximo de grupos de 2 x 2 datos. El cabezal de clasificación se implementa con una capa densa con activación de softmax.
En Keras
La pila convolucional ilustrada anteriormente se puede escribir en Keras de la siguiente manera:
model = tf.keras.Sequential([
# input: images of size 192x192x3 pixels (the three stands for RGB channels)
tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu', input_shape=[192, 192, 3]),
tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
tf.keras.layers.MaxPooling2D(pool_size=2),
tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu'),
tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
tf.keras.layers.MaxPooling2D(pool_size=2),
tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu'),
tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
tf.keras.layers.MaxPooling2D(pool_size=2),
tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu'),
tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
tf.keras.layers.MaxPooling2D(pool_size=2),
tf.keras.layers.Conv2D(kernel_size=3, filters=16, padding='same', activation='relu'),
tf.keras.layers.Conv2D(kernel_size=1, filters=8, padding='same', activation='relu'),
tf.keras.layers.Flatten(),
# classifying into 5 categories
tf.keras.layers.Dense(5, activation='softmax')
])
model.compile(
optimizer='adam',
loss= 'categorical_crossentropy',
metrics=['accuracy'])
6. Tu convnet personalizado
Actividad práctica
Creemos y entrenemos una red neuronal convolucional desde cero. El uso de una TPU nos permitirá iterar muy rápido. Abre el siguiente notebook, ejecuta las celdas (Mayúsculas-Intro) y sigue las instrucciones cuando veas la etiqueta “TRABAJO OBLIGATORIO”.
Keras_Flowers_TPU (playground).ipynb
El objetivo es superar la precisión del 75% del modelo de aprendizaje transferible. Ese modelo tenía una ventaja, ya que había sido entrenado previamente con un conjunto de datos de millones de imágenes, mientras que aquí solo tenemos 3,670 imágenes. ¿Puedes al menos igualarlo?
Información adicional
¿Cuántas capas y qué tamaño tienen?
Seleccionar los tamaños de las capas es más un arte que una ciencia. Debes encontrar el equilibrio adecuado entre tener muy pocos y demasiados parámetros (pesos y sesgos). Con muy pocos pesos, la red neuronal no puede representar la complejidad de las formas de las flores. Si hay demasiadas, puede ser propenso a la “sobreajuste”, es decir, a especializarse en las imágenes de entrenamiento y no poder generalizar. Con muchos parámetros, el modelo también tardará en entrenarse. En Keras, la función model.summary()
muestra la estructura y el recuento de parámetros de tu modelo:
Layer (type) Output Shape Param #
=================================================================
conv2d (Conv2D) (None, 192, 192, 16) 448
_________________________________________________________________
conv2d_1 (Conv2D) (None, 192, 192, 30) 4350
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 96, 96, 30) 0
_________________________________________________________________
conv2d_2 (Conv2D) (None, 96, 96, 60) 16260
_________________________________________________________________
...
_________________________________________________________________
global_average_pooling2d (Gl (None, 130) 0
_________________________________________________________________
dense (Dense) (None, 90) 11790
_________________________________________________________________
dense_1 (Dense) (None, 5) 455
=================================================================
Total params: 300,033
Trainable params: 300,033
Non-trainable params: 0
_________________________________________________________________
Estas son algunas sugerencias:
- Tener varias capas es lo que hace que las redes neuronales "profundas" sean eficaces. Para este problema simple de reconocimiento de flores, entre 5 y 10 capas son adecuadas.
- Usa filtros pequeños. Por lo general, los filtros de 3 × 3 son buenos en todas partes.
- También se pueden usar filtros de 1×1, que son económicos. En realidad, no “filtran” nada, sino que calculan combinaciones lineales de canales. Alternalos con filtros reales. (Obtén más información sobre las "convoluciones de 1 × 1" en la siguiente sección).
- Para un problema de clasificación como este, reduce la muestra con frecuencia con capas de max-pooling (o convolución con un paso superior a 1). No importa dónde está la flor, solo que es una rosa o un diente de león, por lo que perder información sobre X e Y no es importante y filtrar áreas más pequeñas es más económico.
- La cantidad de filtros generalmente se asemeja a la cantidad de clases al final de la red (¿por qué? Consulta el truco de “reducción promedio global” a continuación). Si clasificas cientos de clases, aumenta el recuento de filtros de forma progresiva en capas consecutivas. Para el conjunto de datos de flores con 5 clases, filtrar con solo 5 filtros no sería suficiente. Puedes utilizar el mismo recuento de filtros en la mayoría de las capas, por ejemplo, 32, y disminuirlo hacia el final.
- Las capas densas finales son costosas. Pueden tener más pesos que todas las capas convolucionales combinadas. Por ejemplo, incluso con una salida muy razonable del último cubo de datos de 24 × 24 × 10 datos, una capa densa de 100 neuronas costaría 24 × 24 × 10 × 100=576,000 pesos. Intenta ser cuidadoso o prueba la reducción promedio global (consulta a continuación).
Agrupación promedio global
En lugar de usar una capa densa costosa al final de una red neuronal convolucional, puedes dividir el "cubo" de datos entrantes en tantas partes como tengas clases, promediar sus valores y pasarlos a través de una función de activación softmax. Esta forma de compilar el cabezal de clasificación cuesta 0 pesos. En Keras, la sintaxis es tf.keras.layers.GlobalAveragePooling2D().
.
Solución
Este es el notebook de la solución. Puedes usarla si no puedes avanzar.
Keras_Flowers_TPU (solution).ipynb
Temas abordados
- 🤔 Jugaste con las capas convolucionales
- 🤓 Experimentaste con la agrupación máxima, los pasos, la agrupación global promedio, etcétera.
- 😀 iteró en un modelo del mundo real rápidamente, en TPU
Tómate un momento para repasar esta lista de tareas mentalmente.
7. ¡Felicitaciones!
Creaste tu primera red neuronal convolucional moderna y la entrenaste con una exactitud del 80% o más, iterando su arquitectura en solo minutos gracias a las TPU. Continúa con el siguiente lab para aprender sobre las arquitecturas de convoluciones modernas:
- Canalizaciones de datos con velocidades de TPU: tf.data.Dataset y TFRecords
- Tu primer modelo de Keras, con aprendizaje transferible
- [ESTE LAB] Redes neuronales convolucionales, con Keras y TPU
- Convnets modernos, squeezenet, Xception, con Keras y TPU
TPU en la práctica
Las TPU y las GPUs están disponibles en Cloud AI Platform:
- En VMs de aprendizaje profundo
- En AI Platform Notebooks
- En los trabajos de AI Platform Training
Por último, nos encanta recibir comentarios. Infórmanos si ves algo fuera de lugar en este lab o si crees que se puede mejorar. Los comentarios se pueden enviar a través de los problemas de GitHub [ vínculo de comentarios].
|