Esta página foi traduzida pela API Cloud Translation.
Switch to English

Carregar imagens

Ver no TensorFlow.org Executar no Google Colab Ver fonte no GitHub Baixar caderno

Este tutorial mostra como carregar e pré-processar um conjunto de dados de imagem de três maneiras. Primeiro, você usará camadas e utilitários de pré-processamento Keras de alto nível para ler um diretório de imagens no disco. Em seguida, você escreverá seu próprio pipeline de entrada do zero usando tf.data . Por fim, você fará o download de um conjunto de dados do grande catálogo disponível no TensorFlow Datasets .

Configuração

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

Baixe o conjunto de dados de flores

Este tutorial usa um conjunto de dados de vários milhares de fotos de flores. O conjunto de dados de flores contém 5 subdiretórios, um por classe:

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)

Após o download (218 MB), você deve ter uma cópia das fotos das flores disponíveis. Existem 3670 imagens no total:

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

Cada diretório contém imagens desse tipo de flor. Aqui estão algumas 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

Carregar usando keras.preprocessing

Vamos carregar essas imagens do disco usando image_dataset_from_directory .

Crie um conjunto de dados

Defina alguns parâmetros para o carregador:

batch_size = 32
img_height = 180
img_width = 180

É uma boa prática usar uma divisão de validação ao desenvolver seu modelo. Usaremos 80% das imagens para treinamento e 20% para validação.

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.

Você pode encontrar os nomes das classes no atributo class_names nesses conjuntos de dados.

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

Visualize os dados

Aqui estão as primeiras 9 imagens do conjunto de dados de treinamento.

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

Você pode treinar um modelo usando esses conjuntos de dados, passando-os para model.fit (mostrado posteriormente neste tutorial). Se desejar, você também pode iterar manualmente no conjunto de dados e recuperar lotes de imagens:

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

O image_batch é um tensor da forma (32, 180, 180, 3) . Este é um lote de 32 imagens de formato 180x180x3 (a última dimensão se refere aos canais de cores RGB). O label_batch é um tensor da forma (32,) , esses são rótulos correspondentes às 32 imagens.

Padronize os dados

Os valores do canal RGB estão na faixa [0, 255] . Isso não é ideal para uma rede neural; em geral, você deve tentar diminuir os valores de entrada. Aqui, iremos padronizar os valores para estarem em [0, 1] usando uma camada de reescalonamento.

from tensorflow.keras import layers

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

Existem duas maneiras de usar essa camada. Você pode aplicá-lo ao conjunto de dados chamando 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 pixels values are now in `[0,1]`.
print(np.min(first_image), np.max(first_image)) 
0.0 0.96902645

Ou você pode incluir a camada dentro da definição do modelo para simplificar a implantação. Usaremos a segunda abordagem aqui.

Configure o conjunto de dados para desempenho

Vamos nos certificar de usar a pré-busca em buffer para que possamos gerar dados do disco sem que o I / O se torne um bloqueio. Esses são dois métodos importantes que você deve usar ao carregar dados.

.cache() mantém as imagens na memória depois que são carregadas do disco durante a primeira época. Isso garantirá que o conjunto de dados não se torne um gargalo durante o treinamento do seu modelo. Se o seu conjunto de dados for muito grande para caber na memória, você também pode usar este método para criar um cache em disco de alto desempenho.

.prefetch() sobrepõe o pré-processamento de dados e a execução do modelo durante o treinamento.

Leitores interessados ​​podem aprender mais sobre os dois métodos, bem como como armazenar dados em cache no disco no guia de desempenho de dados .

AUTOTUNE = tf.data.experimental.AUTOTUNE

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

Treine uma modelo

Para completar, mostraremos como treinar um modelo simples usando os conjuntos de dados que acabamos de preparar. Este modelo não foi ajustado de forma alguma - o objetivo é mostrar a você a mecânica usando os conjuntos de dados que você acabou de criar. Para saber mais sobre a classificação de imagens, 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 [==============================] - 7s 74ms/step - loss: 1.3679 - accuracy: 0.4131 - val_loss: 1.1740 - val_accuracy: 0.5381
Epoch 2/3
92/92 [==============================] - 1s 11ms/step - loss: 1.0772 - accuracy: 0.5623 - val_loss: 1.0466 - val_accuracy: 0.5899
Epoch 3/3
92/92 [==============================] - 1s 11ms/step - loss: 0.9490 - accuracy: 0.6349 - val_loss: 0.9824 - val_accuracy: 0.6267

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

Você pode notar que a precisão da validação é baixa em comparação com a precisão do treinamento, indicando que nosso modelo está superdimensionado. Você pode aprender mais sobre overfitting e como reduzi-lo neste tutorial .

Usando tf.data para um controle mais preciso

Os utilitários keras.preprocessing acima são uma maneira conveniente de criar um tf.data.Dataset partir de um diretório de imagens. Para um controle mais refinado, você pode escrever seu próprio pipeline de entrada usando tf.data . Esta seção mostra como fazer exatamente isso, começando com os caminhos de arquivo do zip que baixamos 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/tulips/13510068773_c925c5517c.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/tulips/6931748252_68f06086b3.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/daisy/1031799732_e7f4008c03.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/dandelion/18342918441_b1bb69a2fd_n.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/daisy/162362896_99c7d851c8_n.jpg'

A estrutura em árvore dos arquivos pode ser usada para compilar uma 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 o conjunto de dados em treinamento e validação:

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

Você pode ver o comprimento de cada conjunto de dados da seguinte maneira:

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

Escreva uma função curta que converta um caminho de arquivo em um 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 criar um conjunto de dados 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:  4

Configurar conjunto de dados para desempenho

Para treinar um modelo com este conjunto de dados, você vai querer os dados:

  • Para ser bem embaralhado.
  • Para ser agrupado.
  • Os lotes estarão disponíveis o mais rápido possível.

Esses recursos podem ser adicionados usando a API tf.data . Para obter mais detalhes, consulte o guia Desempenho do pipeline 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)

Visualize os dados

Você pode visualizar este conjunto de dados de forma semelhante ao criado 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

Continue treinando o modelo

Agora você construiu manualmente um tf.data.Dataset semelhante ao criado pelo keras.preprocessing acima. Você pode continuar treinando o modelo com ele. Como antes, treinaremos por apenas algumas épocas para reduzir o tempo de corrida.

model.fit(
  train_ds,
  validation_data=val_ds,
  epochs=3
)
Epoch 1/3
92/92 [==============================] - 2s 20ms/step - loss: 0.8373 - accuracy: 0.6890 - val_loss: 0.8115 - val_accuracy: 0.6866
Epoch 2/3
92/92 [==============================] - 1s 12ms/step - loss: 0.6614 - accuracy: 0.7585 - val_loss: 0.7761 - val_accuracy: 0.7003
Epoch 3/3
92/92 [==============================] - 1s 11ms/step - loss: 0.4723 - accuracy: 0.8294 - val_loss: 0.8492 - val_accuracy: 0.7125

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

Usando conjuntos de dados TensorFlow

Até agora, este tutorial se concentrou em carregar dados fora do disco. Você também pode encontrar um conjunto de dados para usar explorando o grande catálogo de conjuntos de dados fáceis de baixar no TensorFlow Datasets . Como você carregou anteriormente o conjunto de dados Flowers fora do disco, vamos ver como importá-lo com os conjuntos de dados TensorFlow.

Faça o download do conjunto de dados de flores usando os conjuntos de dados TensorFlow.

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

O conjunto de dados de flores tem cinco classes.

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

Recupere uma imagem do conjunto de dados.

get_label_name = metadata.features['label'].int2str

image, label = next(iter(train_ds))
_ = plt.imshow(image)
_ = plt.title(get_label_name(label))

png

Como antes, lembre-se de agrupar, embaralhar e configurar cada conjunto de dados para desempenho.

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

Você pode encontrar um exemplo completo de como trabalhar com o conjunto de dados de flores e os conjuntos de dados TensorFlow visitando o tutorial de aumento de dados .

Próximos passos

Este tutorial mostrou duas maneiras de carregar imagens do disco. Primeiro, você aprendeu como carregar e pré-processar um conjunto de dados de imagem usando camadas e utilitários de pré-processamento Keras. Em seguida, você aprendeu como escrever um pipeline de entrada do zero usando tf.data. Por fim, você aprendeu como fazer o download de um conjunto de dados do TensorFlow Datasets. Como uma próxima etapa, você pode aprender como adicionar aumento de dados visitando este tutorial . Para saber mais sobre tf.data, você pode visitar este guia .