Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
tensorflow
GitHub Repository: tensorflow/docs-l10n
Path: blob/master/site/es-419/tutorials/load_data/images.ipynb
25118 views
Kernel: Python 3
#@title Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License.

Carga y procesamiento de imágenes

En este tutorial se muestra cómo cargar y preprocesar un conjunto de datos de imágenes de tres formas:

  • Primero, usarás las utilidades de preprocesamiento de alto nivel de Keras (como tf.keras.utils.image_dataset_from_directory) y capas (como tf.keras.layers.Rescaling) para leer un directorio de imágenes en un disco.

  • Luego, escribirá su propia canalización de entrada desde cero con tf.data.

  • Por último, descargará un conjunto de datos de un catálogo más grande que está disponible en TensorFlow Datasets.

Preparación

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

Descargar el conjunto de datos de flores

Este tutorial usa un conjunto de datos de miles de fotos de flores. El conjunto de datos de flores contiene cinco subdirectorios, uno por clase.

flowers_photos/ daisy/ dandelion/ roses/ sunflowers/ tulips/

Nota: todas las imágenes son licencia de CC-BY, los creadores están en el archivo LICENSE.txt.

import pathlib dataset_url = "https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz" archive = tf.keras.utils.get_file(origin=dataset_url, extract=True) data_dir = pathlib.Path(archive).with_suffix('')

Después de la descarga (218MB), debería tener una copia disponible de las fotos de flores. Son 3670 imágenes en total.

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

Cada directorio contiene imágenes de ese tipo de flor. Estas son algunas rosas:

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

Cargar datos con una utilidad de Keras

Carguemos estas imágenes fuera del disco con la utilidad tf.keras.utils.image_dataset_from_directory que es muy útil.

Crear un conjunto de datos

Defina algunos parámetros para el cargador:

batch_size = 32 img_height = 180 img_width = 180

Se considera buena práctica usar un separador de validación al desarrollar el modelo. El 80 % de las imágenes las usará para entrenamiento y el 20 % para validación.

train_ds = tf.keras.utils.image_dataset_from_directory( data_dir, validation_split=0.2, subset="training", seed=123, image_size=(img_height, img_width), batch_size=batch_size)
val_ds = tf.keras.utils.image_dataset_from_directory( data_dir, validation_split=0.2, subset="validation", seed=123, image_size=(img_height, img_width), batch_size=batch_size)

En estos conjuntos de datos, puede encontrar los nombres de clase en el atributo class_names.

class_names = train_ds.class_names print(class_names)

Visualizar los datos

Aquí están las primeras nueve imágenes del conjunto de datos para 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")

Puede entrenar un modelo con estos conjuntos de datos al pasarlos a model.fit (lo veremos más adelante). Si quiere, también puede iterar manualmente por los conjuntos 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

El lote de imagen image_batch es un tensor de la forma (32, 180, 180, 3). Esto es un lote de 32 imágenes de forma 180x180x3 (la última dimensión hace referencia a los canales de color RGB). El lote label_batch es un tensor de la forma (32,), estas son etiquetas que concuerdan con las 32 imágenes.

Se puede llamar a .numpy() en cualquiera de estos tensores para convertirlos en numpy.ndarray.

Estandarizar los datos

Los valores del canal RGB están dentro del rango [0, 255], lo cual no es ideal para una red neuronal. En general, debería buscar que los valores de su entrada sean bajos.

Aquí, estandarizará los valores para que estén dentro del rango [0, 1] mediante el uso de tf.keras.layers.Rescaling:

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

Esta capa se puede usar de dos formas. Se puede aplicar en el conjunto de datos llamando Dataset.map:

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 pixel values are now in `[0,1]`. print(np.min(first_image), np.max(first_image))

O, se puede incluir la capa en la definición de su modelo para simplificar la implementación. Aquí se usará el segundo enfoque.

Nota: Si lo que quiere es escalar valores de píxeles a [-1,1] escriba tf.keras.layers.Rescaling(1./127.5, offset=-1) en su lugar

Nota: Previamente, usaste el argumento image_size de tf.keras.utils.image_dataset_from_directory para ajustar el tamaño de las imágenes. Si también quiere incluir la lógica del ajuste en su modelo, puede usar la capa tf.keras.layers.Resizing.

Configurar el conjunto de datos para rendimiento

Vamos a asegurarnos de usar una preextracción almacenada en el búfer para que pueda producir datos desde el disco sin provocar un bloqueo en la E/S. Hay dos métodos importantes que deberías usar al cargar datos:

  • Dataset.cache conserva los datos en la memoria después de que se carga desde el disco durante la primera época. Así se garantiza que el conjunto de datos no se transforme en un cuello de botella mientras entrena su modelo. Si su conjunto de datos es muy grande para guardar en la memoria, también puede usar este método para crear un caché en disco de alto rendimiento.

  • Dataset.prefetch superpone el preprocesamiento de los datos y la ejecución del modelo durante el entrenamiento.

Quienes quieran aprender más sobre ambos modelos y también sobre cómo copiar datos en caché en disco, pueden leer la sección Preextracción de la guía Mejor rendimiento con la API tf.data.

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

Entrenar un modelo

Para completar el tutorial, deberá mostrar cómo entrenar un modelo simple con los conjuntos de datos que acaba de preparar.

El modelo Sequential consiste en tres bloques de convolución (tf.keras.layers.Conv2D) con una capa de agrupación máxima (tf.keras.layers.MaxPooling2D) en cada uno de ellos. Hay una capa totalmente conectada (tf.keras.layers.Dense) con 128 unidades más que se activa con una función de activación de ReLU ('relu'). El modelo no tiene ningún ajuste, el objetivo es mostrarle los mecanismos con los conjuntos de datos que usted acaba de crear. Para aprender más sobre la clasificación de imágenes, vea el tutorial de Clasificación de imágenes.

num_classes = 5 model = tf.keras.Sequential([ tf.keras.layers.Rescaling(1./255), tf.keras.layers.Conv2D(32, 3, activation='relu'), tf.keras.layers.MaxPooling2D(), tf.keras.layers.Conv2D(32, 3, activation='relu'), tf.keras.layers.MaxPooling2D(), tf.keras.layers.Conv2D(32, 3, activation='relu'), tf.keras.layers.MaxPooling2D(), tf.keras.layers.Flatten(), tf.keras.layers.Dense(128, activation='relu'), tf.keras.layers.Dense(num_classes) ])

Escoja el optimizador tf.keras.optimizers.Adam y la función de pérdida tf.keras.losses.SparseCategoricalCrossentropy. Para ver la precisión de entrenamiento y validación de cada época de entrenamiento, realice una pasada del argumento de métricas en Model.compile.

model.compile( optimizer='adam', loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True), metrics=['accuracy'])

Nota: Solo lo entrenará para algunas épocas para que el tutorial se ejecute rápido.

model.fit( train_ds, validation_data=val_ds, epochs=3 )

Nota: También puede escribir un bucle de entrenamiento personalizado en vez de usar Model.fit. Para más información, visite el tutorial de Escribir un bucle desde cero.

Quizás notará que la precisión de la validación es baja en comparación con la precisión del entrenamiento, esto quiere decir que su modelo está sobreajustado. Puede obtener más información sobre sobrejuste y sobre cómo reducirlo en este tutorial.

El uso de tf.data para control más preciso

La utilidad de preprocesamiento de Keras mencionada anteriormente, tf.keras.utils.image_dataset_from_directory, es una forma conveniente de crear un tf.data.Dataset desde una directorio de imágenes.

Para control más preciso y específico, puede escribir su propia canalización de entrada con tf.data. En esta sección se muestra cómo hacerlo, empezando con las rutas de archivo del archivo TGZ que descargó antes.

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())

La estructura de árbol de estos archivos puede usarse para compilar una lista class_names.

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

Divida los conjuntos de datos en conjuntos de entrenamiento 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 imprimir la longitud de cada conjunto de datos como se muestra a continuación:

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

Escriba una función breve que convierta una ruta de archivo en una pareja (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.io.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 parejas 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())

Configurar conjuntos de datos para rendimiento

Para entrenar un modelo con este conjunto de datos, necesita que los datos:

  • Estén en orden aleatorio.

  • Estén en lotes.

  • Que los lotes estén disponibles lo antes posible.

Se pueden agregar estas características con la API tf.data. Para más información, lea la guía Input Pipeline Performance.

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)

Visualizar los datos

Puede visualizar estos conjuntos de datos de forma similar a como lo hizo previamente:

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")

Continuar entrenando el modelo

Ahora ha construido un tf.data.Dataset parecido al de tf.keras.utils.image_dataset_from_directory anteriormente. Puede continuar entrenándolo con ese modelo. Igual que antes, solo lo entrenará para algunas épocas para que el tiempo de ejecución sea corto.

model.fit( train_ds, validation_data=val_ds, epochs=3 )

El uso de TensorFlow Datasets

Por ahora, este tutorial solo se ha enfocado en cargar datos fuera del disco. También puede encontrar conjuntos de datos para usar si explora el gran catálogo de conjuntos de datos de fácil descarga en TensorFlow Datasets.

Previamente, ya cargó el conjunto de datos de flores fuera del disco, ahora lo vamos a importar con TensorFlow Datasets.

Descargue el conjunto de datos de flores con TensorFlow Datasets:

(train_ds, val_ds, test_ds), metadata = tfds.load( 'tf_flowers', split=['train[:80%]', 'train[80%:90%]', 'train[90%:]'], with_info=True, as_supervised=True, )

El conjunto de datos de flores tiene cinco clases:

num_classes = metadata.features['label'].num_classes print(num_classes)

Recupere una imagen del conjunto de datos:

get_label_name = metadata.features['label'].int2str image, label = next(iter(train_ds)) _ = plt.imshow(image) _ = plt.title(get_label_name(label))

Igual que antes, recuerde que los conjuntos de entrenamiento, validación y prueba deben estar en lotes, en orden aleatorio y configurados para buen rendimiento:

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

Puede encontrar un ejemplo completo que usa el conjunto de datos de flores y TensorFlow Datasets en el tutorial de Aumento de datos.

Próximos pasos

En este tutorial se mostraron dos formas de cargar imágenes fuera del disco. Primero, aprendió a cargar y preprocesar un conjunto de imágenes con las capas y utilidades de preprocesamiento de Keras. Luego, aprendió cómo escribir una canalización de entrada desde cero con tf.data{/code}. Por último, aprendió cómo descargar un conjunto de datos desde TensorFlow Datasets.

Para sus próximos pasos: