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.
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.
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.
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.
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.
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.
python -m pip install git+https://github.com/piyop/tfaug
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]]
"""
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)