La quantification peut être définie comme le processus de mappage de valeurs d'un grand ensemble de nombres réels vers des valeurs d'un petit ensemble discret. En règle générale, cela implique de mapper des entrées continues sur des valeurs fixes en sortie. Une manière courante d’y parvenir consiste à arrondir ou à tronquer. En cas d'arrondi, on calcule l'entier le plus proche. Par exemple, une valeur de 1,8 devient 2. Mais une valeur de 1,2 devient 1. En cas de troncature, nous supprimons aveuglément les valeurs après la décimale pour convertir l'entrée en entier.
Quelle que soit la manière dont nous procédons, la principale motivation derrière la quantification des réseaux de neurones profonds est d'améliorer la vitesse d'inférence, car il va sans dire que l'inférence et la formation des réseaux de neurones sont assez coûteuses en termes de calcul. Avec l'avènement des grands modèles linguistiques , le nombre de paramètres dans ces modèles ne fait qu'augmenter, ce qui signifie que l'empreinte mémoire ne fait que devenir de plus en plus élevée.
Avec la vitesse à laquelle ces réseaux de neurones évoluent, il existe une demande croissante pour exécuter ces réseaux de neurones sur nos ordinateurs portables ou nos téléphones mobiles et même sur de petits appareils comme les montres. Rien de tout cela n’est possible sans quantification.
Avant de plonger dans la quantification, n'oublions pas que les réseaux de neurones entraînés sont de simples nombres flottants stockés dans la mémoire de l'ordinateur.
Certaines des représentations ou formats bien connus pour stocker des nombres dans les ordinateurs sont float32 ou FP32, float16 ou FP16, int8, bfloat16 où B signifie Google Brain ou plus récemment, tensor float 32 ou TF32, un format spécialisé pour la gestion des matrices ou des tenseurs. opérations. Chacun de ces formats consomme une partie différente de la mémoire. Par exemple, float32 alloue 1 bit pour le signe, 8 bits pour l'exposant et 23 bits pour la mantisse.
De même, float16 ou FP16 alloue 1 bit pour le signe mais seulement 5 bits pour l'exposant et 10 bits pour la mantisse. En revanche, BF16 alloue 8 bits pour l'exposant et seulement 7 bits pour la mantisse.
Assez de représentations. Ce que je veux dire, c'est que la conversion d'un format de mémoire supérieur vers un format de mémoire inférieur est appelée quantification. En termes d'apprentissage profond, Float32 est appelé simple ou pleine précision, et Float16 et BFloat16 sont appelés demi-précision . La manière par défaut avec laquelle les modèles d'apprentissage profond sont formés et stockés est en toute précision. La conversion la plus couramment utilisée est celle du format pleine précision vers un format int8.
La quantification peut être uniforme ou non uniforme . Dans le cas uniforme, le mappage de l'entrée à la sortie est une fonction linéaire résultant en des sorties uniformément espacées pour des entrées uniformément espacées. Dans le cas non uniforme, le mappage de l'entrée à la sortie est une fonction non linéaire, donc les sorties ne seront pas uniformément espacées pour une entrée uniforme.
En plongeant dans le type uniforme, la fonction de mappage linéaire peut être une opération de mise à l'échelle et d'arrondi. Ainsi, la quantification uniforme implique un facteur d'échelle, S dans l'équation.
Lors de la conversion de float16 en int8, notez que nous pouvons toujours nous limiter aux valeurs comprises entre -127 et plus 127 et garantir que le zéro de l'entrée correspond parfaitement au zéro de la sortie conduisant à un mappage symétrique et cette quantification est donc appelée symétrique. quantification .
Par contre si les valeurs de part et d'autre de zéro ne sont pas les mêmes par exemple entre -128 et +127. De plus, si nous mappons le zéro de l’entrée sur une autre valeur autre que zéro à la sortie, cela s’appelle une quantification asymétrique . Comme la valeur zéro est maintenant décalée dans la sortie, nous devons en tenir compte dans notre équation en incluant le facteur zéro, Z , dans l'équation.
Pour savoir comment choisir le facteur d'échelle et le point zéro, prenons un exemple d'entrée distribuée comme dans la figure ci-dessus dans l'axe des nombres réels. Le facteur d'échelle divise essentiellement toute cette plage d'entrée, de la valeur minimale r_min à la valeur maximale r_max, en partitions uniformes. Nous pouvons cependant choisir de découper cette entrée à un moment donné, par exemple alpha pour les valeurs négatives et bêta pour les valeurs positives. Toute valeur au-delà de alpha et bêta n’a pas de sens car elle correspond à la même sortie que celle d’alpha. Dans cet exemple, il s'agit de -127 et +127. Le processus de choix de ces valeurs de découpage alpha et bêta et donc de la plage de découpage est appelé calibrage .
Afin d'éviter un écrêtage excessif, l'option la plus simple pourrait être de définir alpha comme étant égal à r_min et beta comme étant égal à r_max. Et nous pouvons volontiers calculer le facteur d'échelle S , en utilisant ces valeurs r_min et r_max . Cependant, cela peut rendre la sortie asymétrique. Par exemple, r_max dans l'entrée pourrait être 1,5 mais r_min ne pourrait être que -1,2. Donc, pour limiter la quantification symétrique, nous avons besoin que alpha et bêta soient les valeurs maximales des deux et bien sûr, fixons le point zéro à 0.
La quantification symétrique est exactement ce qui est utilisé lors de la quantification des poids des réseaux neuronaux, car les poids entraînés sont déjà précalculés lors de l'inférence et ne changeront pas pendant l'inférence. Le calcul est également plus simple par rapport au cas asymétrique puisque le point zéro est fixé à 0.
Examinons maintenant un exemple dans lequel les entrées sont biaisées dans une direction, disons vers le côté positif. Cela ressemble au résultat de certaines des fonctions d'activation les plus réussies comme ReLU ou GeLU. De plus, les sorties des activations changent avec l'entrée. Par exemple, le résultat des fonctions d’activation est très différent lorsque nous montrons deux images d’un chat. La question est donc maintenant : « Quand allons-nous calibrer la plage de quantification ? » Est-ce pendant l'entraînement ? Ou pendant l'inférence et lorsque nous obtenons les données à des fins de prédiction ?
Cette question conduit à différents modes de quantification, notamment en Post Training Quantization (PTQ). Chez PTQ, nous commençons avec un modèle pré-entraîné sans effectuer de formation supplémentaire. Les données cruciales requises du modèle concernent les données d'étalonnage, qui sont utilisées pour calculer la plage de découpage, puis le facteur d'échelle (S) et le point zéro (Z). Généralement, ces données d'étalonnage sont dérivées des poids du modèle. Après le processus d'étalonnage, nous pouvons procéder à la quantification du modèle, ce qui donne le modèle quantifié.
Dans Quantization Aware Training ou QAT en abrégé, nous quantifions le modèle formé à l'aide d'une procédure standard, mais effectuons ensuite des ajustements ou un recyclage supplémentaires, en utilisant de nouvelles données de formation afin d'obtenir le modèle quantifié. QAT est généralement effectué pour ajuster le paramètre du modèle afin de récupérer la précision perdue ou toute autre métrique qui nous préoccupe lors de la quantification. Ainsi, QAT a tendance à fournir de meilleurs modèles que la quantification post-formation.
Afin de procéder à un réglage fin, le modèle doit être différentiable. Mais l’opération de quantification n’est pas différentiable. Pour surmonter ce problème, nous utilisons de faux quantificateurs tels que des estimateurs directs. Lors du réglage fin, ces estimateurs estiment l'erreur de quantification, et les erreurs sont combinées avec l'erreur d'apprentissage pour affiner le modèle et obtenir de meilleures performances. Lors du réglage fin, les passes avant et arrière sont effectuées sur le modèle quantifié en virgule flottante. Cependant, les paramètres sont quantifiés après chaque mise à jour du gradient.
Regardez la vidéo ci-dessous expliquant la quantification des modèles dans l'apprentissage profond
Cela couvre à peu près les bases de la quantification. Nous avons commencé par le besoin de quantification et les différents types de quantification tels que symétrique et asymétrique. Nous avons également rapidement appris comment choisir les paramètres de quantification, à savoir le facteur d’échelle et le point zéro. Et nous avons terminé avec différents modes de quantification. Mais comment tout cela est-il implémenté dans PyTorch ou TensorFlow ? C'est pour un autre jour. J'espère que cette vidéo vous a fourni un aperçu de la quantification dans le Deep Learning.
J'espère vous voir dans mon prochain. En attendant, prenez soin de vous !