Aumento de datos de imágenes para aprendizaje profundo

Comprenda qué es el aumento de datos de imágenes y cómo usarlo con Keras para sus proyectos de aprendizaje profundo

Foto por chris lawton on Unsplash

Si alguna vez ha intentado realizar el reconocimiento de imágenes mediante el aprendizaje profundo, sabe la importancia de un buen conjunto de datos para el entrenamiento. Sin embargo, encontrar imágenes suficientes para el entrenamiento no siempre es fácil y la precisión de su modelo depende directamente de la calidad de los datos de entrenamiento.

Afortunadamente, existen técnicas que puede utilizar para complementar el conjunto de datos de imágenes que utilizan para el entrenamiento. Una de las técnicas se llama aumento de datos de imagen. En este artículo, analizaré qué es el aumento de datos de imágenes, cómo funciona, por qué es útil en el aprendizaje profundo y, finalmente, cómo realizar el aumento de datos de imágenes utilizando la biblioteca Keras.

Aumento de datos de imagen es una técnica que crea nuevas imágenes a partir de las existentes. Para hacer eso, realiza algunos pequeños cambios en ellos, como ajustar el brillo de la imagen, rotar la imagen o cambiar el sujeto en la imagen horizontal o verticalmente.

Las técnicas de aumento de imágenes le permiten aumentar artificialmente el tamaño de su conjunto de entrenamiento, proporcionando así muchos más datos a su modelo para el entrenamiento. Esto le permite mejorar la precisión de su modelo al mejorar la capacidad de su modelo para reconocer nuevas variantes de sus datos de entrenamiento.

Tipos de aumento de datos de imagen

El aumento de imágenes se presenta de muchas formas, estas son algunas de las más comunes: desplazamiento vertical, desplazamiento horizontal, giro vertical, giro horizontal, rotación, ajuste de brillo y acercamiento/alejamiento.

Primero demostraré las diversas técnicas de aumento de imágenes usando Python y Keras. Si desea probar, asegúrese de tener instalados el siguiente software y paquetes:

Una vez que Anaconda y TensorFlow estén instalados, cree un nuevo Jupyter Notebook.

Desplazamiento vertical

La primera técnica de aumento de imagen que quiero mostrar es la desplazamiento vertical. desplazamiento vertical desplaza aleatoriamente la imagen verticalmente hacia arriba o hacia abajo. Para este ejemplo, voy a usar una imagen llamada 747.jpg, ubicado en la misma carpeta que mi Jupyter Notebook.

Fuente de imagen: https://commons.wikimedia.org/wiki/File:Qantas_Boeing_747-438ER_VH-OEI_at_LAX.jpg. Este archivo tiene licencia bajo el Creative Commons Reconocimiento-Compartir Igual 2.0 Genérico licencia.

El siguiente fragmento de código utiliza el ImageDataGenerator class en Keras para desplazar verticalmente la imagen.

La ImageDataGenerator La clase de Keras genera lotes de datos de imagen con aumento de datos en tiempo real.

#---importar los módulos---
importar numpy como np
importar matplotlib.pyplot como plt
desde tensorflow.keras.preprocessing.image importar load_img
desde tensorflow.keras.preprocessing.image importar img_to_array
de tensorflow.keras.preprocessing.image importar ImageDataGenerator
#---carga la imagen---
nombre_archivo_imagen = '747.jpg'
img = load_img(nombre_archivo_imagen)
#---convertir la imagen a matriz 3D---
imagen_datos = img_to_array(img)
#---convertir en una matriz 4-D de 1 elemento de matriz 3D que representa
# la imagen---
imágenes_datos = np.expand_dims(imagen_datos, eje=0)
#---crear generador de aumento de datos de imagen---
generación de datos = ImageDataGenerator(width_shift_range=0.2)
#---preparar el iterador; flow() toma una matriz 4D y devuelve
# un iterador que contiene un lote de imágenes---
tren_generador = datagen.flow(images_data, lote_tamaño=1)
filas = 5
columnas = 4
#---trazar 5 filas y 4 columnas---
higo, ejes = plt.subparcelas (filas, columnas)
para r en rango (filas):
para c en el rango (columnas):
#---Obtener la siguiente imagen en el lote (una imagen desde el lote
# tamaño es 1)---
image_batch = tren_generador.next()

#---convertir a enteros sin signo para verlos---
imagen = image_batch[0].astype('uint8')

#---muestra la imagen---
ejes[r,c].imshow(imagen)
#---establecer el tamaño de la figura---
fig.set_size_inches(15,10)

El fragmento de código anterior produce el siguiente resultado:

Como puede ver en el resultado anterior, cada vez que llama al next() método del train_generator objeto, obtienes una imagen ligeramente alterada. En el fragmento de código anterior, se devuelve una nueva imagen que se desplaza un 20% en función de la altura de la imagen original cada vez que llama al next() método:

generador de datos = ImageDataGenerator(ancho_cambio_rango=0.2)

Curiosamente, para esta versión del ImageDataGenerator (tensorflow.keras.preprocessing.image) clase, especificando el width_shift_range El parámetro cambia la imagen verticalmente, en lugar de horizontalmente (que es el comportamiento de la antiguaImageDataGeneratordel desplegable keras.preprocessing.image módulo). Del mismo modo, si desea que la imagen se desplace horizontalmente, debe utilizar el height_shift_range parámetro (ver la siguiente sección).

Tenga en cuenta que next() El método devolverá una imagen aumentada tantas veces como desee. En el fragmento de código anterior, lo llamamos 20 veces (5 filas por 4 columnas).

Desplazamiento horizontal

Ahora puede intentar cambiar la imagen horizontalmente usando el height_shift_range parámetro:

generador de datos = ImageDataGenerator(rango_cambio_altura=0.2)
tren_generador = datagen.flow(images_data, lote_tamaño=1)
filas = 5
columnas = 4
higo, ejes = plt.subparcelas (filas, columnas)
para r en rango (filas):
para c en el rango (columnas):
image_batch = tren_generador.next()
imagen = image_batch[0].astype('uint8')
ejes[r,c].imshow(imagen)
fig.set_size_inches(15,10)

El fragmento de código anterior produce el siguiente resultado:

Volteo horizontal

A veces tiene sentido voltear la imagen horizontalmente. En el caso de un avión, la parte delantera del avión puede mirar hacia la izquierda o hacia la derecha:

generador de datos = ImageDataGenerator(horizontal_flip=Verdadero)
tren_generador = datagen.flow(images_data, lote_tamaño=1)
filas = 2
columnas = 2
higo, ejes = plt.subparcelas (filas, columnas)
para r en rango (filas):
para c en el rango (columnas):
image_batch = tren_generador.next()
imagen = image_batch[0].astype('uint8')
ejes[r,c].imshow(imagen)
fig.set_size_inches(15,10)

Para el fragmento de código anterior, generar cuatro imágenes es suficiente, ya que la parte delantera del avión puede estar orientada hacia la izquierda o hacia la derecha:

Recuerde que el volteo es aleatorio (a veces obtiene las cuatro imágenes originales y, a veces, obtiene imágenes que se voltean horizontalmente). Es probable que las cuatro imágenes de arriba sean todas iguales. Si eso sucede, simplemente ejecute ese bloque de código nuevamente.

Volteo vertical

Al igual que el volteo horizontal, también puede realizar un volteo vertical:

generador de datos = ImageDataGenerator(vertical_flip=Verdadero)
tren_generador = datagen.flow(images_data, lote_tamaño=1)
filas = 2
columnas = 2
higo, ejes = plt.subparcelas (filas, columnas)
para r en rango (filas):
para c en el rango (columnas):
image_batch = tren_generador.next()
imagen = image_batch[0].astype('uint8')
ejes[r,c].imshow(imagen)
fig.set_size_inches(15,10)

En el caso de los aviones, ¡podría no tener mucho sentido voltear nuestro avión boca abajo! Si está tratando de realizar el reconocimiento de imágenes, es probable que sus imágenes de planos estén en posición vertical, por lo que entrenar su modelo para reconocer planos invertidos puede no ser demasiado común. Para otros casos, el volteo vertical tiene mucho sentido.

Rotación

La rotación, como su nombre lo indica, gira la imagen. Esto sería muy útil para nuestra imagen de avión. Los siguientes fragmentos de código giran aleatoriamente la imagen hasta 50 grados:

generador de datos = ImageDataGenerator(rango_de_rotación=50)
tren_generador = datagen.flow(images_data)
filas = 5
columnas = 4
higo, ejes = plt.subparcelas (filas, columnas)
para r en rango (filas):
para c en el rango (columnas):
image_batch = tren_generador.next()
imagen = image_batch[0].astype('uint8')
ejes[r,c].imshow(imagen)
fig.set_size_inches(15,10)

Con la rotación, la salida muestra los aviones en las distintas posiciones, simulando las posiciones de despegue y aterrizaje:

Brillo

Otra técnica de aumento es ajustar el brillo de la imagen. El siguiente fragmento de código establece un rango de valores de cambio de brillo:

generador de datos = ImageDataGenerator(rango_brillo=[0.15,2.0])
tren_generador = datagen.flow(images_data, lote_tamaño=1)
filas = 5
columnas = 4
higo, ejes = plt.subparcelas (filas, columnas)
para r en rango (filas):
para c en el rango (columnas):
image_batch = tren_generador.next()
imagen = image_batch[0].astype('uint8')
ejes[r,c].imshow(imagen)
fig.set_size_inches(15,10)

La salida contiene una serie de imágenes de brillo variable:

Zoom

También puede acercar o alejar las imágenes:

generador de datos = ImageDataGenerator(zoom_rango=[5,0.5])
tren_generador = datagen.flow(images_data, lote_tamaño=1)
filas = 5
columnas = 4
higo, ejes = plt.subparcelas (filas, columnas)
para r en rango (filas):
para c en el rango (columnas):
image_batch = tren_generador.next()
imagen = image_batch[0].astype('uint8')
ejes[r,c].imshow(imagen)
fig.set_size_inches(15,10)

La salida muestra la imagen en las distintas relaciones de zoom:

Tenga en cuenta que hacer zoom en las imágenes alterará las relaciones de aspecto de las imágenes.

Combinando todos los aumentos

Por supuesto, todas las diversas técnicas de aumento que he discutido hasta ahora se pueden combinar:

generador de datos = ImageDataGenerator(ancho_cambio_rango=0.2,
altura_cambio_rango=0.2,
horizontal_flip=Verdadero,
rango_de_rotación=50,
rango_brillo=[0.15,2.0],
zoom_rango=[5,0.5]
)
tren_generador = datagen.flow(images_data, lote_tamaño=1)filas = 8
columnas = 8
higo, ejes = plt.subparcelas (filas, columnas)
para r en rango (filas):
para c en el rango (columnas):
image_batch = tren_generador.next()
imagen = image_batch[0].astype('uint8')
ejes[r,c].imshow(imagen)
fig.set_size_inches(15,10)

Tenga en cuenta que he omitido el giro vertical ya que no tiene sentido para nuestro ejemplo.

La salida ahora muestra la imagen con los diversos aumentos aplicados:

Las secciones anteriores mostraron los conceptos básicos del aumento de datos de imágenes y cómo se puede aplicar a una sola imagen. En el aprendizaje profundo, a menudo tratamos con un conjunto de imágenes. Así que ahora veamos cómo se puede aplicar el aumento de imágenes a un conjunto de imágenes. Para las ilustraciones, supondré que en la carpeta que contiene su Jupyter Notebook, tiene un Frutas carpeta y las siguientes subcarpetas:

Frutas
|__plátano
|__plátano1.jpg
|__plátano2.jpg
|__plátano3.jpg
|__...
|__durián
|__durian1.jpg
|__durian2.jpg
|__durian3.jpg
|__...
|__naranja
|__naranja1.jpg
|__naranja2.jpg
|__naranja3.jpg
|__...
|__fresa
|__fresa1.jpg
|__fresa2.jpg
|__fresa3.jpg
|__...

Cada subcarpeta contiene un conjunto de imágenes. por ejemplo, el plátano carpeta contiene una serie de imágenes llamadas plátano1.jpg, plátano2.jpg, y así. El nombre de las subcarpetas servirá como etiquetas para las distintas imágenes. Esto significa que todos los archivos bajo el plátano carpeta contiene imágenes de plátano, y así sucesivamente.

Para cargar una serie de imágenes desde el disco, ahora llame al flow_from_directory() método de la ImageDataGenerator instancia en lugar de la flow() método (para cargar imágenes desde la memoria):

train_datagen = Generador de datos de imagen (
horizontal_flip=Verdadero,
vertical_flip=Verdadero,
rango_de_rotación=50,
)
tamaño_lote = 8tren_generador = train_datagen.flow_from_directory(
'./Frutas',
tamaño_objetivo=(224,224),
color_mode='rgb',
tamaño_lote=tamaño_lote,
class_mode='categórico',
barajar = Verdadero)

Observe que ahora configuro el batch_size a 8. Verá el uso del tamaño del lote en breve.

Usando el iterador devuelto, puedo encontrar las etiquetas de las diversas frutas (plátano, durian, naranja y fresa):

diccionario_clase = generador_tren.índices_clase#---crear un diccionario de etiquetas---
class_dictionary = { valor: clave para clave, valor en
diccionario_clase.items()}
#---convertir el diccionario a una lista---
class_list = [valor para _, valor en class_dictionary.items()]
imprimir (clase_lista)

Verá el siguiente resultado:

Encontradas 54 imágenes pertenecientes a 4 clases.
['plátano', 'durian', 'naranja', 'fresa']

En total, hay un total de 54 imágenes en 4 carpetas. También el class_list variable contiene la lista de frutas.

Ahora voy a imprimir el conjunto de imágenes aumentadas que son creadas por el ImageDataGenerator clase. Estableceré arbitrariamente las filas en 10, y para cada fila, quiero imprimir el lote de imágenes devueltas (que son 8 en este ejemplo):

filas = 10higo, ejes = plt.subparcelas (filas, lote_tamaño)para r en rango (filas):    
#---obtenga el lote de imágenes aumentadas---
image_batch = tren_generador.next()
#---Obtener el número de imágenes devueltas---
imágenes_cuenta = imagen_lote[0].forma[0]

para c en el rango (images_count):
#---convertir a enteros sin signo para verlos---
imagen = image_batch[0][c].astype('uint8')

#---mostrar la imagen---
ejes[r,c].imshow(imagen)

#---muestra la etiqueta de la imagen---
ejes[r,c].title.set_text(
lista_clase[np.argmax(image_batch[1][c])])
#---oculta las marcas x e y---
ejes[r,c].set_xticks([])
ejes[r,c].set_yticks([])
fig.set_size_inches(15,18)

Puesto que el batch_size ahora está configurado en 8 (y ya no es 1), el train_generator.next() método le devolverá un lote de ocho imágenes aumentadas cada vez que lo llamas. El número de imágenes devueltas se basa en batch_size que configuró anteriormente en el flow_from_directory() método:

tren_generador = tren_datagen.flow_from_directory(
'./Frutas',
tamaño_objetivo=(224,224),
color_mode='rgb',
tamaño_lote=tamaño_lote, # lote_tamaño = 8
class_mode='categórico',
barajar = Verdadero)

El valor de la image_batch variable (devuelta por el next() método) es una tupla de dos elementos:

  • El primer elemento (image_batch[0]) es una matriz de tamaño del lote imágenes (matriz 4D)
  • El segundo elemento (image_batch[1]) contiene las etiquetas para las imágenes

El fragmento de código anterior produce el siguiente resultado:

Observe que en la séptima fila hay dos gráficos vacíos sin imágenes. Recuerde que hay un total de 54 imágenes en el conjunto de imágenes y dado que cada lote devuelve 8 imágenes (por fila), las primeras siete filas mostrarán un total de 54 imágenes (8×6 + 6). La siguiente figura lo aclara:

Tenga en cuenta que puede configurar rows a cualquier número y el ImageDataGenerator La clase seguirá generando nuevas imágenes aumentadas para ti.

Construyendo un modelo utilizando el aprendizaje por transferencia

Ahora sabe cómo utilizar el ImageDataGenerator para cargar conjuntos de imágenes desde el disco para aumentarlas. Pero, ¿cómo lo usas para entrenar? El siguiente fragmento de código muestra cómo construir un modelo de aprendizaje profundo usando transferencia de aprendizaje.

El aprendizaje por transferencia es un método de aprendizaje automático en el que un modelo desarrollado para una tarea se reutiliza como punto de partida para un modelo en una segunda tarea. Transferir el aprendizaje reduce la cantidad de tiempo que necesita dedicar a la capacitación.

de tensorflow.keras.models modelo de importación
de tensorflow.keras.applications importar VGG16
de tensorflow.keras.layers import Dense, GlobalAveragePooling2D
#---número de frutas---
NO_CLASSES = max(train_generator.class_indices.values()) + 1
#---cargue el modelo VGG16 como modelo base para el entrenamiento---
base_model = VGG16(include_top=Falso, input_shape=(224, 224, 3))
#---añadir nuestras propias capas---
x = modelo_base.salida
x = GlobalAveragePooling2D()(x)
x = Dense(1024,activation='relu')(x) # agregar capas densas para
# que el modelo puede
# aprender más complejo
# funciones y
# clasificar para mejor
# resultados.
x = Dense (1024, activación = 'relu') (x) # capa densa 2
x = Densa (512, activación = 'relu') (x) # capa densa 3
preds = Denso(NO_CLASSES,
activación='softmax')(x) # capa final con
# activación softmax
#---crear un nuevo modelo con el original del modelo base
# entrada y salida del nuevo modelo---
modelo = Modelo (entradas = base_model.input, salidas = preds)
#---no entrenar las primeras 19 capas - 0..18---
para capa en model.layers[:19]:
capa.entrenable=Falso
#---entrena el resto de las capas - 19 en adelante---
para capa en model.layers[19:]:
capa.entrenable=Verdadero

#---compilar el modelo---
modelo.compilar(optimizador='Adam',
loss='categorical_crossentropy',
métricas = ['precisión'])

Explicar cómo funciona el aprendizaje por transferencia está más allá del alcance de este artículo. Lo dejo para otro artículo.

Uso de las imágenes generadas para el entrenamiento

Para usar las imágenes aumentadas para el entrenamiento, pase el train_generator en el fit() método del modelo:

#---entrenar al modelo---
step_size_train = tren_generador.n // tren_generador.batch_size
modelo.encajar(tren_generador,
steps_per_epoch=paso_tamaño_tren,
épocas=15)

La steps_per_epoch El parámetro básicamente significa cuántos pasos hay en una época; depende de la cantidad de imágenes que tenga y del tamaño del lote definido anteriormente. Si configura esto en un número alto, entonces está haciendo un entrenamiento repetitivo. Debe configurarlo en función de esta fórmula:

número de imágenes/tamaño del lote

En nuestro ejemplo, tenemos 54 imágenes en total. Y así en cada época, el ImageDataGenerator La clase transformará las 54 imágenes para el entrenamiento. En cada época el modelo obtendrá diferentes variaciones de las imágenes. Si tiene 15 épocas, se generarán un total de 15 × 54 variaciones de las imágenes y se introducirán en el modelo de entrenamiento.

La ImageDataGenerator La clase permite que su modelo reciba nuevas variaciones de las imágenes en cada época. Pero recuerde que solo devuelve las imágenes transformadas y no las agrega al conjunto de imágenes que tiene.

Espero que este artículo le haya dado una buena idea de qué se trata el aumento de datos de imágenes y por qué los necesita en el entrenamiento de sus modelos de aprendizaje profundo. En particular, lo he demostrado usando el módulo Keras en la biblioteca TensorFlow.

Aumento de datos de imagen para aprendizaje profundo republicado desde la fuente https://towardsdatascience.com/image-data-augmentation-for-deep-learning-77a87fabd2bf?source=rss—-7f60cf5620c9—4 a través de https://towardsdatascience.com/feed

<!–

->

Sello de tiempo:

Mas de Consultores Blockchain