subtitles/fr/74_debugging-the-training-pipeline-(tensorflow).srt (189 lines of code) (raw):
1
00:00:04,720 --> 00:00:09,280
Certains bogues dans votre code sont très simples. Vous essayez de l'exécuter,
2
00:00:09,280 --> 00:00:14,720
vous obtenez une erreur de syntaxe quelque part, Python vous indique exactement où et vous la corrigez. C'est
3
00:00:14,720 --> 00:00:22,240
génial : c'est simple et satisfaisant. Parfois, cependant, les choses se bloquent et l'erreur est impossible
4
00:00:22,240 --> 00:00:27,360
à comprendre. Cela se produit souvent en apprentissage automatique pour plusieurs raisons : vous travaillez avec
5
00:00:27,360 --> 00:00:33,920
des structures de données volumineuses, utilisez des bibliothèques volumineuses et complexes avec de nombreuses pièces mobiles, et vous faites également
6
00:00:33,920 --> 00:00:41,600
beaucoup de calcul GPU qui sont en génrénal les plus durs à corriger. Dans Keras, il y a le problème supplémentaire que vos modèles sont souvent compilés
7
00:00:41,600 --> 00:00:46,080
avant l'exécution, ce qui est excellent pour les performances mais rend leur débogage très difficile.
8
00:00:47,920 --> 00:00:56,160
Ce sera une vidéo sur ce qu'il faut faire lorsque vous rencontrez l'un de ces bugs cauchemardesques et avez aucune idée de comment les déboguer.
9
00:00:56,400 --> 00:01:07,600
Pour vous donner une idée des choses les plus courantes de ce qui peut mal tourner et où chercher la source des bogues que
10
00:01:07,600 --> 00:01:13,360
vous rencontrez, utilisons cet exemple de script. Je vais vous le montrer ici en deux parties. Tout d'abord,
11
00:01:13,360 --> 00:01:19,280
nous effectuons toutes nos importations, nous chargeons un jeu de données, nous créons notre tokenizer et nous tokenisons le jeu de données.
12
00:01:20,160 --> 00:01:28,320
Ensuite, nous convertissons nos jeux de données en jeux de données TensorFlow, c'est le `to_tf_dataset`, afin de pouvoir leur appliquer `fit()`,
13
00:01:28,320 --> 00:01:34,640
puis nous chargeons notre modèle à partir d'un checkpoint pré-entraîné, le compilons et pouvons appliquer `fit` sur le jeu de données. Cela semble
14
00:01:34,640 --> 00:01:42,880
assez simple, similaire à ce qu'on a vu dans le cours avant, mais attention ! Ce code effrayant cache de nombreux secrets sombres et mystérieux.
15
00:01:43,760 --> 00:01:52,880
Que se passe-t-il lorsque nous l'exécutons ? Eh bien, ce n'est pas génial. Nous obtenons ce message d'erreur. Qu'est-ce que cela signifie? Nous avons essayé de nous entraîner
16
00:01:52,880 --> 00:01:59,600
sur nos données, mais nous n'avons pas obtenu de gradient ? C'est assez déroutant. Comment pouvons-nous même commencer à déboguer
17
00:02:00,400 --> 00:02:04,880
quelque chose comme ça ? Lorsque l'erreur que vous obtenez ne suggère pas immédiatement où se situe le problème,
18
00:02:05,440 --> 00:02:11,040
la meilleure solution consiste souvent à parcourir les éléments dans l'ordre, en s'assurant à chaque étape
19
00:02:11,040 --> 00:02:19,120
que tout semble correct. Que tout est ok à ce point. Et bien sûr, le point de départ consiste toujours à vérifier vos données.
20
00:02:20,720 --> 00:02:28,960
La meilleure façon de le faire est de récupérer un batch à partir de `tf.data.Dataset` sur lequel votre modèle s'entraîne,
21
00:02:30,560 --> 00:02:41,840
juste à la fin du pipeline d'entraînement. Et si votre sortie est bonne, cela garanti que votre pipeline de données fonctionne bien. Et nous pouvons faire cela comme ça, en bouclant
22
00:02:41,840 --> 00:02:50,320
le jeu de données pendant une itération, puis en interrompant. Alors, qu'obtenons-nous lorsque nous inspectons ce batch ?
23
00:02:50,320 --> 00:02:54,800
Nous constatons que nous n'obtenons aucun gradient car nous ne transmettons pas d'étiquettes à Keras !
24
00:02:55,520 --> 00:03:00,800
Nos étiquettes se trouvent dans le batch, mais il s'agit d'une clé dans le dictionnaire d'entrée, et non d'une étiquette distincte.
25
00:03:02,400 --> 00:03:06,160
Il s'agit de l'un des problèmes les plus courants que vous rencontrerez lors de l'entraînement de vos transformers
26
00:03:06,160 --> 00:03:12,960
avec TensorFlow. Nos modèles peuvent tous calculer la perte en interne, mais pour utiliser cette perte pour l'entraînement,
27
00:03:12,960 --> 00:03:16,880
les étiquettes doivent être transmises dans le dictionnaire d'entrée, où le modèle peut les voir.
28
00:03:17,760 --> 00:03:23,200
Cette perte interne est la perte que nous utilisons lorsque nous ne spécifions pas de valeur de perte à `compile()`.
29
00:03:26,640 --> 00:03:30,960
Keras, d'autre part, s'attend généralement à ce que les étiquettes soient transmises séparément du
30
00:03:30,960 --> 00:03:36,720
dictionnaire d'entrée et qu'elles ne soient pas visibles par le modèle, et les calculs de perte échouent généralement si vous
31
00:03:36,720 --> 00:03:43,040
ne le faites pas. Nous devons choisir l'un ou l'autre. Soit nous utilisons la perte interne du modèle et conservons
32
00:03:43,040 --> 00:03:49,120
les étiquettes là où elles se trouvent, soit nous continuons à utiliser les pertes de Keras, mais nous déplaçons les étiquettes à l'endroit où Keras les
33
00:03:49,120 --> 00:03:57,680
attend. Pour plus de simplicité, utilisons les pertes internes du modèle, en supprimant l'argument
34
00:03:57,680 --> 00:04:06,000
de perte lors de l'appel de `compile()`. Donc que se passe-t-il si nous essayons ré-entraînons. Et bien nous recompilons en appelant `model.fit()` à nouveau.
35
00:04:06,560 --> 00:04:13,840
Que se passe t'il ? Eh bien, il fonctionne cette fois... mais maintenant nous obtenons une perte de `nan`. Ce n'est pas bon.
36
00:04:16,240 --> 00:04:22,160
`nan` signifique « not a number » et ce n'est pas une bonne perte à avoir en général. En fait, si nous inspectons notre modèle maintenant, nous verrons que non seulement toutes
37
00:04:22,160 --> 00:04:30,640
les sorties sont `nan` , mais que toutes les poids sont également `nan` comme pour la perte. Une fois qu'un seul `nan` se glisse dans vos calculs,
38
00:04:30,640 --> 00:04:37,280
il a tendance à se propager, car il se propage depuis la perte jusqu'à votre gradient
39
00:04:37,280 --> 00:04:48,320
puis dans les mises à jour de poids et donc à chaque mise à jour vous avez des `nan`. Donc `nan` détruit notre modèle. Mais où s'est-il glissé en premier ?
40
00:04:49,600 --> 00:04:57,760
Pour le savoir, nous devons réinitialiser le modèle et examiner les résultats du premier batch uniquement.
41
00:04:58,400 --> 00:05:04,160
Et lorsque nous faisons cela, nous voyons que `nan` apparaît d'abord dans la perte, mais seulement dans certains échantillons !
42
00:05:04,960 --> 00:05:08,480
Vous pouvez voir cela plus en détail dans la section du cours qui nous accompagneme, je vais très vite ici.
43
00:05:11,040 --> 00:05:17,120
Mais nous constatons que si nous regardons les étiquettes, les échantillons avec une perte de `nan` ont tous une étiquette de 2 !
44
00:05:17,760 --> 00:05:24,400
Cela nous donne un indice très fort. Si nous vérifions le modèle, avec `model.config.num_labels`, nous voyons que
45
00:05:24,400 --> 00:05:30,080
le modèle pense qu'il n'y a que 2 étiquettes, mais si nous voyons une valeur de 2, cela signifie qu'il y a au moins
46
00:05:30,080 --> 00:05:36,400
3 étiquettes, car 0 c'est aussi une étiquette ! Nous avons donc perdu `nan` parce que nous avons obtenu une étiquette impossible dans notre jeu de données
47
00:05:36,400 --> 00:05:43,040
Pour résoudre ce problème, nous devons revenir en arrière et configurer le modèle pour qu'il ait le bon nombre d'étiquettes.
48
00:05:43,680 --> 00:05:52,240
Nous pouvons définir `num_labels=3` lorsque nous initialisons le modèle avec `from_pretrained`. Alors maintenant, nous pensons que nos
49
00:05:52,240 --> 00:05:58,000
données sont bonnes et que notre modèle est bon, donc l'entraînement devrait fonctionner. Et si nous essayons d'exécuter `model.fit()`,
50
00:05:58,000 --> 00:06:07,600
nous obtenons... hmm. Nous obtenons une perte, c'est un nombre, cela diminue, mais cela ne diminue pas très rapidement. Et si nous continuons,
51
00:06:07,600 --> 00:06:13,600
nous constaterons que cela se fige à une valeur assez élevée. Que se passe-t-il ? Eh bien, lorsque les choses fonctionnent pour la
52
00:06:13,600 --> 00:06:19,280
plupart mais que l'entraînement est simplement lent, cela peut être un bon moment pour examiner votre optimiseur
53
00:06:19,280 --> 00:06:24,560
et les hyperparamètres d'entraînement. Et c'est là que je veux mentionner l'une des sources les plus courantes
54
00:06:24,560 --> 00:06:30,480
de problèmes lorsque vous travaillez avec Keras. Vous pouvez nommer des choses comme des optimiseurs avec des chaînes, Keras supporte ça et c'est très utile,
55
00:06:32,960 --> 00:06:37,680
mais si vous faites cela, toutes les options sont silencieusement définies sur leurs valeurs par défaut.
56
00:06:38,240 --> 00:06:43,920
Nous avons donc spécifié Adam comme optimiseur, mais au cours du processus, nous avons obtenu de manière invisible le taux d'apprentissage par défaut,
57
00:06:43,920 --> 00:06:51,440
qui est de 1e-3, soit 10 à la puissance moins 3. C'est bien trop élevé pour entraîner des transformers.
58
00:06:51,440 --> 00:06:59,120
Nous devrions revenir en arrière et spécifier directement le taux d'apprentissage sans utiliser une chaîne. Les bonnes valeurs se situent entre 1e-5
59
00:06:59,760 --> 00:07:06,800
et 1e-4. Séparons en deux et choisissons 5e-5. Et si vous recompilez avec cela,
60
00:07:06,800 --> 00:07:16,880
vous constaterez que l'entraînement fonctionne enfin. La perte diminue efficacement et converge vers une valeur basse. Encore une fois, je suis passé ici assez rapidement, et je vous
61
00:07:16,880 --> 00:07:20,720
recommande de consulter les notes de cours pour voir cela plus en détail et d'expérimenter
62
00:07:20,720 --> 00:07:28,840
le code vous-même pour regarder à quoi l'erreur ressemble et comment l'approcher.
63
00:07:20,720 --> 00:07:28,840
J'espère que cela vous a donné un bref résumé des bugs les plus fréquents et des approches de deboguage les plus fréquentes pour les résoudre. Bonne chance et n'oubliez pas de faire des pauses si votre code vous donne du fil à retordre !