Diese Seite wurde von der Cloud Translation API übersetzt.
Switch to English

Bilder laden

Ansicht auf TensorFlow.org In Google Colab ausführen Quelle auf GitHub anzeigen Notizbuch herunterladen

Dieses Tutorial zeigt, wie ein Bilddatensatz auf drei Arten geladen und vorverarbeitet wird. Als erstes müssen Sie auf hohe Ebene Keras Vorverarbeitung verwenden Dienstprogramme und Schichten ein Verzeichnis der Bilder auf der Festplatte zu lesen. Als Nächstes schreiben Sie mit tf.data Ihre eigene Eingabepipeline von Grund auf neu . Schließlich laden Sie einen Datensatz aus dem großen Katalog herunter, der in TensorFlow-Datensätzen verfügbar ist.

Konfiguration

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

Laden Sie den Blumendatensatz herunter

In diesem Tutorial wird ein Datensatz mit mehreren tausend Fotos von Blumen verwendet. Der Blumendatensatz enthält 5 Unterverzeichnisse, eines pro Klasse:

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)
Downloading data from https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz
228818944/228813984 [==============================] - 1s 0us/step

Nach dem Herunterladen (218 MB) sollten Sie nun eine Kopie der Blumenfotos zur Verfügung haben. Es gibt insgesamt 3670 Bilder:

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

Jedes Verzeichnis enthält Bilder dieses Blumentyps. Hier sind einige Rosen:

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

Laden Sie mit keras.preprocessing

Laden Sie diese Bilder mit image_dataset_from_directory von der Festplatte.

Erstellen Sie einen Datensatz

Definieren Sie einige Parameter für den Loader:

batch_size = 32
img_height = 180
img_width = 180

Es wird empfohlen, bei der Entwicklung Ihres Modells einen Validierungssplit zu verwenden. Wir werden 80% der Bilder für das Training und 20% für die Validierung verwenden.

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.

Sie finden die Klassennamen im Attribut class_names für diese Datasets.

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

Visualisieren Sie die Daten

Hier sind die ersten 9 Bilder aus dem Trainingsdatensatz.

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

Sie können ein Modell mithilfe dieser Datensätze trainieren, indem Sie sie an model.fit (siehe weiter model.fit in diesem Lernprogramm). Wenn Sie möchten, können Sie den Datensatz auch manuell durchlaufen und Stapel von Bildern abrufen:

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

Der image_batch ist ein Tensor der Form (32, 180, 180, 3) . Dies ist ein Stapel von 32 Bildern mit der Form 180x180x3 (die letzte Dimension bezieht sich auf Farbkanäle RGB). Der label_batch ist ein Tensor der Form (32,) , dies sind entsprechende Beschriftungen zu den 32 Bildern.

Standardisieren Sie die Daten

Die RGB-Kanalwerte liegen im Bereich [0, 255] . Dies ist nicht ideal für ein neuronales Netzwerk. Im Allgemeinen sollten Sie versuchen, Ihre Eingabewerte klein zu machen. Hier standardisieren wir die Werte in [0, 1] mithilfe einer Rescaling-Ebene.

from tensorflow.keras import layers

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

Es gibt zwei Möglichkeiten, diese Ebene zu verwenden. Sie können es auf den Datensatz anwenden, indem Sie map aufrufen:

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

Sie können die Ebene auch in Ihre Modelldefinition aufnehmen, um die Bereitstellung zu vereinfachen. Wir werden hier den zweiten Ansatz verwenden.

Konfigurieren Sie das Dataset für die Leistung

Stellen Sie sicher, dass Sie gepuffertes Prefetching verwenden, damit wir Daten von der Festplatte liefern können, ohne dass E / A blockiert werden. Dies sind zwei wichtige Methoden, die Sie beim Laden von Daten verwenden sollten.

.cache() speichert die Bilder, nachdem sie in der ersten Epoche von der Festplatte geladen wurden. Dadurch wird sichergestellt, dass der Datensatz beim Training Ihres Modells nicht zu einem Engpass wird. Wenn Ihr Dataset zu groß ist, um in den Speicher zu passen, können Sie mit dieser Methode auch einen performanten Cache auf der Festplatte erstellen.

.prefetch() überlappt die Datenvorverarbeitung und die Modellausführung während des Trainings.

Interessierte Leser erfahren mehr über beide Methoden sowie über das Zwischenspeichern von Daten auf der Festplatte im Handbuch zur Datenleistung .

AUTOTUNE = tf.data.experimental.AUTOTUNE

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

Trainiere ein Modell

Der Vollständigkeit halber zeigen wir, wie ein einfaches Modell anhand der soeben vorbereiteten Datensätze trainiert wird. Dieses Modell wurde in keiner Weise optimiert. Ziel ist es, Ihnen die Mechanik anhand der soeben erstellten Datensätze zu zeigen. Weitere Informationen zur Bildklassifizierung finden Sie in diesem 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 67ms/step - loss: 1.3187 - accuracy: 0.4401 - val_loss: 1.1184 - val_accuracy: 0.5681
Epoch 2/3
92/92 [==============================] - 1s 10ms/step - loss: 1.0639 - accuracy: 0.5838 - val_loss: 1.0369 - val_accuracy: 0.5926
Epoch 3/3
92/92 [==============================] - 1s 10ms/step - loss: 0.9236 - accuracy: 0.6458 - val_loss: 0.9955 - val_accuracy: 0.5995

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

Möglicherweise stellen Sie fest, dass die Validierungsgenauigkeit im Vergleich zur Trainingsgenauigkeit niedrig ist, was darauf hinweist, dass unser Modell überpasst. In diesem Tutorial erfahren Sie mehr über Überanpassung und wie Sie diese reduzieren können.

Verwendung von tf.data für eine feinere Kontrolle

Die oben genannten Dienstprogramme für keras.preprocessing sind eine bequeme Möglichkeit, ein tf.data.Dataset aus einem Verzeichnis von Bildern zu erstellen. Für eine feinere tf.data können Sie mit tf.data Ihre eigene Eingabepipeline tf.data . Dieser Abschnitt zeigt, wie Sie genau das tun, beginnend mit den Dateipfaden aus der zuvor heruntergeladenen Zip-Datei.

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/dandelion/3530500952_9f94fb8b9c_m.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/sunflowers/16656015339_2ccb7cd18d.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/sunflowers/8480886751_71d88bfdc0_n.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/dandelion/14021281124_89cc388eac_n.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/daisy/2632216904_274aa17433.jpg'

Die Baumstruktur der Dateien kann zum Kompilieren einer 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']

Teilen Sie den Datensatz in Zug und Validierung auf:

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

Sie können die Länge jedes Datensatzes wie folgt sehen:

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

Schreiben Sie eine kurze Funktion, die einen Dateipfad in ein (img, label) Paar konvertiert:

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

Verwenden Sie Dataset.map , um einen Datensatz mit image, label zu erstellen:

# 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

Konfigurieren Sie das Dataset für die Leistung

Um ein Modell mit diesem Datensatz zu trainieren, benötigen Sie die Daten:

  • Gut gemischt sein.
  • Zu chargen.
  • Chargen müssen so schnell wie möglich verfügbar sein.

Diese Funktionen können mithilfe der tf.data API hinzugefügt werden. Weitere Informationen finden Sie im Handbuch zur Leistung der Eingabepipeline.

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)

Visualisieren Sie die Daten

Sie können dieses Dataset ähnlich wie das zuvor erstellte anzeigen.

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

Trainieren Sie das Modell weiter

Sie haben jetzt manuell ein ähnliches tf.data.Dataset erstellt, das dem von keras.preprocessing oben erstellten entspricht. Sie können das Modell damit weiter trainieren. Nach wie vor werden wir nur einige Epochen trainieren, um die Laufzeit kurz zu halten.

model.fit(
  train_ds,
  validation_data=val_ds,
  epochs=3
)
Epoch 1/3
92/92 [==============================] - 2s 19ms/step - loss: 0.7869 - accuracy: 0.7054 - val_loss: 0.7747 - val_accuracy: 0.7071
Epoch 2/3
92/92 [==============================] - 1s 11ms/step - loss: 0.5762 - accuracy: 0.7892 - val_loss: 0.8838 - val_accuracy: 0.6689
Epoch 3/3
92/92 [==============================] - 1s 11ms/step - loss: 0.4070 - accuracy: 0.8556 - val_loss: 0.9416 - val_accuracy: 0.6812

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

Verwenden von TensorFlow-Datensätzen

Bisher konzentrierte sich dieses Tutorial auf das Laden von Daten von der Festplatte. Sie können auch einen Datensatz finden, den Sie verwenden können, indem Sie den großen Katalog einfach herunterladbarer Datensätze unter TensorFlow -Datensätze durchsuchen . Nachdem Sie das Flowers-Dataset zuvor von der Festplatte geladen haben, sehen wir uns an, wie Sie es mit TensorFlow-Datasets importieren.

Laden Sie den Blumendatensatz mit TensorFlow-Datensätzen herunter.

(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,
)
Downloading and preparing dataset tf_flowers/3.0.1 (download: 218.21 MiB, generated: 221.83 MiB, total: 440.05 MiB) to /home/kbuilder/tensorflow_datasets/tf_flowers/3.0.1...

Warning:absl:Dataset tf_flowers is hosted on GCS. It will automatically be downloaded to your
local data directory. If you'd instead prefer to read directly from our public
GCS bucket (recommended if you're running on GCP), you can instead pass
`try_gcs=True` to `tfds.load` or set `data_dir=gs://tfds-data/datasets`.


Dataset tf_flowers downloaded and prepared to /home/kbuilder/tensorflow_datasets/tf_flowers/3.0.1. Subsequent calls will reuse this data.

Der Blumendatensatz hat fünf Klassen.

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

Rufen Sie ein Bild aus dem Datensatz ab.

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

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

png

Denken Sie nach wie vor daran, jedes Dataset für die Leistung zu stapeln, zu mischen und zu konfigurieren.

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

Ein vollständiges Beispiel für die Arbeit mit dem Blumendatensatz und den TensorFlow- Datensätzen finden Sie im Tutorial zur Datenerweiterung.

Nächste Schritte

Dieses Tutorial zeigte zwei Möglichkeiten zum Laden von Bildern von der Festplatte. Zunächst haben Sie gelernt, wie Sie ein Bilddatensatz mithilfe von Keras-Vorverarbeitungsebenen und -Dienstprogrammen laden und vorverarbeiten. Als Nächstes haben Sie gelernt, wie Sie mit tf.data eine Eingabepipeline von Grund auf neu schreiben. Schließlich haben Sie gelernt, wie Sie einen Datensatz von TensorFlow-Datensätzen herunterladen. In einem nächsten Schritt erfahren Sie, wie Sie Datenerweiterungen hinzufügen, indem Sie dieses Lernprogramm besuchen. Um mehr über tf.data zu erfahren, können Sie diesen Leitfaden besuchen.