Importance de buffer_size
dansshuffle()
Je voulais faire suite à la réponse précédente de @mrry pour souligner l' importance de buffer_size
in tf.data.Dataset.shuffle()
.
Avoir un faible buffer_size
ne vous donnera pas seulement un mélange inférieur dans certains cas: cela peut gâcher tout votre entraînement.
Un exemple pratique: classificateur de chat
Supposons par exemple que vous entraînez un classificateur de chat sur des images et que vos données sont organisées de la manière suivante (avec des 10000
images dans chaque catégorie):
train/
cat/
filename_00001.jpg
filename_00002.jpg
...
not_cat/
filename_10001.jpg
filename_10002.jpg
...
Un moyen standard de saisir des données avec tf.data
peut être d'avoir une liste de noms de fichiers et une liste d'étiquettes correspondantes, et d'utiliser tf.data.Dataset.from_tensor_slices()
pour créer l'ensemble de données:
filenames = ["filename_00001.jpg", "filename_00002.jpg", ...,
"filename_10001.jpg", "filename_10002.jpg", ...]
labels = [1, 1, ..., 0, 0...] # 1 for cat, 0 for not_cat
dataset = tf.data.Dataset.from_tensor_slices((filenames, labels))
dataset = dataset.shuffle(buffer_size=1000) # 1000 should be enough right?
dataset = dataset.map(...) # transform to images, preprocess, repeat, batch...
Le gros problème avec le code ci-dessus est que l'ensemble de données ne sera pas mélangé de la bonne manière. Pendant environ la première moitié d'une époque, nous ne verrons que des images de chats, et pour la seconde moitié uniquement des images non félines. Cela nuira beaucoup à l'entraînement.
Au début de la formation, l'ensemble de données prendra les premiers 1000
noms de fichiers et les mettra dans sa mémoire tampon, puis en choisira un au hasard parmi eux. Puisque toutes les premières 1000
images sont des images de chat, nous ne choisirons que des images de chat au début.
Le correctif ici est de s'assurer que buffer_size
c'est plus grand que 20000
, ou de mélanger à l'avance filenames
et labels
(avec les mêmes indices évidemment).
Étant donné que le stockage de tous les noms de fichiers et étiquettes en mémoire n'est pas un problème, nous pouvons en fait l'utiliser buffer_size = len(filenames)
pour nous assurer que tout sera mélangé ensemble. Assurez-vous d'appeler tf.data.Dataset.shuffle()
avant d'appliquer les transformations lourdes (comme la lecture des images, leur traitement, le traitement par lots ...).
dataset = tf.data.Dataset.from_tensor_slices((filenames, labels))
dataset = dataset.shuffle(buffer_size=len(filenames))
dataset = dataset.map(...) # transform to images, preprocess, repeat, batch...
La chose à retenir est de toujours vérifier ce que fera le brassage. Un bon moyen d'attraper ces erreurs pourrait être de tracer la distribution des lots au fil du temps (assurez-vous que les lots contiennent à peu près la même distribution que l'ensemble d'entraînement, moitié chat et moitié non chat dans notre exemple).