Questa pagina è stata tradotta dall'API Cloud Translation.
Switch to English

Carica immagini

Visualizza su TensorFlow.org Esegui in Google Colab Visualizza sorgente su GitHub Scarica il quaderno

Questa esercitazione mostra come caricare e preelaborare un set di dati di immagini in due modi. In primo luogo, utilizzerai utility e livelli di preelaborazione Keras di alto livello. Successivamente, scriverai la tua pipeline di input da zero usando tf.data .

Impostare

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

Scarica il set di dati di fiori

Questo tutorial utilizza un set di dati di diverse migliaia di foto di fiori. Il set di dati di fiori contiene 5 sottodirectory, una per 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)
 

Dopo aver scaricato (218 MB), ora dovresti avere una copia delle foto dei fiori disponibili. Ci sono 3670 immagini totali:

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

Ogni directory contiene immagini di quel tipo di fiore. Ecco alcune rose:

 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

Carica usando keras.preprocessing

Carichiamo queste immagini dal disco usando image_dataset_from_directory .

Crea un set di dati

Definire alcuni parametri per il caricatore:

 batch_size = 32
img_height = 180
img_width = 180
 

È buona norma utilizzare una suddivisione di convalida durante lo sviluppo del modello. Useremo l'80% delle immagini per la formazione e il 20% per la convalida.

 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.

È possibile trovare i nomi delle classi nell'attributo class_names in questi set di dati.

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

Visualizza i dati

Ecco le prime 9 immagini dal set di dati di allenamento.

 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

Puoi addestrare un modello usando questi set di dati passandoli a model.fit (mostrato più avanti in questo tutorial). Se lo desideri, puoi anche scorrere manualmente il set di dati e recuperare batch di immagini:

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

image_batch è un tensore della forma (32, 180, 180, 3) . Si tratta di un lotto di 32 immagini di forma 180x180x3 (l'ultima dimensione si riferisce ai canali di colore RGB). label_batch è un tensore della forma (32,) , queste sono etichette corrispondenti alle 32 immagini.

Standardizzare i dati

I valori del canale RGB sono compresi nell'intervallo [0, 255] . Questo non è l'ideale per una rete neurale; in generale dovresti cercare di ridurre i tuoi valori di input. Qui, standardizzeremo i valori in modo che siano in [0, 1] usando un livello Rescaling.

 from tensorflow.keras import layers

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

Esistono due modi per utilizzare questo livello. Puoi applicarlo al set di dati chiamando 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

In alternativa, è possibile includere il livello all'interno della definizione del modello per semplificare la distribuzione. Useremo il secondo approccio qui.

Configurare il set di dati per le prestazioni

Assicuriamoci di utilizzare il prefetching bufferizzato in modo da poter produrre dati dal disco senza che l'I / O diventi blocco. Questi sono due metodi importanti che dovresti usare quando carichi i dati.

.cache() mantiene le immagini in memoria dopo che sono state caricate dal disco durante la prima epoca. Ciò garantirà che il set di dati non diventi un collo di bottiglia durante l'addestramento del modello. Se il set di dati è troppo grande per adattarsi alla memoria, è anche possibile utilizzare questo metodo per creare una cache su disco performante.

.prefetch() sovrappone alla preelaborazione dei dati e all'esecuzione del modello durante l'addestramento.

I lettori interessati possono saperne di più su entrambi i metodi e su come memorizzare nella cache i dati su disco nella guida alle prestazioni dei dati .

 AUTOTUNE = tf.data.experimental.AUTOTUNE

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

Allena un modello

Per completezza, mostreremo come addestrare un modello semplice usando i set di dati che abbiamo appena preparato. Questo modello non è stato ottimizzato in alcun modo: l'obiettivo è mostrarti la meccanica usando i set di dati che hai appena creato. Per ulteriori informazioni sulla classificazione delle immagini, visita questo 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>

È possibile notare che l'accuratezza della convalida è bassa rispetto alla precisione dell'addestramento, indicando che il nostro modello è troppo adatto. Puoi imparare di più sul sovradimensionamento e su come ridurlo in questo tutorial .

Utilizzo di tf.data per un controllo più preciso

Le utilità di cui sopra keras.preprocessing sono un modo conveniente per creare un tf.data.Dataset da una directory di immagini. Per un controllo più tf.data cereali, è possibile scrivere la propria pipeline di input utilizzando tf.data . Questa sezione mostra come fare proprio questo, a partire dai percorsi dei file dalla zip che abbiamo scaricato in precedenza.

 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 struttura ad albero dei file può essere utilizzata per compilare un elenco di 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']

Dividi il set di dati in treno e convalida:

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

È possibile visualizzare la lunghezza di ciascun set di dati come segue:

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

Scrivi una breve funzione che converte un percorso di file in una coppia (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
 

Utilizzare Dataset.map per creare un set di dati di image, label coppie di 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

Configurare il set di dati per le prestazioni

Per addestrare un modello con questo set di dati è necessario disporre dei dati:

  • Essere mescolati bene.
  • Essere batch.
  • I lotti saranno disponibili il prima possibile.

Queste funzionalità possono essere aggiunte utilizzando l'API tf.data . Per ulteriori dettagli, consultare la Guida alle prestazioni della pipeline di input .

 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)
 

Visualizza i dati

È possibile visualizzare questo set di dati in modo simile a quello creato in precedenza.

 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

Continua ad allenare il modello

Ora hai creato manualmente un tf.data.Dataset simile a quello creato da keras.preprocessing sopra. Puoi continuare ad addestrare il modello con esso. Come prima, ci alleneremo solo per alcune epoche per ridurre i tempi di esecuzione.

 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>

Prossimi passi

Questo tutorial ha mostrato due modi per caricare le immagini dal disco. Innanzitutto, hai imparato come caricare e preelaborare un set di dati di immagini utilizzando i livelli e le utilità di preelaborazione di Keras. Successivamente, hai imparato come scrivere una pipeline di input da zero utilizzando tf.data. Come passaggio successivo, puoi imparare come aggiungere l'aumento dei dati visitando questo tutorial . Per saperne di più su tf.data, puoi visitare questa guida .