![]() | ![]() | ![]() | ![]() |
מדריך זה מראה כיצד לטעון ולעבד מראש מערך תמונות בשלוש דרכים. ראשית, תשתמש בכלי עזר לעיבוד מקדים 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]))
roses = list(data_dir.glob('roses/*'))
PIL.Image.open(str(roses[1]))
טען באמצעות 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")
אתה יכול לאמן מודל באמצעות מערכי נתונים אלה על ידי העברתם ל- 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")
המשך באימון המודל
כעת בנית ידנית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))
כמו בעבר, זכור לאצווה, לדשדש ולהגדיר תצורה של כל מערך נתונים לביצועים.
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, תוכל לבקר במדריך זה.