[PYTHON] Étant donné que ImageDataGenerator ne peut plus être utilisé, une histoire sur la création d'une classe d'extension de données pour tensorflow> = 2.0

Contexte

Dans Tensorflow, ImageDataGenerator de Keras était souvent utilisé pour étendre les données d'image. Cela a été largement utilisé car il vous permet d'entraîner le modèle tensorflow tout en appliquant diverses extensions de données à l'image d'entrée dans un multi-processus.

Cependant, comme le multitraitement est obsolète depuis tensorflow 2.0, lors de l'apprentissage avec tensorflow tout en développant des données par traitement multi-processus, la barre de progression s'arrête sans générer soudainement une erreur. Ce qui est particulièrement douloureux, c'est que vous n'obtenez pas d'erreurs, donc si vous utilisez un service qui vous facture à l'heure, vous gaspillerez de l'argent même si l'apprentissage ne progresse pas ...: money_mouth:

J'ai utilisé un générateur qui apprend en lisant un fichier hdf5 qui a été divisé en plusieurs fichiers et je l'ai écrit dans un multi-processus, mais même avec tensorflow <2.0, si j'utilisais le multi-traitement, l'apprentissage pourrait s'arrêter dans environ 2 jours. Après tensorflow> = 2,0, il s'est arrêté encore plus fréquemment, par exemple, même pendant environ 2 heures.

Donc...

Comme ImageDataGenerator, nous avons créé une classe qui peut être facilement </ strong> apprise avec tensorflow tout en appliquant diverses extensions de données aux images dans un multi-processus.

politique

La méthode de saisie de données recommandée pour tensorflow consiste à utiliser tensorflow.data.Dataset (ci-après dénommé tf.data.Dataset). En utilisant cela, il est possible de créer un traitement d'entrée de données multi-processus à grande vitesse, par exemple, comme mentionné dans ici. Devenir. Cependant, tf.data n'a pas beaucoup d'informations dans le débordement de pile, etc., et bien qu'il y ait une écriture qui semble essayer chaque expansion de données, apprendre tout en étendant facilement diverses données à l'image d'entrée comme ImageDataGenerator Je n'ai pas trouvé le moyen de le faire ...

Vous pouvez utiliser tf.data pour créer un traitement de saisie rapide des données, mais la documentation officielle révèle quelques pièges.

1. tf.data.Dataset.from_generator n'étend pas les données dans plusieurs processus

Vous pouvez utiliser tf.data.Dataset.from_generator pour envelopper un générateur python et l'entraîner en tant que tf.data avec la fonction fit (). Tout d'abord, enveloppez ImageDataGenerator avec cette fonction! J'ai pensé facilement. Cependant, dans le Document officiel, Note de from_generator, il y a la description suivante.

Note: The current implementation of Dataset.from_generator() uses tf.numpy_function and inherits the same constraints. In particular, it requires the Dataset- and Iterator-related operations to be placed on a device in the same process as the Python program that called Dataset.from_generator(). The body of generator will not be serialized in a GraphDef, and you should not use this method if you need to serialize your model and restore it in a different environment.

En utilisant tf.numpy_function, j'ai abandonné car il ne prend pas en charge le multi-processus.

2. Implémentez avec tf autant que possible

Il est décrit dans document officiel tf.function, mais si vous le placez dans le décorateur @ tf.function pour les performances, tout le code est tf Sera automatiquement converti au code de. Si vous utilisez une bibliothèque externe ou numpy à ce moment-là, vous finirez par l'encapsuler dans tf.numpy_function, tf.py_func, etc., et vous vous retrouverez avec les mêmes restrictions que dans 1. Par conséquent, j'ai essayé d'utiliser le type tf.Tensor pour le traitement et le type de données autant que possible, et même si ce n'était pas le cas, j'ai essayé d'utiliser uniquement le type standard python.

3. Développez l'image de l'étiquette en même temps

Si l'image d'entrée est transformée par exemple par rotation, est-il nécessaire de transformer l'image qui est la source de l'étiquette exactement de la même manière? Je l'ai fait, j'ai donc essayé d'appliquer exactement les mêmes transformations à l'image d'étiquette (facultative) que l'image d'entrée.

Comment installer

python -m pip install git+https://github.com/piyop/tfaug

Comment utiliser

1. Initialisation

from tfaug import augment_img 
#set your augment parameters below:
arg_fun = augment_img(rotation=0, 
                      standardize=False,
                      random_flip_left_right=True,
                      random_flip_up_down=True, 
                      random_shift=(.1,.1), 
                      random_zoom=.1,
                      random_brightness=.2,
                      random_saturation=None,
                      training=True) 
                      
"""
augment_img.__init__() setting up the parameters for augmantation.

Parameters
----------
rotation : float, optional
    rotation angle(degree). The default is 0.
standardize : bool, optional
    image standardization. The default is True.
random_flip_left_right : bool, optional
    The default is False.
random_flip_up_down : bool, optional
    The default is False.
random_shift : Tuple[float, float], optional
    random shift images.
    vartical direction (-list[0], list[0])
    holizontal direction  (-list[1], list[1])
    Each values shows ratio of image size.
    The default is None.
random_zoom : float, optional
    random zoom range -random_zoom to random_zoom.
    value of random_zoom is ratio of image size
    The default is None.
random_brightness : float, optional
    randomely adjust image brightness range 
    [-max_delta, max_delta). 
     The default is None.
random_saturation : Tuple[float, float], optional
    randomely adjust image brightness range between [lower, upper]. 
    The default is None.
training : bool, optional
    If false, this class don't augment image except standardize. 
    The default is False.
Returns
-------
class instance : Callable[[tf.Tensor, tf.Tensor, bool], Tuple[tf.Tensor,tf.Tensor]]
"""                     

2. Utilisé dans tf.data.Dataset.map ()

ds=tf.data.Dataset.zip((tf.data.Dataset.from_tensor_slices(image),
                      tf.data.Dataset.from_tensor_slices(label))) \
                    .shuffle(BATCH_SIZE*10).batch(BATCH_SIZE)\
                    .map(arg_fun, num_parallel_calls=tf.data.experimental.AUTOTUNE)
model.fit(ds)

Voir test pour un exemple d'utilisation détaillé. (https://github.com/piyop/tfaug)

Recommended Posts

Étant donné que ImageDataGenerator ne peut plus être utilisé, une histoire sur la création d'une classe d'extension de données pour tensorflow> = 2.0
Lors du développement avec ipython, scrapy ne peut plus être lu
[2015.02.22] Youtube-dl a été mis à jour et ne peut plus être utilisé dans les versions précédentes.
le noyau du notebook jupyter ne peut plus se connecter
l'éclipse ne commence plus.
Étant donné que ImageDataGenerator ne peut plus être utilisé, une histoire sur la création d'une classe d'extension de données pour tensorflow> = 2.0
Que faire si Linux VLC ne peut plus tourner
Puis-je être un data scientist?
Je l'ai fait parce que je veux des données JSON qui peuvent être utilisées librement dans les démos et les prototypes
J'ai créé un modèle de projet Python générique
[Atcoder] [C ++] J'ai fait un outil d'automatisation de test qui peut être utilisé pendant le concours
J'ai créé un outil pour générer automatiquement un diagramme de transition d'état pouvant être utilisé à la fois pour le développement Web et le développement d'applications
J'ai fait un shuffle qui peut être réinitialisé (inversé) avec Python
[python] J'ai créé une classe qui peut écrire rapidement une arborescence de fichiers
J'ai écrit un tri-arbre qui peut être utilisé pour l'implémentation de dictionnaire à grande vitesse en langage D et Python
[Mise à jour Ver1.3.1] J'ai créé une bibliothèque de prétraitement de données DataLiner pour l'apprentissage automatique
J'ai fait une simple minuterie qui peut être démarrée depuis le terminal
J'ai créé un docset de tableau de bord pour Holoviews
J'ai fait une bibliothèque pour l'assurance actuarielle
Classe pour PYTHON qui peut être utilisée sans connaître LDAP
[2015.02.22] Youtube-dl a été mis à jour et ne peut plus être utilisé dans les versions précédentes.
J'ai créé un fichier de dictionnaire python pour Neocomplete
J'ai créé un outil utile pour Digital Ocean
J'ai créé un téléchargeur pour l'expression distribuée par mot
Nous avons créé un produit de prévention du télétravail.
Serveur de partage de fichiers réalisé avec Raspberry Pi pouvant être utilisé pour le travail à distance