J'installe un réseau convolutionnel complet sur certaines données d'image pour la segmentation sémantique à l'aide de Keras. Cependant, j'ai des problèmes de sur-ajustement. Je n'ai pas beaucoup de données et je veux augmenter les données. Cependant, comme je souhaite effectuer une classification au niveau des pixels, j'ai besoin de toute augmentation, comme des flips, des rotations et des décalages, à appliquer à la fois aux images de fonction et aux images d'étiquette. Idéalement, j'aimerais utiliser Keras ImageDataGenerator pour des transformations à la volée. Cependant, pour autant que je sache, vous ne pouvez pas effectuer de transformations équivalentes sur les données d'entité et d'étiquette.
Est-ce que quelqu'un sait si c'est le cas et sinon, quelqu'un a-t-il des idées? Sinon, je vais utiliser d'autres outils pour créer un plus grand ensemble de données et le nourrir en une seule fois.
Merci!
Il y a des travaux pour étendre ImageDataGenerator pour être plus flexible pour exactement ce type de cas (voir dans ce problème sur Github pour des exemples).
De plus, comme mentionné par Mikael Rousson dans les commentaires, vous pouvez facilement créer votre propre version d'ImageDataGenerator vous-même, tout en tirant parti de plusieurs de ses fonctions intégrées pour le rendre plus facile. Voici un exemple de code que j'ai utilisé pour un problème de débruitage d'image, où j'utilise des recadrages aléatoires + du bruit additif pour générer des paires d'images propres et bruyantes à la volée. Vous pouvez facilement modifier cela pour ajouter d'autres types d'augmentations. Après quoi, vous pouvez utiliser Model.fit_generator pour vous entraîner à l'aide de ces méthodes.
from keras.preprocessing.image import load_img, img_to_array, list_pictures
def random_crop(image, crop_size):
height, width = image.shape[1:]
dy, dx = crop_size
if width < dx or height < dy:
return None
x = np.random.randint(0, width - dx + 1)
y = np.random.randint(0, height - dy + 1)
return image[:, y:(y+dy), x:(x+dx)]
def image_generator(list_of_files, crop_size, to_grayscale=True, scale=1, shift=0):
while True:
filename = np.random.choice(list_of_files)
try:
img = img_to_array(load_img(filename, to_grayscale))
except:
return
cropped_img = random_crop(img, crop_size)
if cropped_img is None:
continue
yield scale * cropped_img - shift
def corrupted_training_pair(images, sigma):
for img in images:
target = img
if sigma > 0:
source = img + np.random.normal(0, sigma, img.shape)/255.0
else:
source = img
yield (source, target)
def group_by_batch(dataset, batch_size):
while True:
try:
sources, targets = Zip(*[next(dataset) for i in xrange(batch_size)])
batch = (np.stack(sources), np.stack(targets))
yield batch
except:
return
def load_dataset(directory, crop_size, sigma, batch_size):
files = list_pictures(directory)
generator = image_generator(files, crop_size, scale=1/255.0, shift=0.5)
generator = corrupted_training_pair(generator, sigma)
generator = group_by_batch(generator, batch_size)
return generator
Vous pouvez ensuite utiliser ce qui précède comme ceci:
train_set = load_dataset('images/train', (patch_height, patch_width), noise_sigma, batch_size)
val_set = load_dataset('images/val', (patch_height, patch_width), noise_sigma, batch_size)
model.fit_generator(train_set, samples_per_Epoch=batch_size * 1000, nb_Epoch=nb_Epoch, validation_data=val_set, nb_val_samples=1000)
Oui, vous pouvez. Voici un exemple tiré des documents de Keras. Vous zippez deux générateurs ensemencés avec les mêmes graines et le fit_generator. https://keras.io/preprocessing/image/
# we create two instances with the same arguments
data_gen_args = dict(featurewise_center=True,
featurewise_std_normalization=True,
rotation_range=90.,
width_shift_range=0.1,
height_shift_range=0.1,
zoom_range=0.2)
image_datagen = ImageDataGenerator(**data_gen_args)
mask_datagen = ImageDataGenerator(**data_gen_args)
# Provide the same seed and keyword arguments to the fit and flow methods seed = 1
image_datagen.fit(images, augment=True, seed=seed)
mask_datagen.fit(masks, augment=True, seed=seed)
image_generator = image_datagen.flow_from_directory(
'data/images',
class_mode=None,
seed=seed)
mask_generator = mask_datagen.flow_from_directory(
'data/masks',
class_mode=None,
seed=seed)
# combine generators into one which yields image and masks
train_generator = Zip(image_generator, mask_generator)
model.fit_generator(
train_generator,
samples_per_Epoch=2000,
nb_Epoch=50)