Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
tensorflow
GitHub Repository: tensorflow/docs-l10n
Path: blob/master/site/es-419/tutorials/images/classification.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.

Clasificación de imágenes

Este tutorial muestra cómo clasificar imágenes de flores utilizando un modelo tf.keras.Sequential y cargar datos utilizando tf.keras.utils.image_dataset_from_directory. Demuestra los siguientes conceptos:

  • Carga eficaz de un conjunto de datos del disco.

  • La identificación del sobreajuste y la aplicación de técnicas para mitigarlo, incluidos el aumento de datos y abandonarlos.

Este tutorial sigue un flujo de trabajo básico de aprendizaje automático:

  1. Examinar y comprender los datos

  2. Construirá una canalización de entrada

  3. Construir el modelo

  4. Entrene el modelo

  5. Pruebe el modelo

  6. Mejore el modelo y repita el proceso

Además, el bloc de notas demuestra cómo convertir un modelo guardado en un modelo de TensorFlow Lite para el aprendizaje automático en dispositivos móviles, embebidos y de IoT.

Preparación

Importe TensorFlow y otras bibliotecas necesarias:

import matplotlib.pyplot as plt import numpy as np import PIL import tensorflow as tf from tensorflow import keras from tensorflow.keras import layers from tensorflow.keras.models import Sequential

Descargar y explorar el conjunto de datos

Este tutorial utiliza un conjunto de datos de unas 3,700 fotos de flores. El conjunto de datos contiene cinco subdirectorios, uno por clase:

flower_photo/ 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('flower_photos.tar', origin=dataset_url, extract=True) data_dir = pathlib.Path(data_dir).with_suffix('')

Después de la descarga, ya debería disponer de una copia del conjunto de datos. Hay 3,670 imágenes en total:

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

Estas son algunas rosas:

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

Y algunos tulipanes:

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

Cargar datos con una utilidad de Keras

A continuación, cargue estas imágenes desde el disco utilizando la útil utilidad tf.keras.utils.image_dataset_from_directory. Esto nos permitirá pasar de un directorio de imágenes en disco a un tf.data.Dataset con sólo un par de líneas de código. Si lo desea, también puede escribir su propio código para cargar datos desde cero visitando el tutorial Cargar y preprocesar imágenes.

Crear un conjunto de datos

Defina algunos parámetros para el cargador:

batch_size = 32 img_height = 180 img_width = 180

Es una práctica recomendada utilizar una división de validación cuando desarrolle su modelo. Utilice el 80% de las imágenes para el entrenamiento y el 20% para la 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)

Puede encontrar los nombres de las clases en el atributo class_names de estos conjuntos de datos. Éstos corresponden a los nombres de los directorios por orden alfabético.

class_names = train_ds.class_names print(class_names)

Visualizar los datos

Estas son las nueve primeras 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")

Pasará estos conjuntos de datos al método Keras Model.fit para el entrenamiento más adelante en este tutorial. Si lo desea, también puede iterar manualmente 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

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.

Puede llamar a .numpy() sobre los tensores image_batch y labels_batch para convertirlos en un numpy.ndarray.

Configuración del conjunto de datos para rendimiento

Asegúrese de utilizar la preextracción de datos en búfer, para poder ceder los datos desde el disco sin que la E/S se bloquee. Estos son dos métodos importantes que debe utilizar 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().shuffle(1000).prefetch(buffer_size=AUTOTUNE) val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)

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 = 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 bien, puede incluir la capa dentro de la definición de su modelo, lo que puede simplificar la implementación. Utilice aquí el segundo enfoque.

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.

Un modelo básico de Keras

Crear el modelo

El modelo Sequential de Keras consta de tres bloques de convolución (tf.keras.layers.Conv2D) con una capa de agrupamiento máximo (tf.keras.layers.MaxPooling2D) en cada uno de ellos. Hay una capa totalmente conectada (tf.keras.layers.Dense) con 128 unidades en la parte superior que se activa mediante una función de activación ReLU ('relu'). Este modelo no se ajustó para obtener una gran precisión; el objetivo de este tutorial es mostrar un enfoque estándar.

num_classes = len(class_names) model = Sequential([ layers.Rescaling(1./255, input_shape=(img_height, img_width, 3)), layers.Conv2D(16, 3, padding='same', activation='relu'), layers.MaxPooling2D(), layers.Conv2D(32, 3, padding='same', activation='relu'), layers.MaxPooling2D(), layers.Conv2D(64, 3, padding='same', activation='relu'), layers.MaxPooling2D(), layers.Flatten(), layers.Dense(128, activation='relu'), layers.Dense(num_classes) ])

Compilar el modelo

Para este tutorial, elija 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, pase el argumento metrics a Model.compile.

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

Resumen del modelo

Visualice todas las capas de la red utilizando el método Keras Model.summary:

model.summary()

Entrene el modelo

Entrene el modelo durante 10 épocas con el método Keras Model.fit:

epochs=10 history = model.fit( train_ds, validation_data=val_ds, epochs=epochs )

Visualice los resultados del entrenamiento

Cree gráficos de la pérdida y la precisión en los conjuntos de entrenamiento y validación:

acc = history.history['accuracy'] val_acc = history.history['val_accuracy'] loss = history.history['loss'] val_loss = history.history['val_loss'] epochs_range = range(epochs) plt.figure(figsize=(8, 8)) plt.subplot(1, 2, 1) plt.plot(epochs_range, acc, label='Training Accuracy') plt.plot(epochs_range, val_acc, label='Validation Accuracy') plt.legend(loc='lower right') plt.title('Training and Validation Accuracy') plt.subplot(1, 2, 2) plt.plot(epochs_range, loss, label='Training Loss') plt.plot(epochs_range, val_loss, label='Validation Loss') plt.legend(loc='upper right') plt.title('Training and Validation Loss') plt.show()

Las representaciones gráficas muestran que la precisión de entrenamiento y la de validación están alejadas por grandes márgenes, y que el modelo sólo ha logrado una precisión en torno al 60% en el conjunto de validación.

Las siguientes secciones del tutorial muestran cómo inspeccionar lo que salió mal e intentar aumentar el rendimiento general del modelo.

Sobreajuste

En las representaciones gráficas anteriores, la precisión de entrenamiento aumenta linealmente con el tiempo, mientras que la precisión de validación se estanca en torno al 60% en el proceso de entrenamiento. Además, la diferencia de precisión entre la precisión de entrenamiento y la de validación es notable, un signo de sobreajuste.

Cuando hay un número reducido de ejemplos de entrenamiento, el modelo aprende a veces de los ruidos o de los detalles no deseados de los ejemplos de entrenamiento, hasta el punto de repercutir negativamente en el rendimiento del modelo con los nuevos ejemplos. Este fenómeno se conoce como sobreajuste. Significa que el modelo tendrá dificultades para generalizar en un nuevo conjunto de datos.

Hay múltiples formas de combatir el sobreajuste en el proceso de entrenamiento. En este tutorial, utilizará el aumento de datos y agregará abandonar a su modelo.

Aumento de datos

El sobreajuste suele producirse cuando hay un número reducido de ejemplos en el entrenamiento. El aumento de datos adopta el enfoque consistente en generar datos de entrenamiento adicionales a partir de los ejemplos existentes, al aumentarlos mediante transformaciones aleatorias que producen imágenes de aspecto realista. Esto ayuda a exponer el modelo a más aspectos de los datos y a generalizar mejor.

Implementará el aumento de datos utilizando las siguientes capas de preprocesamiento de Keras: tf.keras.layers.RandomFlip, tf.keras.layers.RandomRotation, y tf.keras.layers.RandomZoom. Estas pueden incluirse dentro de su modelo como otras capas, y ejecutarse en la GPU.

data_augmentation = keras.Sequential( [ layers.RandomFlip("horizontal", input_shape=(img_height, img_width, 3)), layers.RandomRotation(0.1), layers.RandomZoom(0.1), ] )

Visualice algunos ejemplos aumentados aplicando varias veces el aumento de datos a la misma imagen:

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

En el siguiente paso agregará el aumento de datos a su modelo antes del entrenamiento.

Abandonar

Otra técnica para reducir el sobreajuste es introducir abandonar{:.external} regularización a la red.

Cuando se aplica abandonar a una capa, se elimina aleatoriamente (poniendo la activación a cero) un número de unidades de salida de la capa durante el proceso de entrenamiento. Abandonar toma un número fraccionario como valor de entrada, en la forma como 0.1, 0.2, 0.4, etc. Esto significa descartar aleatoriamente el 10%, el 20% o el 40% de las unidades de salida de la capa aplicada.

Cree una nueva red neuronal con tf.keras.layers.Dropout antes de entrenarla utilizando las imágenes aumentadas:

model = Sequential([ data_augmentation, layers.Rescaling(1./255), layers.Conv2D(16, 3, padding='same', activation='relu'), layers.MaxPooling2D(), layers.Conv2D(32, 3, padding='same', activation='relu'), layers.MaxPooling2D(), layers.Conv2D(64, 3, padding='same', activation='relu'), layers.MaxPooling2D(), layers.Dropout(0.2), layers.Flatten(), layers.Dense(128, activation='relu'), layers.Dense(num_classes, name="outputs") ])

Compile y entrene el modelo

model.compile(optimizer='adam', loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True), metrics=['accuracy'])
model.summary()
epochs = 15 history = model.fit( train_ds, validation_data=val_ds, epochs=epochs )

Visualice los resultados del entrenamiento

Después de aplicar el aumento de datos y tf.keras.layers.Dropout, hay menos sobreajuste que antes, y la precisión de entrenamiento y validación están más alineadas:

acc = history.history['accuracy'] val_acc = history.history['val_accuracy'] loss = history.history['loss'] val_loss = history.history['val_loss'] epochs_range = range(epochs) plt.figure(figsize=(8, 8)) plt.subplot(1, 2, 1) plt.plot(epochs_range, acc, label='Training Accuracy') plt.plot(epochs_range, val_acc, label='Validation Accuracy') plt.legend(loc='lower right') plt.title('Training and Validation Accuracy') plt.subplot(1, 2, 2) plt.plot(epochs_range, loss, label='Training Loss') plt.plot(epochs_range, val_loss, label='Validation Loss') plt.legend(loc='upper right') plt.title('Training and Validation Loss') plt.show()

Predecir con nuevos datos

Utilice su modelo para clasificar una imagen que no estaba incluida en los conjuntos de entrenamiento o validación.

Nota: El aumento de datos y abandonar capas estarán inactivos en el momento de hacer inferencias.

sunflower_url = "https://storage.googleapis.com/download.tensorflow.org/example_images/592px-Red_sunflower.jpg" sunflower_path = tf.keras.utils.get_file('Red_sunflower', origin=sunflower_url) img = tf.keras.utils.load_img( sunflower_path, target_size=(img_height, img_width) ) img_array = tf.keras.utils.img_to_array(img) img_array = tf.expand_dims(img_array, 0) # Create a batch predictions = model.predict(img_array) score = tf.nn.softmax(predictions[0]) print( "This image most likely belongs to {} with a {:.2f} percent confidence." .format(class_names[np.argmax(score)], 100 * np.max(score)) )

Utilice TensorFlow Lite

TensorFlow Lite es un conjunto de herramientas que permite el aprendizaje automático en el dispositivo ayudando a los desarrolladores a ejecutar sus modelos en dispositivos móviles, integrados y edge.

Convertir el modelo secuencial Keras en un modelo de TensorFlow Lite

Para utilizar el modelo entrenado con aplicaciones en el dispositivo, primero convertirlo a un formato de modelo más pequeño y eficiente llamado modelo TensorFlow Lite.

En este ejemplo, tome el modelo secuencial de Keras entrenado y utilice tf.lite.TFLiteConverter.from_keras_model para generar un modelo TensorFlow Lite:

# Convert the model. converter = tf.lite.TFLiteConverter.from_keras_model(model) tflite_model = converter.convert() # Save the model. with open('model.tflite', 'wb') as f: f.write(tflite_model)

El modelo TensorFlow Lite que guardó en el paso anterior puede contener varias firmas de funciones. La API de conversión de modelos de Keras utiliza automáticamente la firma predeterminada. Obtenga más información sobre firmas de TensorFlow Lite.

Ejecute el modelo de TensorFlow Lite

Puede acceder a las firmas del modelo guardado de TensorFlow Lite en Python a través de la clase tf.lite.Interpreter.

Cargue el modelo con el Interpreter:

TF_MODEL_FILE_PATH = 'model.tflite' # The default path to the saved TensorFlow Lite model interpreter = tf.lite.Interpreter(model_path=TF_MODEL_FILE_PATH)

Imprima las firmas del modelo convertido para obtener los nombres de las entradas (y salidas):

interpreter.get_signature_list()

En este ejemplo, tiene una firma predeterminada llamada serving_default. Además, el nombre de las 'inputs' es 'sequential_1_input', mientras que las 'outputs' se llaman 'outputs'. Puede consultar estos nombres de la primera y la última capa de Keras al ejecutar Model.summary, como se demostró anteriormente en este tutorial.

Ahora puede probar el modelo TensorFlow cargado realizando la inferencia en una imagen de muestra con tf.lite.Interpreter.get_signature_runner pasando el nombre de la firma de la siguiente manera:

classify_lite = interpreter.get_signature_runner('serving_default') classify_lite

De forma similar a lo que hizo anteriormente en el tutorial, puede utilizar el modelo de TensorFlow Lite para clasificar imágenes que no se incluyeron en los conjuntos de entrenamiento o validación.

Ya ha tensorizado esa imagen y la guardó como img_array. Ahora, pásela al primer argumento (el nombre de las 'inputs') del modelo TensorFlow Lite cargado (predictions_lite), calcule las activaciones softmax y, a continuación, imprima la predicción para la clase con la mayor probabilidad calculada.

predictions_lite = classify_lite(sequential_1_input=img_array)['outputs'] score_lite = tf.nn.softmax(predictions_lite)
print( "This image most likely belongs to {} with a {:.2f} percent confidence." .format(class_names[np.argmax(score_lite)], 100 * np.max(score_lite)) )

La predicción generada por el modelo lite debería ser casi idéntica a las predicciones generadas por el modelo original:

print(np.max(np.abs(predictions - predictions_lite)))

De las cinco clases -'daisy', 'dandelion', 'roses', 'sunflowers', y 'tulips' - el modelo debería predecir que la imagen pertenece a los girasoles, que es el mismo resultado que antes de la conversión de TensorFlow Lite.

Siguientes pasos

Este tutorial mostraba cómo entrenar un modelo para la clasificación de imágenes, probarlo, convertirlo al formato TensorFlow Lite para aplicaciones en dispositivos (como una aplicación de clasificación de imágenes) y realizar inferencias con el modelo TensorFlow Lite con la API de Python.

Puede obtener más información sobre TensorFlow Lite a través de tutoriales y guías.