简体   繁体   English

使用 TensorFlow-Keras API 进行数据增强

[英]Data Augmentation using TensorFlow-Keras API

The following code allows the images of a training set to be rotated 90º at the end of each epoch.以下代码允许在每个 epoch 结束时将训练集的图像旋转 90º。

from skimage.io import imread
from skimage.transform import resize, rotate
import numpy as np

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
from keras.utils import Sequence 
from keras.models import Sequential
from keras.layers import Conv2D, Activation, Flatten, Dense

# Model architecture  (dummy)
model = Sequential()
model.add(Conv2D(32, (3, 3), input_shape=(15, 15, 4)))
model.add(Activation('relu'))
model.add(Flatten())
model.add(Dense(1))
model.add(Activation('sigmoid'))
model.compile(loss='binary_crossentropy',
              optimizer='rmsprop',
              metrics=['accuracy'])

# Data iterator 
class CIFAR10Sequence(Sequence):
    def __init__(self, filenames, labels, batch_size):
        self.filenames, self.labels = filenames, labels
        self.batch_size = batch_size
        self.angles = [0,90,180,270]
        self.current_angle_idx = 0

    # Method to loop throught the available angles
    def change_angle(self):
      self.current_angle_idx += 1
      if self.current_angle_idx >= len(self.angles):
        self.current_angle_idx = 0
  
    def __len__(self):
        return int(np.ceil(len(self.filenames) / float(self.batch_size)))

    # read, resize and rotate the image and return a batch of images
    def __getitem__(self, idx):
        angle = self.angles[self.current_angle_idx]
        print (f"Rotating Angle: {angle}")

        batch_x = self.filenames[idx * self.batch_size:(idx + 1) * self.batch_size]
        batch_y = self.labels[idx * self.batch_size:(idx + 1) * self.batch_size]
        return np.array([
            rotate(resize(imread(filename), (15, 15)), angle)
               for filename in batch_x]), np.array(batch_y)

# Custom call back to hook into on epoch end
class CustomCallback(keras.callbacks.Callback):
    def __init__(self, sequence):
      self.sequence = sequence

    # after end of each epoch change the rotation for next epoch
    def on_epoch_end(self, epoch, logs=None):
      self.sequence.change_angle()               


# Create data reader
sequence = CIFAR10Sequence(["f1.PNG"]*10, [0, 1]*5, 8)
# fit the model and hook in the custom call back
model.fit(sequence, epochs=10, callbacks=[CustomCallback(sequence)])

How can I modify the code so that the rotations of the images occur during each epoch?如何修改代码以便在每个时期发生图像的旋转?

Desired output:期望的输出:

Epoch 1/10
Rotating Angle: 0
Rotating Angle: 90
Rotating Angle: 180
Rotating Angle: 270

Epoch 2/10
Rotating Angle: 0
Rotating Angle: 90
Rotating Angle: 180
Rotating Angle: 270

(...)

Epoch 10/10
Rotating Angle: 0
Rotating Angle: 90
Rotating Angle: 180
Rotating Angle: 270

In other words, how can I write a callback that runs on the "end" of an epoch that changes the angle value and continues training on the same epoch (without changing to the next one)?换句话说,我如何编写一个回调,该回调在一个时代的“结束”上运行,该回调改变了角度值并在同一时代继续训练(不更改到下一个)?

Thanks in Advance提前致谢

Note: The code credits are from 'mujjiga'.注意:代码来源来自“mujjiga”。

Since you have a custom sequence generator you can create a function that runs on either the start or end of an epoch.由于您有一个自定义序列生成器,因此您可以创建一个在 epoch 开始或结束时运行的函数。 That is where you can put your code to modify the images.这是您可以放置​​代码来修改图像的地方。 Documentation is [here.][1]文档在[这里][1]

Epoch-level methods (training only)
on_epoch_begin(self, epoch, logs=None)
Called at the beginning of an epoch during training.

on_epoch_end(self, epoch, logs=None)
Called at the end of an epoch during training.


  [1]: https://keras.io/guides/writing_your_own_callbacks/

There is no need to create a CustomCallback for this purpose;无需为此创建CustomCallback in the end, you want augmentation during the training.最后,您希望在训练期间进行扩充。

The solution is to apply the rotation operation with a probability解决方案是以概率应用旋转操作

# read, resize and rotate the image and return a batch of images
def __getitem__(self, idx):
    angle = self.angles[self.current_angle_idx]
    print(f"Rotating Angle: {angle}")
    batch_x = self.filenames[idx * self.batch_size:(idx + 1) * self.batch_size]
    batch_y = self.labels[idx * self.batch_size:(idx + 1) * self.batch_size]
    #These new lines (say we augment with probability > 0.5)
    #Number between 0 and 1
    images = []
    for filename in batch_x:
        probability = random.random()
        apply_rotate = probability > 0.5
        if apply_rotate:
            images.append(rotate(resize(imread(filename), (15, 15)), angle))
        else:
            images.append(resize(imread(filename), (15, 15)))
    return np.array(images), np.array(batch_y)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM