דף זה תורגם על ידי Cloud Translation API.
Switch to English

טוען תמונות

צפה ב- TensorFlow.org הפעל בגוגל קולאב צפה במקור ב- GitHub הורד מחברת

מדריך זה מראה כיצד לטעון ולעבד מראש מערך תמונות בשלוש דרכים. ראשית, תשתמש בכלי עזר לעיבוד מקדים Keras ברמה גבוהה ובשכבות כדי לקרוא ספריית תמונות בדיסק. לאחר מכן, תכתוב צינור קלט משלך מאפס באמצעות tf.data . לבסוף, תוכלו להוריד מערך נתונים מהקטלוג הגדול הזמין במערכי הנתונים של TensorFlow .

להכין

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

הורד את מערך הפרחים

הדרכה זו משתמשת במערך של כמה אלפי תמונות של פרחים. מערך הפרחים מכיל 5 ספריות משנה, אחת לכל כיתה:

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)

לאחר ההורדה (218MB), כעת יהיה עליך לקבל עותק של תמונות הפרחים. יש 3670 תמונות בסך הכל:

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

כל ספריה מכילה תמונות מאותו סוג פרח. הנה כמה ורדים:

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

טען באמצעות keras.preprocessing

בואו נטען את התמונות הללו מהדיסק באמצעות image_dataset_from_directory .

צור מערך נתונים

הגדר כמה פרמטרים עבור המטעין:

batch_size = 32
img_height = 180
img_width = 180

כדאי להשתמש בפיצול אימות בעת פיתוח המודל שלך. נשתמש ב -80% מהתמונות לצורך אימון, וב -20% לצורך אימות.

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.

תוכל למצוא את שמות הכיתות במאפיין class_names במערכי נתונים אלה.

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

דמיין את הנתונים

להלן 9 התמונות הראשונות ממערך האימונים.

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

אתה יכול לאמן מודל באמצעות מערכי נתונים אלה על ידי העברתם ל- model.fit (מוצג בהמשך במדריך זה). אם תרצה, תוכל גם לחזור ידנית על מערך הנתונים ולקבל קבוצות תמונות:

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

ה- image_batch הוא טנסור של הצורה (32, 180, 180, 3) . זהו קבוצה של 32 תמונות בצורת 180x180x3 (הממד האחרון 180x180x3 לערוצי צבע RGB). label_batch הוא טנסור של הצורה (32,) , אלה תוויות תואמות ל- 32 התמונות.

תקן את הנתונים

ערכי ערוץ RGB הם בטווח [0, 255] . זה לא אידיאלי עבור רשת עצבית; באופן כללי עליכם לחפש להפוך את ערכי הקלט שלכם לקטנים. כאן, נתקן את הערכים שיהיו ב- [0, 1] באמצעות שכבת שינוי גודל.

from tensorflow.keras import layers

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

ישנן שתי דרכים להשתמש בשכבה זו. תוכל להחיל אותו על מערך הנתונים על ידי התקשרות למפה:

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

לחלופין, תוכל לכלול את השכבה בתוך הגדרת המודל שלך כדי לפשט את הפריסה. נשתמש כאן בגישה השנייה.

הגדר את מערך הנתונים לביצועים

בואו נדאג להשתמש באיסוף מקדים שנאגר בכדי שנוכל להניב נתונים מהדיסק מבלי ש- I / O יהפוך לחסימה. אלה שתי שיטות חשובות שעליך להשתמש בהן בעת ​​טעינת נתונים.

.cache() שומר את התמונות בזיכרון לאחר .cache() מהדיסק במהלך העידן הראשון. זה יבטיח שמערך הנתונים לא יהפוך לצוואר בקבוק בזמן אימון המודל שלך. אם מערך הנתונים שלך גדול מכדי להיכנס לזיכרון, תוכל גם להשתמש בשיטה זו כדי ליצור מטמון ביצועים בדיסק.

.prefetch() חופף עיבוד מקדים של נתונים וביצוע מודל בזמן אימון.

קוראים מעוניינים יכולים ללמוד עוד על שתי השיטות, כמו גם כיצד לשמור מטמון נתונים לדיסק במדריך ביצועי הנתונים .

AUTOTUNE = tf.data.AUTOTUNE

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

לאמן מודל

להשלמה, נראה כיצד להכשיר מודל פשוט באמצעות מערכי הנתונים שהכנו זה עתה. מודל זה לא הותאם בשום צורה שהיא - המטרה היא להראות לך את המכניקה באמצעות מערכי הנתונים שיצרת זה עתה. למידע נוסף על סיווג תמונות, בקר במדריך זה.

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>

יתכן שתבחין שדיוק האימות נמוך בהשוואה לדיוק האימונים, מה שמעיד על כך שהמודל שלנו מתאים יותר מדי. אתה יכול ללמוד עוד על overfitting וכיצד להפחית אותו זה הדרכה .

שימוש ב- tf.data לשליטה טובה יותר

כלי keras.precessing לעיל הם דרך נוחה ליצורtf.data.Dataset מתוך ספריית תמונות. לשליטה טובה יותר בדגנים, תוכלו לכתוב צינור קלט משלכם באמצעות tf.data . סעיף זה מראה כיצד לעשות בדיוק את זה, החל מנתיבי הקבצים מה- zip שהורדנו קודם.

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'

ניתן להשתמש במבנה העץ של הקבצים class_names רשימת 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']

פצל את מערך הנתונים לרכבת ואימות:

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

אתה יכול לראות את אורכו של כל מערך נתונים באופן הבא:

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

כתוב פונקציה קצרה הממירה נתיב קובץ לזוג (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

השתמש ב- Dataset.map כדי ליצור מערך נתונים של image, label זוגות 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

הגדר את מערך הנתונים לביצועים

כדי להכשיר מודל עם מערך נתונים זה תרצו את הנתונים:

  • להיות מעורבב היטב.
  • להיות קבוצה.
  • אצוות יהיו זמינים בהקדם האפשרי.

ניתן להוסיף תכונות אלה באמצעות ממשק ה- API של tf.data . לפרטים נוספים, עיין במדריך ביצועי צינור הקלט .

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)

דמיין את הנתונים

באפשרותך לדמיין את מערך הנתונים זהה לזה שיצרת בעבר.

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

המשך באימון המודל

כעת בנית ידניתtf.data.Dataset דומהtf.data.Dataset שנוצר על ידי keras.preprocessing לעיל. אתה יכול להמשיך לאמן את המודל איתו. כמו בעבר, נתאמן רק כמה תקופות כדי לשמור על זמן הריצה קצר.

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>

שימוש במערכי נתונים של TensorFlow

עד כה, הדרכה זו התמקדה בטעינת נתונים מדיסק. אתה יכול גם למצוא מערך נתונים לשימוש על ידי עיון בקטלוג הגדול של מערכי הנתונים הקלים להורדה ב- TensorFlow Datasets . כפי שטעננת בעבר את מערך הנתונים של פרחים מהדיסק, בוא נראה כיצד לייבא אותו עם ערכות נתונים של TensorFlow.

הורד את מערך הנתונים של פרחים באמצעות מערכי נתונים של 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,
)

מערך הפרחים כולל חמש מחלקות.

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

אחזר תמונה ממערך הנתונים.

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

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

png

כמו בעבר, זכור לאצווה, לדשדש ולהגדיר תצורה של כל מערך נתונים לביצועים.

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

תוכל למצוא דוגמה מלאה לעבודה עם מערך הנתונים של פרחים ומערכי הנתונים של TensorFlow על ידי ביקור במדריך להגדלת הנתונים .

הצעדים הבאים

מדריך זה הראה שתי דרכים לטעינת תמונות מהדיסק. ראשית, למדת כיצד לטעון ולעבד מראש מערך תמונות באמצעות Keras שכבות ועיבוד מראש. לאחר מכן למדת כיצד לכתוב צינור קלט מאפס באמצעות tf.data. לבסוף למדת כיצד להוריד מערך נתונים ממערכי הנתונים של TensorFlow. כשלב הבא, תוכלו ללמוד כיצד להוסיף הגדלת נתונים על ידי ביקור במדריך זה. למידע נוסף על tf.data, תוכל לבקר במדריך זה.