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 notebook

Questo tutorial mostra come caricare e preelaborare un set di dati di immagine in tre modi. Per prima cosa, utilizzerai le utility ei livelli di pre-elaborazione di Keras di alto livello per leggere una directory di immagini sul disco. Successivamente, scriverai la tua pipeline di input da zero usando tf.data . Infine, scaricherai un set di dati dall'ampio catalogo disponibile in TensorFlow Datasets .

Impostare

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

Scarica il dataset dei fiori

Questo tutorial utilizza un set di dati di diverse migliaia di foto di fiori. Il set di dati dei 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 il download (218 MB), ora dovresti avere una copia delle foto dei fiori disponibile. 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

Definisci alcuni parametri per il caricatore:

batch_size = 32
img_height = 180
img_width = 180

È buona norma utilizzare una divisione 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 su 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 addestramento.

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 iterare manualmente sul 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) . Questo è 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.

Standardizza i dati

I valori del canale RGB sono nella gamma [0, 255] . Questo non è l'ideale per una rete neurale; in generale dovresti cercare di ridurre i valori di input. Qui standardizzeremo i valori in modo che siano in [0, 1] utilizzando un livello di ridimensionamento.

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

Oppure puoi includere il livello all'interno della definizione del modello per semplificare la distribuzione. Useremo il secondo approccio qui.

Configura il set di dati per le prestazioni

Assicuriamoci di utilizzare il precaricamento bufferizzato in modo da poter produrre dati dal disco senza che l'I / O si blocchi. Questi sono due metodi importanti da utilizzare durante il caricamento dei 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 tuo set di dati è troppo grande per essere contenuto in memoria, puoi anche utilizzare questo metodo per creare una cache su disco efficiente.

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

I lettori interessati possono ottenere ulteriori informazioni su entrambi i metodi e su come memorizzare nella cache i dati su disco nella guida alle prestazioni dei dati .

AUTOTUNE = tf.data.AUTOTUNE

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

Addestra un modello

Per completezza, mostreremo come addestrare un modello semplice utilizzando i set di dati che abbiamo appena preparato. Questo modello non è stato messo a punto in alcun modo: l'obiettivo è mostrarti la meccanica utilizzando 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 [==============================] - 9s 70ms/step - loss: 1.4384 - accuracy: 0.3840 - val_loss: 1.0406 - val_accuracy: 0.5913
Epoch 2/3
92/92 [==============================] - 1s 12ms/step - loss: 1.0117 - accuracy: 0.6021 - val_loss: 0.9834 - val_accuracy: 0.6158
Epoch 3/3
92/92 [==============================] - 1s 12ms/step - loss: 0.8540 - accuracy: 0.6748 - val_loss: 0.9012 - val_accuracy: 0.6553

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

Potresti notare che la precisione della convalida è bassa rispetto alla precisione dell'addestramento, indicando che il nostro modello è overfitting. Puoi saperne di più sull'overfitting e su come ridurlo in questo tutorial .

Utilizzo di tf.data per un controllo più preciso

Le suddette utilità keras.preprocessing sono un modo conveniente per creare untf.data.Dataset da una directory di immagini. Per un controllo più preciso, puoi scrivere la tua pipeline di input utilizzando tf.data . Questa sezione mostra come farlo, iniziando con i percorsi dei file dallo 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/tulips/8733586143_3139db6e9e_n.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/daisy/14523675369_97c31d0b5b.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/dandelion/16716172029_2166d8717f_m.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/sunflowers/4186808407_06688641e2_n.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/roses/3667366832_7a8017c528_n.jpg'

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

Suddividi il set di dati in formazione e convalida:

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

Puoi vedere la lunghezza di ogni 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 converta 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

Usa 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:  3

Configura set di dati per le prestazioni

Per addestrare un modello con questo set di dati ti serviranno i dati:

  • Per essere ben mescolato.
  • Da raggruppare.
  • I lotti saranno disponibili il prima possibile.

Queste funzionalità possono essere aggiunte utilizzando l'API tf.data . Per ulteriori dettagli, vedere 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

Puoi visualizzare questo set di dati in modo simile a quello che hai 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 addestrare il modello

Ora hai creato manualmente untf.data.Dataset simile a quello creato da keras.preprocessing sopra. Puoi continuare ad addestrare il modello con esso. Come prima, ci alleneremo solo per poche epoche per mantenere breve il tempo di esecuzione.

model.fit(
  train_ds,
  validation_data=val_ds,
  epochs=3
)
Epoch 1/3
92/92 [==============================] - 2s 20ms/step - loss: 0.7249 - accuracy: 0.7296 - val_loss: 0.6796 - val_accuracy: 0.7466
Epoch 2/3
92/92 [==============================] - 1s 12ms/step - loss: 0.5239 - accuracy: 0.8055 - val_loss: 0.6280 - val_accuracy: 0.7793
Epoch 3/3
92/92 [==============================] - 1s 12ms/step - loss: 0.3618 - accuracy: 0.8801 - val_loss: 0.6565 - val_accuracy: 0.7766

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

Utilizzo di set di dati TensorFlow

Finora, questo tutorial si è concentrato sul caricamento dei dati dal disco. Puoi anche trovare un set di dati da utilizzare esplorando l'ampio catalogo di set di dati facili da scaricare in Set di dati TensorFlow . Dato che hai precedentemente caricato il dataset Flowers su disco, vediamo come importarlo con i dataset TensorFlow.

Scarica il set di dati dei fiori utilizzando i set di dati 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,
)

Il set di dati dei fiori ha cinque classi.

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

Recupera un'immagine dal set di dati.

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

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

png

Come prima, ricorda di raggruppare, mescolare e configurare ogni set di dati per le prestazioni.

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

Puoi trovare un esempio completo di utilizzo del set di dati dei fiori e dei set di dati TensorFlow visitando il tutorial sull'aumento dei dati .

Prossimi passi

Questo tutorial ha mostrato due modi per caricare le immagini dal disco. Innanzitutto, hai imparato a caricare e preelaborare un set di dati di immagine utilizzando i livelli e le utilità di preelaborazione di Keras. Successivamente, hai imparato come scrivere una pipeline di input da zero usando tf.data. Infine, hai imparato a scaricare un set di dati dai set di dati TensorFlow. 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 .