7.1 Introduction aux réseaux de neurones
Objectifs d'apprentissage
À la fin de cette section, vous devriez être en mesure de :
- 7.1.1 Définir les réseaux de neurones et discuter des types de problèmes pour lesquels ils peuvent être utiles.
- 7.1.2 Résumer le rôle des poids et des biais dans un réseau de neurones.
- 7.1.3 Construire un réseau de neurones simple.
Imaginez ce qui doit se passer dans le cerveau humain lorsqu'il est chargé de reconnaître des chiffres, compte tenu des multiples façons dont les chiffres de 0 à 9 peuvent être dessinés à la main. Les humains peuvent classer instantanément ces chiffres, et ce dès leur plus jeune âge. L'objectif des réseaux de neurones est de permettre à un algorithme informatique de classer ces chiffres aussi efficacement qu'un être humain.
Pour aller plus loin
Base de données MNIST
La base de données MNIST (Modified National Institute of Standards and Technology) est un vaste jeu de données de chiffres manuscrits fréquemment utilisé pour entraîner divers systèmes de traitement d'images et d'apprentissage automatique. Cette présentation vidéo par Michael Garris, chercheur principal, en fournit un aperçu. Vous pouvez télécharger directement les fichiers du jeu de données MNIST pour approfondir votre exploration.
Dans cette section, nous présentons des modèles simples de réseaux de neurones et découvrons leur fonctionnement. De nombreux détails techniques sont reportés aux sections ultérieures ou dépassent le cadre de cet ouvrage.
Qu'est-ce qu'un réseau de neurones ?
Un réseau de neurones (neural network) est une structure composée d'éléments appelés neurones (neurons), qui sont des unités décisionnelles individuelles recevant un certain nombre d'entrées et produisant une sortie , comme illustré à la Figure 7.2. La manière dont la sortie est déterminée par les entrées peut être très complexe. De plus, deux neurones distincts peuvent se comporter de manière tout à fait différente face aux mêmes entrées.
Le réseau de neurones lui-même peut être constitué de centaines, de milliers, voire de millions de neurones reliés les uns aux autres en couches, c'est-à-dire des groupes de neurones qui reçoivent tous les mêmes entrées des couches précédentes et transmettent des signaux de manière agrégée à la couche suivante. Il y a toujours au moins deux couches : la couche d'entrée (input layer) (qui contient les neurones recevant les données d'entrée initiales) et la couche de sortie (output layer) (qui contient les neurones utilisés pour interpréter la réponse ou fournir des informations de classification), ainsi qu'un certain nombre de couches cachées (hidden layers) (situées entre la couche d'entrée et la couche de sortie). La Figure 7.3 présente un schéma de réseau de neurones simple à titre de référence.
L'objectif principal d'un réseau de neurones est de classifier des données complexes. Les problèmes pour lesquels les réseaux de neurones sont particulièrement bien adaptés comprennent notamment :
- La reconnaissance d'images, y compris la reconnaissance faciale, l'identification de lettres et de symboles manuscrits, ainsi que la classification d'éléments d'images. Il s'agit d'un domaine d'innovation majeur, doté d'outils puissants tels que TensorFlow développé par Google et PyTorch développé par Meta.
- La reconnaissance vocale, comme le service Cloud Speech-to-Text de Google, qui offre une transcription précise de la parole et la traduction dans diverses langues.
- Les systèmes de recommandation, qui sont utilisés pour diffuser des publicités en ligne en fonction des habitudes de navigation de chaque utilisateur, ont été développés et utilisés par Amazon, Meta, Netflix et de nombreuses autres grandes entreprises pour cibler leurs marchés.
- La détection d'anomalies, développée pour faciliter la détection des fraudes, la sécurité des données et l'analyse/correction d'erreurs en repérant les valeurs aberrantes dans des jeux de données volumineux et complexes. On peut citer par exemple Azure Anomaly Detector de Microsoft, capable de détecter des anomalies dans des données de séries temporelles.
- Les véhicules autonomes et la robotique, notamment la technologie Autopilot de Tesla, occupent une place de plus en plus prépondérante à mesure que l'automatisation allège certaines tâches routinières du quotidien et améliore l'efficacité dans les entreprises, la fabrication et les transports.
- L'art génératif, qui comprend par exemple les arts visuels, la musique, la vidéo et la poésie, exploite d'immenses réserves de la création humaine pour produire des variations inédites.
- Le texte prédictif, y compris les modèles de traitement du langage naturel tels que ChatGPT (voir Réseaux de neurones convolutifs).
Pour aller plus loin
TensorFlow
Si vous souhaitez faire vos premiers pas avec les réseaux de neurones, découvrez cet outil interactif en ligne appelé TensorFlow Playground, qui utilise TensorFlow pour entraîner le modèle et mettre à jour les sorties en temps réel. Vous pouvez y choisir un jeu de données dans une liste, ajuster le nombre de couches cachées et de neurones par couche en cliquant sur les boutons plus (+) et moins (), et régler le taux d'apprentissage, le choix de la fonction d'activation ainsi que d'autres paramètres (des notions que nous approfondirons dans la suite de ce chapitre). Cliquez ensuite sur le bouton « lecture » pour lancer l'entraînement du modèle et observez la façon dont il apprend à classer les points du jeu de données choisi ! Si vous souhaitez recommencer, cliquez simplement sur « réinitialiser » pour repartir de zéro !
Neurones, poids, biais et fonctions d'activation
Le mode de fonctionnement des neurones (neurons) dans un réseau de neurones est supposé être similaire, ou analogue, à celui des neurones dans le cerveau. L'entrée du réseau de neurones est injectée dans les neurones de la couche d'entrée. Chaque neurone la traite ensuite et produit une sortie, qui est à son tour transmise aux neurones de la couche suivante. Les neurones individuels n'envoient de signaux, c'est-à-dire ne s'activent, que s'ils reçoivent l'entrée requise pour s'activer. (L'activation est le processus consistant à envoyer un signal de sortie après avoir reçu les signaux d'entrée appropriés.) Après avoir traversé un certain nombre de couches cachées, la sortie de la dernière couche cachée alimente la couche de sortie. Enfin, la sortie de cette couche finale est interprétée selon la nature du problème. S'il n'y a qu'un seul neurone de sortie, l'interprétation peut être vrai si ce neurone est activé ou faux dans le cas contraire. Pour les réseaux de neurones utilisés afin de classer des entrées dans différentes catégories (par exemple, la reconnaissance de chiffres), il y a généralement un neurone de sortie par classe. Celui qui est le plus activé indique la classification retenue, comme l'illustre la Figure 7.4.
Chaque connexion d'un neurone à un autre est associée à deux paramètres. Le poids (weight) est une valeur par laquelle est multiplié le signal entrant, ce qui détermine concrètement l'intensité de la connexion. Le biais (bias) est une valeur qui est ajoutée au signal pondéré, rendant le neurone plus susceptible (ou moins susceptible, si est négatif) de s'activer pour une entrée donnée. Les valeurs de et de peuvent être positives, négatives ou nulles. Une fois le poids et le biais appliqués, le résultat est passé dans une fonction d'activation (activation function), qui est une fonction non décroissante déterminant si le neurone s'active et, le cas échéant, avec quelle intensité. (Vous verrez cela plus loin à la Figure 7.6.)
Considérons le cas le plus simple qui soit : un neurone doté d'une entrée unique et d'une sortie . La circulation du signal à travers le neurone suit alors la formule . Par exemple, supposons que la valeur d'entrée soit , avec un poids et un biais . Le signal commence par être combiné sous la forme . Cette valeur est ensuite fournie en entrée à la fonction d'activation pour produire . Dans la section suivante, nous examinerons diverses fonctions d'activation utilisées dans les réseaux de neurones.
Lorsqu'il y a plusieurs entrées, , chacune est affectée par son propre poids. Généralement, le biais est considéré comme une propriété du neurone lui-même et influe donc de la même manière sur l'ensemble des entrées. Plus précisément, les entrées sont d'abord multipliées par leurs poids respectifs, le résultat est sommé, puis le biais est ajouté. Enfin, la fonction d'activation est appliquée pour obtenir le signal de sortie.
Les poids et les biais sont des paramètres que le réseau de neurones apprend au cours du processus d'entraînement, un sujet que nous expliquerons dans Rétropropagation.
Un réseau de neurones typique peut comporter des centaines ou des milliers d'entrées pour chaque neurone, ce qui rend l'équation difficile à manipuler sous cette forme. Il s'avère plus pratique de considérer l'ensemble des entrées comme les composantes d'une structure mathématique unique, appelée un vecteur (vector). Un vecteur est simplement une liste ordonnée de nombres, c'est-à-dire . (Remarque : dans cet ouvrage, nous utilisons des lettres en gras pour représenter les vecteurs. De plus, les composantes d'un vecteur sont indiquées entre parenthèses. Certains ouvrages utilisent des conventions de notation différentes.) Le nombre de composantes d'un vecteur est appelé sa dimension ; ainsi, par exemple, le vecteur est de dimension 5. Certaines opérations arithmétiques sont définies sur les vecteurs.
- Vectors of the same dimension can be added: If and , then .
- Any real number can be multiplied to a vector: .
- Le produit scalaire de deux vecteurs de même dimension donne un nombre réel (et non un vecteur) et se définit par :
Si les entrées et les poids sont considérés comme des vecteurs, respectivement et , la formule peut alors s'exprimer de manière plus concise par :
Par exemple, si , et , alors
Dans cet exemple, la sortie est donc , dont la valeur exacte dépend de la fonction d'activation choisie.
Types de fonctions d'activation
Les fonctions d'activation sont de plusieurs types. En voici quelques-unes parmi les plus courantes.
- Fonction en escalier (step function), . La valeur de sert de seuil. Le neurone ne s'active que lorsque l'entrée est au moins égale au paramètre .
- Fonction sigmoïde (sigmoid function), . Remarquez qu'il s'agit de la même fonction sigmoïde que celle utilisée dans la régression logistique (voir Classification à l'aide de l'apprentissage automatique). Les valeurs de sortie ont tendance à être proches de 0 lorsque est négatif et proches de 1 lorsque est positif, avec une transition progressive entre les deux.
- Fonction tangente hyperbolique (tanh) (hyperbolic tangent (tanh) function), . Les valeurs de sortie sont du même signe que , avec une transition continue par 0.
- Fonction unité linéaire rectifiée (ReLU) (rectified linear unit (ReLU) function), . La fonction ReLU vaut 0 pour les valeurs de négatives et est égale à l'entrée lorsque est positif.
- Fonction Leaky ReLU (leaky ReLU function), , pour un petit paramètre positif . La fonction Leaky ReLU se comporte de façon très proche de ReLU, sauf que les valeurs deviennent progressivement plus négatives lorsque devient plus négatif. Souvent, la valeur optimale du paramètre de « fuite » est déterminée pendant la phase d'entraînement.
- Fonction Softplus (softplus function), , qui est une version lissée de la fonction ReLU.
La Figure 7.5 montre les courbes des fonctions énumérées. Une caractéristique essentielle des fonctions d'activation est qu'elles sont non linéaires (nonlinear), ce qui signifie qu'elles ne sont pas de simples droites, .
Une autre fonction d'activation importante dans les réseaux de neurones, softmax, prend en entrée un vecteur de nombres réels et produit un vecteur de valeurs normalisées dans l'intervalle entre 0 et 1, que l'on peut interpréter comme une distribution de probabilité discrète. (Rappelez-vous, d'après Distributions de probabilité discrètes et continues, que les distributions de probabilité discrètes fournissent des mesures de probabilité ou de vraisemblance qu'un nombre fini de valeurs se réalisent.) La formule de softmax est :
où . Nous rencontrerons l'activation softmax dans un exemple de la section Rétropropagation.
Exemple 7.1
Problème
Un neurone simple possède quatre entrées, , et une sortie, . Les poids des quatre entrées sont , , et . Le biais du neurone est . Trouvez la sortie dans chacun des cas suivants.
- . Fonction d'activation : ReLU.
- . Fonction d'activation : sigmoïde.
- . Fonction d'activation : en escalier, .
- . Fonction d'activation : softplus.
Solution
Mise en place pour chaque cas :
- , puisque
- (Remarque : 0,32 a déjà été calculé au point a.)
- , puisque (Remarque : 0,32 a déjà été calculé au point a.)
Dans la section suivante, nous explorons les réseaux de neurones qui utilisent la plus simple des fonctions d'activation : la fonction en escalier.
Perceptrons
Bien que l'idée d'utiliser des structures calquées sur les neurones biologiques ait existé avant l'apparition de ce que nous considérons aujourd'hui comme des réseaux de neurones, une avancée majeure a eu lieu au milieu du XXe siècle. En 1957, Frank Rosenblatt a mis au point le perceptron, un type de réseau de neurones à une seule couche conçu pour les tâches de classification binaire — autrement dit, un réseau de neurones dont la sortie pouvait être « vrai » ou « faux » (voir la Figure 7.7). Après des succès initiaux, les progrès de l'IA ont été freinés par les capacités restreintes des programmes et le manque de puissance de calcul, entraînant une période de stagnation appelée « hiver de l'IA ». Malgré ces revers, de nouveaux développements sont apparus dans les années 1980, conduisant au perceptron multicouche (MLP) (multilayer perceptron (MLP)), qui constitue le paradigme fondamental des réseaux de neurones comportant plusieurs couches cachées.
Le perceptron monocouche apprend les poids au moyen d'une règle d'apprentissage simple, appelée règle d'apprentissage du perceptron.
- Initialiser les poids () et le biais () avec de petites valeurs aléatoires.
- Pour chaque entrée () de l'ensemble d'entraînement :
- Calculer les prédictions , où est la fonction en escalier,
- Calculer l'erreur , où est la valeur réelle ou souhaitée correspondant à . Notez que peut être positif ou négatif. Une valeur de positive implique que les poids et/ou le biais sont trop faibles et doivent être augmentés. Une valeur de négative implique le contraire.
- Mettre à jour les poids et les biais selon les formules suivantes, où est une petite constante positive contrôlant le taux d'apprentissage. Souvent, la modification des poids et des biais sera minime et ne produira pas immédiatement un impact important sur l'entrée. Cependant, au fil d'entraînements répétés, le perceptron va apprendre les valeurs appropriées de et de pour obtenir la sortie désirée.
Par exemple, supposons qu'un perceptron à trois entrées possède actuellement les poids et le biais . Pour l'entrée , on obtient :
Supposons que la sortie réelle aurait dû être . Il y a donc une erreur de . Si le taux d'apprentissage est , les poids et le biais seront alors mis à jour comme suit :
Pour la même entrée, le perceptron produit désormais la valeur :
Dans cet exemple simple, la valeur est passée de 1 à 0, éliminant ainsi l'erreur. Cependant, rien ne garantit que le perceptron classera toutes les entrées sans erreur, quel que soit le nombre d'étapes d'entraînement effectuées.
Exemple 7.2
Problème
Supposons que le point de données suivant dans l'ensemble d'entraînement soit , et que la classification correcte pour ce point soit . Avec les poids actuels et le biais , utilisez la règle d'apprentissage du perceptron avec pour mettre à jour les poids et le biais. Y a-t-il une amélioration dans la classification de ce point de données ?
Solution
Erreur : .
Nous obtenons à présent , ce qui classe toujours incorrectement le point comme 0 ; il n'y a donc pas d'amélioration de l'exactitude. (Néanmoins, l'argument a au moins augmenté, passant de à , ce qui montre qu'un certain progrès a été accompli lors de l'entraînement. En pratique, de nombreux cycles d'entraînement peuvent s'avérer nécessaires pour parvenir à des résultats précis, chaque cycle n'apportant qu'un progrès incrémentiel.)
Construire un réseau de neurones simple
Dans Qu'est-ce que la science des données ?, à l'Exemple 1.7, nous avons examiné le jeu de données Iris pour nous familiariser avec les formats et les structures de jeux de données. Dans cette section, nous utiliserons le jeu de données Iris, iris.csv, pour créer un réseau de neurones à quatre entrées et un neurone de sortie (pour l'essentiel, un perceptron simple) afin de classer les iris en setosa ou non setosa, en fonction de quatre caractéristiques : la longueur des sépales (SL), la largeur des sépales (SW), la longueur des pétales (PL) et la largeur des pétales (PW), toutes mesurées en centimètres. Le jeu de données Iris iris.csv contient 150 échantillons d'iris, répartis à raison de 50 pour chaque espèce : setosa, versicolor et virginica. Pour les besoins de cet exemple, les 100 premières lignes de données ont été sélectionnées pour l'entraînement et le test, en consacrant 75 % des données à l'entraînement et les 25 % restants au test. (Rappelez-vous, d'après Prise de décision à l'aide des bases de l'apprentissage automatique, qu'il est de bonne pratique d'utiliser environ 70 % à 80 % des données pour l'entraînement, le reste étant réservé au test.) Le réseau sera entraîné à l'aide de la règle d'apprentissage du perceptron, mais au lieu d'employer la fonction en escalier, la fonction d'activation sera la tangente hyperbolique, , choisie ici simplement à des fins d'illustration.
Le jeu de données des fleurs d'iris
La base de données Iris a été constituée et exploitée par sir R. A. Fisher dans son article de 1936 intitulé « The Use of Multiple Measurements in Taxonomic Problems ». Cet article est devenu une étude de référence sur l'utilisation des données multivariées dans les problèmes de classification, et il réapparaît fréquemment en science des données comme cas de test pratique pour les algorithmes d'apprentissage automatique et de réseaux de neurones.
Le modèle du réseau de neurones est illustré à la Figure 7.6.
The inputs will take the values of SL, SW, PL, and PW, respectively. There are four corresponding weights and one bias value , which are applied to the input layer values, and then the result is fed into the tanh function to obtain the output . Thus, the formula used to produce the predicted values, denoted by , is:
Dans ce modèle très simplifié, nous interprétons la valeur de comme suit :
- Si , classer l'entrée comme setosa.
- Si , classer l'entrée comme non setosa.
Pour mesurer l'erreur de classification, nous devons choisir des valeurs cibles concrètes auxquelles comparer nos sorties. Posons la valeur cible pour la classification setosa égale à , tandis que la cible pour la classification non setosa sera de . Ce choix est raisonnable puisque les valeurs de tendent vers lorsque tend vers l'infini positif et vers lorsque tend vers l'infini négatif.
Par exemple, si après l'entraînement, les poids idéaux obtenus sont et que le biais vaut , alors la réponse face à une entrée sera :
Comme , on classe l'entrée comme setosa. Bien entendu, la question naturelle qui se pose est : comment obtient-on ces valeurs particulières de poids et de biais au départ ? Cette tâche complexe convient parfaitement à un ordinateur. Nous allons utiliser Python pour entraîner le perceptron.
La bibliothèque Python sklearn.datasets dispose d'une fonction, load_iris, qui charge automatiquement le jeu de données Iris, ce qui vous évite d'importer le fichier iris.csv. Les autres modules importés depuis sklearn sont Perceptron, utilisé pour construire le modèle de perceptron, et train_test_split, utilisé pour diviser de manière aléatoire un jeu de données en un ensemble de test et un ensemble d'entraînement. Nous utiliserons ici une répartition de 75 % pour l'entraînement et 25 % pour le test, prise en charge par le paramètre test_size=0.25. Nous allons également renormaliser les données pour que toutes les caractéristiques contribuent équitablement au modèle. En Python, cela s'effectue au moyen de StandardScaler, qui renormalise les caractéristiques du jeu de données de telle sorte que la moyenne soit égale à 0 et l'écart type à 1. Enfin, accuracy_score sert à évaluer l'exactitude de la classification.
Code Python
# import the sklearn library (specific modules)
from sklearn.datasets import load_iris
from sklearn.linear_model import Perceptron
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import accuracy_score
# Load the Iris dataset
iris = load_iris()
X = iris.data[:100] # Only taking first 100 samples for binary classification
y = iris.target[:100] # "0 for setosa", 1 for "not setosa"
# Split the dataset into training and testing sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25)
# Standardize features by removing the mean and scaling to unit variance
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
# Initialize and train the perceptron
perceptron = Perceptron()
perceptron.fit(X_train_scaled, y_train)
# Make predictions on the test set
y_pred = perceptron.predict(X_test_scaled)
# Calculate accuracy
accuracy = accuracy_score(y_test, y_pred)
print("Accuracy:", accuracy)
La sortie obtenue se présentera sous cette forme :
Accuracy: 1.0
Comme le jeu de données était relativement restreint (100 lignes) et bien structuré, le modèle de perceptron a été capable de classifier les données avec une exactitude de 100 % (« Accuracy: 1.0 »). Dans des situations réelles, où les jeux de données sont plus vastes et moins réguliers, on ne peut pas s'attendre à une exactitude de 100 %. Le modèle pourrait également présenter un surapprentissage important, ce qui entraînerait une variance élevée lors de la classification de données n'appartenant pas au jeu de données initial.
Voici comment utiliser le modèle de perceptron que nous venons de créer pour classer de nouvelles données (extérieures au jeu de données d'origine) :
Code Python
# Assume you have new inputs stored in a variable called 'new_inputs'
new_inputs = [[5.1, 3.5, 1.4, 0.2], # Example input 1
[6.3, 2.9, 5.6, 1.8] # Example input 2
]
# Standardize the new inputs using the same scaler used for training
new_inputs_scaled = scaler.transform(new_inputs)
# Use the trained perceptron model to make predictions on the new inputs
predictions = perceptron.predict(new_inputs_scaled)
# Display the predictions
for i, prediction in enumerate(predictions):
print(f"Input {i+1} prediction: {'Setosa' if prediction == 0 else 'Not Setosa'}")
La sortie obtenue se présentera sous cette forme :
Input 1 prediction: Setosa
Input 2 prediction: Not Setosa