web-dev-qa-db-fra.com

Augmentation des données Générateur de données d'images Segmentation sémantique Keras

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!

19
TSW

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)
14
Or Sharir

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)
13
Dennis Sakva