VGG16 预处理数据集生成器到数据集映射
VGG16 preprocessing dataset generator to dataset mapping
我有一个使用 Keras/tensorflow 实现的 VGG16 模型。
当我调用 model.fit
时,我传入了一个数据生成器。生成器执行 VGGNet 所需的转换:
- 使用
vgg16.preprocess_input
预处理图像
- 通过
to_categorical
将标签转换为单热向量
发电机可以在下面看到并且可以工作。不幸的是,由于有多个纪元,我必须设置 dataset.repeat(-1)
(无限重复),这样生成器就不会 运行 了。这反过来又需要一个人通过 steps_per_epoch
以便完成给定的训练迭代。正如您可能在想的那样,这很脆弱,(取决于已知的数据集基数)!
我决定最好预先使用 Dataset.map
对训练 Dataset
进行一次预处理。但是,我正在努力构建映射函数,似乎 to_categorical
不适用于 tf.Tensor
。下面是我现在拥有的,但我不确定是否存在潜在错误。
如何正确地将下面的 Dataset
生成器转换为 Dataset.map
函数?
当前Dataset
发电机
这是通过 Python 3.8 和 tensorflow==2.4.4
实现的(并且已知可以工作)。
from typing import Iterable, Tuple
import numpy as np
import tensorflow as tf
def make_vgg_preprocessing_generator(
dataset: tf.data.Dataset, num_repeat: int = -1
) -> Iterable[Tuple[tf.Tensor, np.ndarray]]:
num_classes = len(dataset.class_names)
for batch_images, batch_labels in dataset.repeat(num_repeat):
pre_images = tf.keras.applications.vgg16.preprocess_input(batch_images)
pre_labels = tf.keras.utils.to_categorical(batch_labels, num_classes)
yield pre_images, pre_labels
train_ds: tf.data.Dataset # Not provided in this sample
model.fit(
make_vgg_preprocessing_generator(train_ds)
epochs=10,
steps_per_epoch=10, # Required since default num_repeat is indefinitely
)
Dataset.map
函数
这是我希望改进的当前翻译。
def vgg_preprocess_dataset(dataset: tf.data.Dataset) -> tf.data.Dataset:
num_classes = len(dataset.class_names)
def _preprocess(x: tf.Tensor, y: tf.Tensor) -> Tuple[tf.Tensor, tf.Tensor]:
pre_x = tf.keras.applications.vgg16.preprocess_input(x)
pre_y = tf.one_hot(y, depth=num_classes)
return pre_x, pre_y
return dataset.map(_preprocess)
是的,您走对了!您需要将 to_categorical
替换为 tf.one_hot
,就像您所做的那样,因为 tf.one_hot
专门用于张量,并且专为这种情况而设计。接下来,您可能想试用其他一些 tf.data.Dataset
方法 here 并将它们添加到您的管道中。现在,您的批量大小将是一个样本,un-shuffled。您可能会执行的一些其他处理的示例:
def vgg_preprocess_dataset(dataset: tf.data.Dataset, batch_size=32, shuffle_buffer=1000) -> tf.data.Dataset:
num_classes = len(dataset.class_names)
def _preprocess(x: tf.Tensor, y: tf.Tensor):
pre_x = tf.keras.applications.vgg16.preprocess_input(x)
pre_y = tf.one_hot(y, depth=num_classes)
# pre_y = to_categorical(y, num_classes)
return pre_x, pre_y
# bigger buffer is better but slower
dataset = dataset.shuffle(shuffle_buffer)
# do your mapping after shuffle
dataset = dataset.map(_preprocess)
# next batch it
dataset = dataset.batch(batch_size)
# this allows your CPU to fetch the next batch (do the above shuffling, mapping, etc) during the
# current GPU pass, so that the GPU has minimal downtime
dataset = dataset.prefetch(2)
return dataset
ds = vgg_preprocess_dataset(ds)
# and you just pass it right to fit!
model.fit(ds)
我有一个使用 Keras/tensorflow 实现的 VGG16 模型。
当我调用 model.fit
时,我传入了一个数据生成器。生成器执行 VGGNet 所需的转换:
- 使用
vgg16.preprocess_input
预处理图像
- 通过
to_categorical
将标签转换为单热向量
发电机可以在下面看到并且可以工作。不幸的是,由于有多个纪元,我必须设置 dataset.repeat(-1)
(无限重复),这样生成器就不会 运行 了。这反过来又需要一个人通过 steps_per_epoch
以便完成给定的训练迭代。正如您可能在想的那样,这很脆弱,(取决于已知的数据集基数)!
我决定最好预先使用 Dataset.map
对训练 Dataset
进行一次预处理。但是,我正在努力构建映射函数,似乎 to_categorical
不适用于 tf.Tensor
。下面是我现在拥有的,但我不确定是否存在潜在错误。
如何正确地将下面的 Dataset
生成器转换为 Dataset.map
函数?
当前Dataset
发电机
这是通过 Python 3.8 和 tensorflow==2.4.4
实现的(并且已知可以工作)。
from typing import Iterable, Tuple
import numpy as np
import tensorflow as tf
def make_vgg_preprocessing_generator(
dataset: tf.data.Dataset, num_repeat: int = -1
) -> Iterable[Tuple[tf.Tensor, np.ndarray]]:
num_classes = len(dataset.class_names)
for batch_images, batch_labels in dataset.repeat(num_repeat):
pre_images = tf.keras.applications.vgg16.preprocess_input(batch_images)
pre_labels = tf.keras.utils.to_categorical(batch_labels, num_classes)
yield pre_images, pre_labels
train_ds: tf.data.Dataset # Not provided in this sample
model.fit(
make_vgg_preprocessing_generator(train_ds)
epochs=10,
steps_per_epoch=10, # Required since default num_repeat is indefinitely
)
Dataset.map
函数
这是我希望改进的当前翻译。
def vgg_preprocess_dataset(dataset: tf.data.Dataset) -> tf.data.Dataset:
num_classes = len(dataset.class_names)
def _preprocess(x: tf.Tensor, y: tf.Tensor) -> Tuple[tf.Tensor, tf.Tensor]:
pre_x = tf.keras.applications.vgg16.preprocess_input(x)
pre_y = tf.one_hot(y, depth=num_classes)
return pre_x, pre_y
return dataset.map(_preprocess)
是的,您走对了!您需要将 to_categorical
替换为 tf.one_hot
,就像您所做的那样,因为 tf.one_hot
专门用于张量,并且专为这种情况而设计。接下来,您可能想试用其他一些 tf.data.Dataset
方法 here 并将它们添加到您的管道中。现在,您的批量大小将是一个样本,un-shuffled。您可能会执行的一些其他处理的示例:
def vgg_preprocess_dataset(dataset: tf.data.Dataset, batch_size=32, shuffle_buffer=1000) -> tf.data.Dataset:
num_classes = len(dataset.class_names)
def _preprocess(x: tf.Tensor, y: tf.Tensor):
pre_x = tf.keras.applications.vgg16.preprocess_input(x)
pre_y = tf.one_hot(y, depth=num_classes)
# pre_y = to_categorical(y, num_classes)
return pre_x, pre_y
# bigger buffer is better but slower
dataset = dataset.shuffle(shuffle_buffer)
# do your mapping after shuffle
dataset = dataset.map(_preprocess)
# next batch it
dataset = dataset.batch(batch_size)
# this allows your CPU to fetch the next batch (do the above shuffling, mapping, etc) during the
# current GPU pass, so that the GPU has minimal downtime
dataset = dataset.prefetch(2)
return dataset
ds = vgg_preprocess_dataset(ds)
# and you just pass it right to fit!
model.fit(ds)