Se usó la API de Cloud Translation para traducir esta página.
Switch to English

Cargar imágenes

Ver en TensorFlow.org Ejecutar en Google Colab Ver código fuente en GitHub Descargar cuaderno

Este tutorial muestra cómo cargar y preprocesar un conjunto de datos de imagen de dos maneras. Primero, utilizará capas y utilidades de preprocesamiento Keras de alto nivel. A continuación, escribirá su propia tubería de entrada desde cero utilizando tf.data .

Preparar

 import numpy as np
import os
import PIL
import PIL.Image
import tensorflow as tf
 
 print(tf.__version__)
 
2.3.0

Descargar el conjunto de datos de flores

Este tutorial utiliza un conjunto de datos de varios miles de fotos de flores. El conjunto de datos de flores contiene 5 subdirectorios, uno por clase:

 flowers_photos/
  daisy/
  dandelion/
  roses/
  sunflowers/
  tulips/
 
 import pathlib
dataset_url = "https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz"
data_dir = tf.keras.utils.get_file(origin=dataset_url, 
                                   fname='flower_photos', 
                                   untar=True)
data_dir = pathlib.Path(data_dir)
 

Después de descargar (218 MB), ahora debería tener una copia de las fotos de flores disponibles. Hay un total de 3670 imágenes:

 image_count = len(list(data_dir.glob('*/*.jpg')))
print(image_count)
 
3670

Cada directorio contiene imágenes de ese tipo de flor. Aquí hay algunas rosas:

 roses = list(data_dir.glob('roses/*'))
PIL.Image.open(str(roses[0]))
 

png

 roses = list(data_dir.glob('roses/*'))
PIL.Image.open(str(roses[1]))
 

png

Carga usando keras.preprocessing

Carguemos estas imágenes del disco usando image_dataset_from_directory .

Crear un conjunto de datos

Defina algunos parámetros para el cargador:

 batch_size = 32
img_height = 180
img_width = 180
 

Es una buena práctica utilizar una división de validación al desarrollar su modelo. Utilizaremos el 80% de las imágenes para capacitación y el 20% para validación.

 train_ds = tf.keras.preprocessing.image_dataset_from_directory(
  data_dir,
  validation_split=0.2,
  subset="training",
  seed=123,
  image_size=(img_height, img_width),
  batch_size=batch_size)
 
Found 3670 files belonging to 5 classes.
Using 2936 files for training.

 val_ds = tf.keras.preprocessing.image_dataset_from_directory(
  data_dir,
  validation_split=0.2,
  subset="validation",
  seed=123,
  image_size=(img_height, img_width),
  batch_size=batch_size)
 
Found 3670 files belonging to 5 classes.
Using 734 files for validation.

Puede encontrar los nombres de clase en el atributo class_names en estos conjuntos de datos.

 class_names = train_ds.class_names
print(class_names)
 
['daisy', 'dandelion', 'roses', 'sunflowers', 'tulips']

Visualiza los datos

Aquí están las primeras 9 imágenes del conjunto de datos de entrenamiento.

 import matplotlib.pyplot as plt

plt.figure(figsize=(10, 10))
for images, labels in train_ds.take(1):
  for i in range(9):
    ax = plt.subplot(3, 3, i + 1)
    plt.imshow(images[i].numpy().astype("uint8"))
    plt.title(class_names[labels[i]])
    plt.axis("off")
 

png

Puede entrenar un modelo utilizando estos conjuntos de datos pasándolos a model.fit (que se muestra más adelante en este tutorial). Si lo desea, también puede iterar manualmente sobre el conjunto de datos y recuperar lotes de imágenes:

 for image_batch, labels_batch in train_ds:
  print(image_batch.shape)
  print(labels_batch.shape)
  break
 
(32, 180, 180, 3)
(32,)

El image_batch es un tensor de la forma (32, 180, 180, 3) . Este es un lote de 32 imágenes de forma 180x180x3 (la última dimensión se refiere a los canales de color RGB). label_batch es un tensor de la forma (32,) , estas son etiquetas correspondientes a las 32 imágenes.

Estandarizar los datos

Los valores del canal RGB están en el rango [0, 255] . Esto no es ideal para una red neuronal; en general, debe tratar de hacer que sus valores de entrada sean pequeños. Aquí, estandarizaremos los valores para que estén en [0, 1] utilizando una capa de reescalado.

 from tensorflow.keras import layers

normalization_layer = tf.keras.layers.experimental.preprocessing.Rescaling(1./255)
 

Hay dos formas de usar esta capa. Puede aplicarlo al conjunto de datos llamando al mapa:

 normalized_ds = train_ds.map(lambda x, y: (normalization_layer(x), y))
image_batch, labels_batch = next(iter(normalized_ds))
first_image = image_batch[0]
# Notice the pixels values are now in `[0,1]`.
print(np.min(first_image), np.max(first_image)) 
 
0.0 0.96902645

O bien, puede incluir la capa dentro de la definición de su modelo para simplificar la implementación. Usaremos el segundo enfoque aquí.

Configurar el conjunto de datos para el rendimiento

Asegurémonos de utilizar la captación previa almacenada en búfer para que podamos generar datos del disco sin que la E / S se bloquee. Estos son dos métodos importantes que debe usar al cargar datos.

.cache() mantiene las imágenes en la memoria después de cargarlas en el disco durante la primera época. Esto asegurará que el conjunto de datos no se convierta en un cuello de botella mientras entrena a su modelo. Si su conjunto de datos es demasiado grande para caber en la memoria, también puede usar este método para crear una memoria caché en el disco con rendimiento.

.prefetch() superpone el preprocesamiento de datos y la ejecución del modelo durante el entrenamiento.

Los lectores interesados ​​pueden obtener más información sobre ambos métodos, así como sobre cómo almacenar en caché los datos en el disco en la guía de rendimiento de datos .

 AUTOTUNE = tf.data.experimental.AUTOTUNE

train_ds = train_ds.cache().prefetch(buffer_size=AUTOTUNE)
val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)
 

Entrenar a una modelo

Para completar, mostraremos cómo entrenar un modelo simple utilizando los conjuntos de datos que acabamos de preparar. Este modelo no se ha ajustado de ninguna manera: el objetivo es mostrarle la mecánica utilizando los conjuntos de datos que acaba de crear. Para obtener más información sobre la clasificación de imágenes, visite este tutorial .

 num_classes = 5

model = tf.keras.Sequential([
  layers.experimental.preprocessing.Rescaling(1./255),
  layers.Conv2D(32, 3, activation='relu'),
  layers.MaxPooling2D(),
  layers.Conv2D(32, 3, activation='relu'),
  layers.MaxPooling2D(),
  layers.Conv2D(32, 3, activation='relu'),
  layers.MaxPooling2D(),
  layers.Flatten(),
  layers.Dense(128, activation='relu'),
  layers.Dense(num_classes)
])
 
 model.compile(
  optimizer='adam',
  loss=tf.losses.SparseCategoricalCrossentropy(from_logits=True),
  metrics=['accuracy'])
 
 model.fit(
  train_ds,
  validation_data=val_ds,
  epochs=3
)
 
Epoch 1/3
92/92 [==============================] - 6s 66ms/step - loss: 1.3282 - accuracy: 0.4240 - val_loss: 1.1035 - val_accuracy: 0.5804
Epoch 2/3
92/92 [==============================] - 1s 11ms/step - loss: 1.0304 - accuracy: 0.5913 - val_loss: 0.9515 - val_accuracy: 0.6267
Epoch 3/3
92/92 [==============================] - 1s 11ms/step - loss: 0.8712 - accuracy: 0.6689 - val_loss: 0.9268 - val_accuracy: 0.6471

<tensorflow.python.keras.callbacks.History at 0x7f86d80ad128>

Puede notar que la precisión de la validación es baja en comparación con la precisión del entrenamiento, lo que indica que nuestro modelo está sobreajustado. Puede obtener más información sobre el sobreajuste y cómo reducirlo en este tutorial .

Usando tf.data para un control más fino

Las utilidades keras.preprocessing anteriores son una forma conveniente de crear un tf.data.Dataset de datos tf.data.Dataset desde un directorio de imágenes. Para un control de grano más fino, puede escribir su propia tubería de entrada usando tf.data . Esta sección muestra cómo hacer eso, comenzando con las rutas de archivo desde el zip que descargamos anteriormente.

 list_ds = tf.data.Dataset.list_files(str(data_dir/'*/*'), shuffle=False)
list_ds = list_ds.shuffle(image_count, reshuffle_each_iteration=False)
 
 for f in list_ds.take(5):
  print(f.numpy())
 
b'/home/kbuilder/.keras/datasets/flower_photos/roses/1445228333_59a07e0801.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/dandelion/14128835667_b6a916222c.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/roses/7551637034_55ae047756_n.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/dandelion/4574736702_b15ecf97d0_m.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/roses/6867597533_d65d1c39fb_n.jpg'

La estructura de árbol de los archivos se puede usar para compilar una lista de class_names .

 class_names = np.array(sorted([item.name for item in data_dir.glob('*') if item.name != "LICENSE.txt"]))
print(class_names)
 
['daisy' 'dandelion' 'roses' 'sunflowers' 'tulips']

Divida el conjunto de datos en tren y validación:

 val_size = int(image_count * 0.2)
train_ds = list_ds.skip(val_size)
val_ds = list_ds.take(val_size)
 

Puede ver la longitud de cada conjunto de datos de la siguiente manera:

 print(tf.data.experimental.cardinality(train_ds).numpy())
print(tf.data.experimental.cardinality(val_ds).numpy())
 
2936
734

Escriba una función corta que convierta una ruta de archivo en un par (img, label) :

 def get_label(file_path):
  # convert the path to a list of path components
  parts = tf.strings.split(file_path, os.path.sep)
  # The second to last is the class-directory
  one_hot = parts[-2] == class_names
  # Integer encode the label
  return tf.argmax(one_hot)
 
 def decode_img(img):
  # convert the compressed string to a 3D uint8 tensor
  img = tf.image.decode_jpeg(img, channels=3)
  # resize the image to the desired size
  return tf.image.resize(img, [img_height, img_width])
 
 def process_path(file_path):
  label = get_label(file_path)
  # load the raw data from the file as a string
  img = tf.io.read_file(file_path)
  img = decode_img(img)
  return img, label
 

Use Dataset.map para crear un conjunto de datos de image, label pares de image, label :

 # Set `num_parallel_calls` so multiple images are loaded/processed in parallel.
train_ds = train_ds.map(process_path, num_parallel_calls=AUTOTUNE)
val_ds = val_ds.map(process_path, num_parallel_calls=AUTOTUNE)
 
 for image, label in train_ds.take(1):
  print("Image shape: ", image.numpy().shape)
  print("Label: ", label.numpy())
 
Image shape:  (180, 180, 3)
Label:  2

Configurar el conjunto de datos para el rendimiento

Para entrenar un modelo con este conjunto de datos, querrá los datos:

  • Estar bien barajado.
  • Para ser agrupados.
  • Los lotes estarán disponibles lo antes posible.

Estas características se pueden agregar utilizando la API tf.data . Para obtener más detalles, consulte la guía de rendimiento de la tubería de entrada .

 def configure_for_performance(ds):
  ds = ds.cache()
  ds = ds.shuffle(buffer_size=1000)
  ds = ds.batch(batch_size)
  ds = ds.prefetch(buffer_size=AUTOTUNE)
  return ds

train_ds = configure_for_performance(train_ds)
val_ds = configure_for_performance(val_ds)
 

Visualiza los datos

Puede visualizar este conjunto de datos de manera similar al que creó anteriormente.

 image_batch, label_batch = next(iter(train_ds))

plt.figure(figsize=(10, 10))
for i in range(9):
  ax = plt.subplot(3, 3, i + 1)
  plt.imshow(image_batch[i].numpy().astype("uint8"))
  label = label_batch[i]
  plt.title(class_names[label])
  plt.axis("off")
 

png

Continuar entrenando al modelo

Ahora ha creado manualmente un tf.data.Dataset de datos tf.data.Dataset similar al creado por el keras.preprocessing anterior. Puedes seguir entrenando al modelo con él. Como antes, entrenaremos solo unas pocas épocas para mantener el tiempo de ejecución corto.

 model.fit(
  train_ds,
  validation_data=val_ds,
  epochs=3
)
 
Epoch 1/3
92/92 [==============================] - 2s 19ms/step - loss: 0.7267 - accuracy: 0.7272 - val_loss: 0.7963 - val_accuracy: 0.7098
Epoch 2/3
92/92 [==============================] - 1s 11ms/step - loss: 0.5384 - accuracy: 0.7987 - val_loss: 0.8067 - val_accuracy: 0.6894
Epoch 3/3
92/92 [==============================] - 1s 11ms/step - loss: 0.3382 - accuracy: 0.8770 - val_loss: 1.0317 - val_accuracy: 0.6662

<tensorflow.python.keras.callbacks.History at 0x7f87cd496320>

Próximos pasos

Este tutorial mostró dos formas de cargar imágenes desde el disco. Primero, aprendió a cargar y preprocesar un conjunto de datos de imagen usando las capas y utilidades de preprocesamiento de Keras. Luego, aprendió a escribir una tubería de entrada desde cero usando tf.data. Como siguiente paso, puede aprender cómo agregar aumento de datos visitando este tutorial . Para obtener más información sobre tf.data, puede visitar esta guía .