KerasCV
可以轻松组装最先进的工业级数据增强管道,用于图像分类和对象检测任务。KerasCV
提供了广泛的预处理层,可实现常见的数据增强技术。最有用的三个层是keras_cv.layers.CutMix、keras_cv.layers.MixUp
和keras_cv.layers.RandAugment
。这些层几乎用于所有图像分类流程。
包导入 && 数据加载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| import os import matplotlib.pyplot as plt import tensorflow as tf import tensorflow_datasets as tfds import keras import keras_cv
os.environ["KERAS_BACKEND"] = "jax"
BATCH_SIZE = 32 AUTOTUNE = tf.data.AUTOTUNE tfds.disable_progress_bar() data, dataset_info = tfds.load("oxford_flowers102", with_info=True, as_supervised=True) train_steps_per_epoch = dataset_info.splits["train"].num_examples // BATCH_SIZE val_steps_per_epoch = dataset_info.splits["test"].num_examples // BATCH_SIZE
IMAGE_SIZE = (224, 224) num_classes = dataset_info.features["label"].num_classes
def to_dict(image, label): image = tf.image.resize(image, IMAGE_SIZE) image = tf.cast(image, tf.float32) label = tf.one_hot(label, num_classes) return {"images": image, "labels": label}
def prepare_dataset(dataset, split): if split == "train": return ( dataset.shuffle(10 * BATCH_SIZE) .map(to_dict, num_parallel_calls=AUTOTUNE) .batch(BATCH_SIZE) ) if split == "test": return dataset.map(to_dict, num_parallel_calls=AUTOTUNE).batch(BATCH_SIZE)
def load_dataset(split="train"): dataset = data[split] return prepare_dataset(dataset, split)
train_dataset = load_dataset()
def visualize_dataset(dataset, title): plt.figure(figsize=(6, 6)).suptitle(title, fontsize=18) for i, samples in enumerate(iter(dataset.take(9))): images = samples["images"] plt.subplot(3, 3, i + 1) plt.imshow(images[0].numpy().astype("uint8")) plt.axis("off") plt.show()
visualize_dataset(train_dataset, title="Before Augmentation")
|
RandAugment
RandAugment
已被证明可以在众多数据集中提供改进的图像分类结果。它对图像执行一组标准的增强。KerasCV
提供了大量的数据增强层,其中最有用的三个层可能是RandAugment,CutMix,MixUp
。RandAugment选择一个随机操作。然后它对随机数进行采样,如果随机数小于速率参数,它将对给定图像应用随机操作。除了塑料参数值之外,值范围参数指定图像的值范围,每个图像的增强指定幅度和幅度stddev基本上决定了用于对每个数据增强进行采样的正态分布。应用RandAugment
之后你可以看到一些示例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| rand_augment = keras_cv.layers.RandAugment( value_range=(0, 255), augmentations_per_image=3, magnitude=0.3, magnitude_stddev=0.2, rate=1.0, )
def apply_rand_augment(inputs): inputs["images"] = rand_augment(inputs["images"]) return inputs
train_dataset = load_dataset().map(apply_rand_augment, num_parallel_calls=AUTOTUNE)
visualize_dataset(train_dataset, title="After RandAugment")
|
CutMix 和 MixUp
CutMix
和MixUp
是另外两个重要的增强操作。CutMix
随机剪切一张图像的一部分并将其放置在另一张图像上,MixUp
则在两幅图像之间插入像素值。这两者都可以防止模型过度拟合训练分布,并提高模型泛化的可能性。此外,CutMix
还可以防止您的模型过度依赖任何特定特征来进行分类。在下边的示例中,我们将在手动创建的预处理管道中独立使用CutMix
和MixUp
。在大多数最先进的管道中,图像是通过CutMix、MixUp
或两者都不随机增强。
1 2 3 4 5 6 7 8 9 10
| cut_mix = keras_cv.layers.CutMix() mix_up = keras_cv.layers.MixUp()
def cut_mix_and_mix_up(samples): samples = cut_mix(samples, training=True) samples = mix_up(samples, training=True) return samples
train_dataset = load_dataset().map(cut_mix_and_mix_up, num_parallel_calls=AUTOTUNE) visualize_dataset(train_dataset, title="After CutMix and MixUp")
|
定制增强管道
默写情况下你可能需要自定义它。例如,你想要排除某个增强或添加另一个增强,在这种情况下,你可以随机增强管道。随机增强管道是一个与RandAugment
类似的层但它可以灵活地自定义增强管道,例如我们在这里删除随机旋转层并在管道中添加网格遮罩层,现在我们可以应用定制的管道。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| layers = keras_cv.layers.RandAugment.get_standard_policy(value_range=(0, 255), magnitude=0.75, magnitude_stddev=0.3)
layers = [ layer for layer in layers if not isinstance(layer, keras_cv.layers.RandomRotation) ]
layers = layers + [keras_cv.layers.GridMask()]
pipeline = keras_cv.layers.RandomAugmentationPipeline( layers=layers, augmentations_per_image=3 )
def apply_pipeline(inputs): inputs["images"] = pipeline(inputs["images"]) return inputs
train_dataset = load_dataset().map(apply_pipeline, num_parallel_calls=AUTOTUNE) visualize_dataset(train_dataset, title="After custom pipeline")
|
正如您所看到的,没有图像被随机旋转。您可以根据需要自定义管道:
1 2 3 4 5 6 7 8 9
| pipeline = keras_cv.layers.RandomAugmentationPipeline( layers=[keras_cv.layers.GridMask(), keras_cv.layers.Grayscale(output_channels=3)], augmentations_per_image=1, )
train_dataset = load_dataset().map(apply_pipeline, num_parallel_calls=AUTOTUNE) visualize_dataset(train_dataset, title="After custom pipeline")
|
训练带有增强功能卷积神经网络(CNN)
我们将使用CutMix、MixUp
和RandAugment
在Oxford
花卉数据集上训练ResNet50
图像分类器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| def preprocess_for_model(inputs): images, labels = inputs["images"], inputs["labels"] images = tf.cast(images, tf.float32) return images, labels
train_dataset = ( load_dataset() .map(apply_rand_augment, num_parallel_calls=AUTOTUNE) .map(cut_mix_and_mix_up, num_parallel_calls=AUTOTUNE) )
visualize_dataset(train_dataset, "CutMix, MixUp and RandAugment")
train_dataset = train_dataset.map(preprocess_for_model, num_parallel_calls=AUTOTUNE) test_dataset = load_dataset(split="test").map(preprocess_for_model, num_parallel_calls=AUTOTUNE)
train_dataset = train_dataset.prefetch(AUTOTUNE) test_dataset = test_dataset.prefetch(AUTOTUNE)
def get_model(): model = keras_cv.models.ImageClassifier.from_preset("efficientnetv2_s", num_classes=num_classes) model.compile( loss=keras.losses.CategoricalCrossentropy(label_smoothing=0.1), optimizer=keras.optimizers.SGD(momentum=0.9), metrics=["accuracy"], ) return model
model = get_model() model.fit(train_dataset,epochs=1,validation_data=test_dataset,)
|
结论
这就是使用KerasCV
组装图像增强管道所需的全部!