В этом посте показано, как загрузить и предварительно обработать набор данных изображения тремя способами: Во-первых, вы будете использовать высокоуровневые утилиты предварительной обработки Keras (такие как tf.keras.utils.image_dataset_from_directory) и слои (такие как tf.keras.layers.Rescaling) для чтения каталога изображений на диске. Далее вы напишете свой собственный конвейер ввода с нуля, используя tf.data. Наконец, вы загрузите набор данных из большого каталога, доступного в наборах данных TensorFlow.
Code 1
(.env) [boris@fedora34server FLOWERS]$ cat tulipTensor2.py
import numpy as np
import os
import PIL
import PIL.Image
import tensorflow as tf
import tensorflow_datasets as tfds
# print(tf.__version__)
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)
image_count = len(list(data_dir.glob('*/*.jpg')))
print(image_count)
batch_size = 32
img_height = 180
img_width = 180
train_ds = tf.keras.utils.image_dataset_from_directory(
data_dir,
validation_split=0.2,
subset="training",
seed=123,
image_size=(img_height, img_width),
batch_size=batch_size)
print(train_ds)
val_ds = tf.keras.utils.image_dataset_from_directory(
data_dir,
validation_split=0.2,
subset="validation",
seed=123,
image_size=(img_height, img_width),
batch_size=batch_size)
print(val_ds)
class_names = train_ds.class_names
print(class_names)
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")
# Стандартизируйте данные
# Значения канала RGB находятся в диапазоне [0, 255]. Это не идеально для нейронной сети;
# в общем, вы должны стремиться к тому, чтобы ваши входные значения были небольшими.
# Здесь вы стандартизируете значения в диапазоне [0, 1] с помощью tf.keras.layers.Rescaling:
normalization_layer = tf.keras.layers.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 pixel values are now in `[0,1]`.
print(np.min(first_image), np.max(first_image))
# Dataset.cache хранит изображения в памяти после их загрузки с диска в течение первой эпохи.
# Это гарантирует, что набор данных не станет узким местом при обучении вашей модели.
# Если ваш набор данных слишком велик, чтобы поместиться в память, вы также можете
# использовать
# этот метод для создания производительного кэша на диске.
# Dataset.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([
tf.keras.layers.Rescaling(1./255),
tf.keras.layers.Conv2D(32, 3, activation='relu'),
tf.keras.layers.MaxPooling2D(),
tf.keras.layers.Conv2D(32, 3, activation='relu'),
tf.keras.layers.MaxPooling2D(),
tf.keras.layers.Conv2D(32, 3, activation='relu'),
tf.keras.layers.MaxPooling2D(),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dense(num_classes)
])
# Выберите оптимизатор tf.keras.optimizers.Adam и функцию потерь
# tf.keras.losses.SparseCategoricalCrossentropy. Чтобы просмотреть
# точность обучения и проверки для каждой эпохи обучения,
# передайте аргумент метрики в Model.compile
model.compile(
optimizer='adam',
loss=tf.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])
model.fit(train_ds,validation_data=val_ds, epochs=3)
# Использование tf.data для более тонкого контроля
# Для более точного управления вы можете написать свой
# собственный входной конвейер,
# используя tf.data. В этом разделе показано, как это сделать,
# начиная с путей к файлам из загруженного ранее файла TGZ.
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())
class_names = np.array(sorted([item.name for item in data_dir.glob('*') if item.name != "LICENSE.txt"]))
print(class_names)
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())
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.io.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 для создания набора данных пар изображений и меток
# 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())
# Чтобы обучить модель с этим набором данных, вам понадобятся данные:
# Чтобы хорошо перетасовать.Для пакетирования.
# Партии должны быть доступны как можно скорее.
# Эти функции можно добавить с помощью 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")
# plt.show()
# Теперь вы вручную создали набор tf.data.Dataset, аналогичный тому, который
# был создан с помощью tf.keras.utils.image_dataset_from_directory выше.
# С ним вы можете продолжить обучение модели. Как и прежде, вы будете
# тренироваться всего несколько эпох, чтобы сократить время бега.
model.fit(
train_ds,
validation_data=val_ds,
epochs=3
)
# Поскольку ранее вы загрузили набор данных Flowers с диска,
# давайте теперь импортируем его с помощью наборов данных TensorFlow.
# Загрузите набор данных Flowers с помощью наборов данных 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)
# Получить изображение из набора данных.
get_label_name = metadata.features['label'].int2str
image, label = next(iter(train_ds))
_ = plt.imshow(image)
_ = plt.title(get_label_name(label))
plt.show()
References
https://www.tensorflow.org/tutorials/load_data/images