Auteurs:
(1) Iason Ofeidis, Département de génie électrique et Yale Institute for Network Science, Yale University, New Haven {Contribution égale} ;
(2) Diego Kiedanski, Département de génie électrique et Yale Institute for Network Science, Yale University, New Haven {Contribution égale} ;
(3) Leandros TassiulasLevon Ghukasyan, Activeloop, Mountain View, Californie, États-Unis, Département de génie électrique et Yale Institute for Network Science, Yale University, New Haven.
Lors du processus de formation d'un modèle de Deep Learning, l'ensemble de données doit être lu depuis la mémoire et prétraité avant de pouvoir être transmis en entrée au modèle. Cette opération nécessite de charger les données en mémoire en une seule fois. Dans la plupart des cas, et en particulier avec des ensembles de données volumineux, un manque de mémoire se produit en raison de la quantité limitée de mémoire disponible dans le système, ce qui détériore également le temps de réponse du système. Ce goulot d'étranglement est souvent résolu dans les bibliothèques d'apprentissage profond en utilisant ce qu'on appelle un chargeur de données. Cette structure fournit un moyen de parcourir l'ensemble de données en tirant parti du traitement parallèle, de la prélecture, du traitement par lots et d'autres techniques pour réduire autant que possible le temps de chargement des données et la surcharge de mémoire (Paszke et al., 2019).
L'objectif principal d'un chargeur de données est d'effectuer les actions responsables du transfert des échantillons de données d'un emplacement de stockage vers la mémoire colocalisée avec les unités de traitement pour la formation afin de former un lot d'échantillons à introduire dans le modèle. Ces actions sont limitées par la bande passante du système de stockage et plus particulièrement par ses performances d'E/S. Ainsi, en fonction des spécifications matérielles du système, du système de fichiers qui le dessert et du débit de la liaison avec les unités informatiques, cela peut avoir une immense influence sur le temps total nécessaire pour terminer la formation.
La spécification suivante du composant dataloader est principalement axée sur PyTorch (torch.DataLoader() (PyTorch Core Team)), tandis que son homologue TensorFlow (tf.Dataset() (Abadi et al., 2015)), bien que ce ne soit pas la même chose, présente de grandes similitudes.
Lors de l'utilisation d'un chargeur de données, en plus de fournir l'ensemble de données en entrée, l'utilisateur a la possibilité de configurer un certain nombre d'hyperparamètres, adaptés à ses besoins et à ses ressources. Un élément commun disponible dans tous les chargeurs de données est la taille du lot, qui, comme mentionné précédemment, définit le nombre d'échantillons qui seront utilisés avant de mettre à jour les paramètres internes du modèle. Ce paramètre est intrinsèquement lié au concept de « mini-batch » dans la descente de gradient stochastique (Hinton et al., 2012) et c'est donc l'un des premiers paramètres qui fait généralement l'objet d'un réglage fin lorsqu'il faut obtenir de meilleurs résultats d'entraînement. .
Deuxièmement, l'utilisateur peut définir l'approche d'échantillonnage, qui détermine la stratégie pour extraire des échantillons de l'ensemble de données et les insérer dans un lot. Cela pourrait inclure la sélection d’échantillons sur la base de critères spécifiques, ainsi que d’une distribution de probabilité. Dans cette étape, il existe l'option de brassage, où les échantillons peuvent être réorganisés avant chaque itération de l'ensemble de données, le but étant généralement d'améliorer la généralisation du modèle de formation. Un autre paramètre est la fonction Collate/Padding, qui spécifie essentiellement le processus de liaison de tous les échantillons individuels à l'intérieur d'un lot (pensez à empiler des vecteurs dans un tenseur), afin de former un seul élément à alimenter en entrée du modèle de formation. . De plus, le chargeur de données peut être configuré pour stocker automatiquement les échantillons de données récupérés dans une mémoire épinglée (verrouillée par page), permettant ainsi un transfert de données plus rapide vers les appareils compatibles CUDA.
Les chargeurs de données sont livrés avec un composant appelé Workers, dont le but est d'optimiser ce processus de transfert de données. Les travailleurs sont définis comme des sous-processus chargés d'effectuer le chargement des données de manière asynchrone. Lors de la création d'une instance d'un chargeur de données, l'utilisateur a la possibilité de spécifier le nombre de travailleurs qui seront générés et qui contrôleront cette opération. Si le nombre de travailleurs est égal à zéro, aucun sous-processus ne sera créé, ce qui signifie que la récupération des données se produit de manière synchrone dans le même processus et que les unités de calcul (GPU) doivent donc attendre le chargement des données. à compléter (PyTorch Core Team). À l’inverse, des sous-processus seront générés égaux au nombre de travailleurs, ce qui évitera le blocage du code de calcul lors du chargement des données. Ceci est accompli en pré-récupérant les futurs lots à l'avance pour être prêts en cas de besoin.
Cet article est disponible sur arxiv sous licence CC 4.0.