Deep Learning: Des Perceptrons Aux Réseaux Profonds

0
3442
Deep Learning: Des Perceptrons Aux Réseaux Profonds

Ces dernières années, il y a eu une résurgence dans le domaine de l’intelligence artificielle. Il se propage au-delà du monde académique avec des acteurs majeurs comme Google, Microsoft et Facebook qui créent leurs propres équipes de recherche et réalisant des acquisitions impressionnantes.

Cela peut être attribué à l’abondance de données brutes générées par les utilisateurs de réseaux sociaux, dont la plupart doivent être analysées, ainsi qu’à la puissance de calcul disponible à bon marché via les GPGPU.

Mais au-delà de ces phénomènes, cette résurgence a été alimentée en grande partie par une nouvelle tendance dans AI (l’intelligence artificielle), en particulier dans machine learning (apprentissage automatique), connu sous le nom de « Deep Learning ».

(Les exemples de cet article sont implémentés en utilisant la bibliothèque bibliothèque d’apprentissage en profondeur Java. Les instructions d’utilisation sont disponibles sur la page d’accueil.)

Un tutoriel de trente secondes sur l’apprentissage automatique

Si vous n’êtes pas familier, consultez cette introduction à l’apprentissage automatique:

La procédure générale est la suivante:

  1. Nous avons un algorithme qui donne une poignée d’exemples étiquetés, disons 10 images de chiens avec le label 1 (« Dog ») et 10 images d’autres choses avec le label 0 (« Not dog »)—Notez que nous nous concentrons principalement dans cet article sur Machine Learning Supervisé et la classification binaire.
  2. L’algorithme « apprend » à identifier les images de chiens et, lorsqu’il est alimenté par une nouvelle image, espère produire l’étiquette correcte (1 si c’est une image d’un chien, et 0 autrement).

Ce paramètre est incroyablement général: vos données peuvent être des symptômes et vos étiquettes des maladies, ou juste des images de caractères manuscrits et vos étiquettes des caractères réels qu’ils représentent.

Perceptrons: premiers algorithmes de Deep Learning

L’un des premiers algorithmes d’entraînement supervisé est celui du perceptron, un bloc de base du réseau neuronal.

Disons que nous avons n points dans le plan, étiquetés ‘0’ et ‘1’. On nous donne un nouveau point et nous voulons deviner son étiquette (cela s’apparente au scénario « Chien » et « Pas chien » ci-dessus). Comment faisons-nous ça?

Une approche pourrait consister à regarder le voisin le plus proche et à renvoyer l’étiquette de ce point. Mais un moyen un peu plus intelligent de s’y prendre serait de choisir une ligne qui sépare le mieux les données étiquetées et l’utilise comme classificateur.

Deep Learning - Classificateur Linéaire
Image: Une représentation des données d’entrée par rapport à un classificateur linéaire est une approche fondamentale de Deep Learning (l’apprentissage en profondeur).

Dans ce cas, chaque donnée d’entrée serait représentée par un vecteur x = (x_1, x_2) et notre fonction serait quelque chose comme « ‘0’ si dessous la ligne, ‘1’ si dessus ».

Pour représenter cela mathématiquement, que notre séparateur soit défini par un vecteur de poids w et un décalage vertical (ou bias) b. Ensuite, notre fonction combinera les entrées et les poids avec une fonction de transfert de somme pondérée:

Deep Learning - Fonction F(x)

Le résultat de cette fonction de transfert serait alors introduit dans une fonction d’activation pour produire un étiquetage. Dans l’exemple ci-dessus, notre fonction d’activation était une coupure de seuil (par exemple, 1 si supérieure à une certaine valeur):

Deep Learning - fonction d'activation

Formation du Perceptron

La formation du perceptron consiste à lui donner plusieurs échantillons d’entraînement et à calculer le rendement de chacun d’entre eux. Après chaque échantillon, les poids w sont ajustés de manière à minimiser l’erreur de sortie, définie comme la différence entre les sorties souhaitées (cible) et les sorties réelles. Il existe d’autres fonctions d’erreur, comme l’ Erreur quadratique moyenne, mais le principe de base de l’entraînement reste le même.

Les Seuls Inconvénients Du Perceptron

L’approche perceptron unique à l’apprentissage en profondeur a un inconvénient majeur:il n’apprend que les fonctions linéairement séparables. Quelle est le degré de la gravité de cet inconvénient? Prenez XOR, une fonction relativement simple, et notez qu’il ne peut pas être classé par un séparateur linéaire (voir la tentative échouée ci-dessous):

Deep Learning - Inconvénients Du Perceptron

L’inconvénient de cette approche Deep Learning est que certaines fonctions ne peuvent pas être classées par un séparateur linéaire.

Pour résoudre ce problème, nous aurons besoin d’utiliser un perceptron multicouche, également connu sous le nom de réseau neuronal feedforward: en effet, nous allons composer un tas de ces perceptrons ensemble pour créer un mécanisme d’apprentissage plus puissant.

Réseau Neuronal De Propagation Vers l’Avant (Feedforward) Pour Le Deep Learning

Un réseau de neurones n’est en réalité qu’une composition de perceptrons, connectés de différentes manières et fonctionnant sur des fonctions d’activation différentes.

Deep Learning - Réseau FeedForward
image: L’apprentissage en profondeur du réseau neuronal de propagation vers l’avant (Feedforward) est une approche plus complexe que les perceptrons simples. caché

Pour commencer, nous regarderons le réseau de neurones de propagation vers l’avant (Feedforward), qui a les propriétés suivantes:

  • Une entrée, une sortie et un ou plusieurs calques cachés. La figure ci-dessus montre un réseau avec une couche d’entrée de 3 unités, une couche cachée de 4 unités et une couche de sortie avec 2 unités (les termes unités et neurones sont interchangeables).
  • Chaque unité est un perceptron unique comme celui décrit ci-dessus.
  • Les unités de la couche d’entrée servent d’entrées pour les unités de la couche cachée, tandis que les unités de couche cachées sont des entrées de la couche de sortie.
  • Chaque connexion entre deux neurones a un poids w (similaire aux poids perceptron).
  • Chaque unité de couche t est généralement connectée à chaque unité de la couche précédente t – 1 (bien que vous puissiez les déconnecter en réglant leur poids sur 0).
  • Pour traiter les données d’entrée, vous « fixez » le vecteur d’entrée à la couche d’entrée, en définissant les valeurs du vecteur comme « sorties » pour chacune des unités d’entrée. Dans ce cas particulier, le réseau peut traiter un vecteur d’entrée tridimensionnel (à cause des 3 unités d’entrée). Par exemple, si votre vecteur d’entrée est [7, 1, 2], vous devez définir la sortie de l’unité d’entrée supérieure sur 7, l’unité centrale sur 1, et ainsi de suite. Ces valeurs sont ensuite propagées vers les unités cachées en utilisant la fonction de transfert de somme pondérée pour chaque unité cachée (d’où le terme de Feedforward— propagation vers l’avant), qui à leur tour calculent leurs sorties (fonction d’activation).
  • La couche de sortie calcule ses sorties de la même manière que la couche cachée. Le résultat de la couche de sortie est la sortie du réseau.

Au-delà de la linéarité

Et si chacun de nos perceptrons est seulement autorisé à utiliser une fonction d’activation linéaire? Ensuite, la sortie finale de notre réseau sera toujours une fonction linéaire des entrées, juste ajustée avec une tonne de poids différents qu’il est collecté dans tout le réseau. En d’autres termes, une composition linéaire d’un groupe de fonctions linéaires n’est encore qu’une fonction linéaire. Si nous sommes limités aux fonctions d’activation linéaires, alors le réseau neuronal feedforward n’est pas plus puissant que le perceptron, peu importe combien de couches il a!

Une composition linéaire d’un groupe de fonctions linéaires n’est encore qu’une fonction linéaire, de sorte que la plupart des réseaux de neurones utilisent des fonctions d’activation non linéaires.

C’est pour cette raison que la plupart des réseaux de neurones utilisent des fonctions d’activation non linéaires comme la Logistic function (fonction logistique), la fonction hyperbolique, la fonction binaire ou la fonction rectifier. Sans eux, le réseau ne peut apprendre que des fonctions qui sont des combinaisons linéaires de ses entrées.

Perceptrons d’Entraînement

L’algorithme d’apprentissage en profondeur (deep learning) le plus courant pour l’entraînement supervisé des perceptrons multicouches est connu sous le nom de rétropropagation (backpropagation). La procédure de base:

  1. Un échantillon d’apprentissage est présenté et propagé (vers l’avant) à travers le réseau.
  2. L’erreur de sortie est calculée, généralement l’erreur quadratique moyenne:Deep Learning - erreur quadratique moyenneOù (t) est la valeur cible et (y) est la sortie réseau réelle. D’autres calculs d’erreur sont également acceptables, mais la MSE ( mean squared error, en français, erreur quadratique moyenne) est le bon choix.
  3. L’erreur de réseau est minimisée en utilisant une méthode appelée descente de gradient stochastiqueDeep Learning - Descente graduelle

La descente graduelle est universelle, mais dans le cas des réseaux de neurones, il s’agirait d’un graphique de l’erreur d’apprentissage en fonction des paramètres d’entrée. La valeur optimale pour chaque poids est celle à laquelle l’erreur atteint un minimum global. Pendant la phase d’entraînement, les poids sont mis à jour par petites étapes (après chaque échantillon d’entraînement ou un mini-lot de plusieurs échantillons) de telle sorte qu’ils essaient toujours d’atteindre le minimum global – mais ce n’est pas une tâche facile, se retrouvent souvent dans des minima locaux, comme celui de droite. Par exemple, si le poids a une valeur de 0,6, il doit être changé vers 0,4.

Cette figure représente le cas le plus simple, celui dans lequel l’erreur dépend d’un seul paramètre. Cependant, l’erreur de réseau dépend de chaque poids de réseau et la fonction d’erreur est beaucoup, beaucoup plus complexe.

Heureusement, la rétro-propagation fournit une méthode pour mettre à jour chaque poids entre deux neurones par rapport à l’erreur de sortie. La dérivation elle-même est assez compliquée, mais le poids mis à jour pour un nœud donné a la forme (simple) suivante:

Deep Learning - exemple de formulaire

E est l’erreur de sortie, et w_i est le poids de l’entrée i au neurone.

Essentiellement, le but est de se déplacer dans la direction du gradient par rapport au poids i. Le terme clé est, bien sûr, la dérivée de l’erreur, qui n’est pas toujours facile à calculer: comment trouveriez-vous cette dérivée pour un poids aléatoire d’un nœud caché aléatoire au milieu d’un grand réseau?

La réponse: par rétro-propagation. Les erreurs sont d’abord calculées aux unités de sortie où la formule est assez simple (basée sur la différence entre la cible et les valeurs prédites), puis propagées intelligemment dans le réseau, ce qui nous permet de mettre à jour efficacement nos poids pendant l’entraînement (espérons-le) atteindre un minimum.

Couche Cachée

La couche cachée est d’un intérêt particulier. Par le théorème d’approximation universel, un seul réseau de couches cachées avec un nombre fini de neurones peut être formé pour approcher une fonction aléatoire arbitraire. En d’autres termes, une seule couche cachée est assez puissante pour apprendre n’importe quelle fonction. Cela dit, nous apprenons souvent mieux en pratique avec plusieurs couches cachées (c.-à-d., Des réseaux plus profonds).

La couche cachée est l’endroit où le réseau stocke sa représentation abstraite interne des données d’apprentissage.

 

La couche cachée est l’endroit où le réseau stocke sa représentation abstraite interne des données d’apprentissage, de la même manière qu’un cerveau humain (analogie simplifiée) a une représentation interne du monde réel. Dans le tutoriel, nous verrons différentes manières de jouer avec la couche cachée.

Un Exemple De Réseau

Vous pouvez voir un Réseau neuronal de propagation (feedforward) simple (couche 4-2-3) qui classe le jeu de données IRIS implémenté en Java ici via la méthode testMLPSigmoidBP. L’ensemble de données contient trois classes de plantes à iris avec des caractéristiques telles que la longueur du sépale, la longueur des pétales, etc. Le réseau reçoit 50 échantillons par classe. Les entités sont bloquées sur les unités d’entrée, tandis que chaque unité de sortie correspond à une seule classe de l’ensemble de données: « 1/0/0 » indique que la plante est de classe Setosa, « 0/1/0″ indique Versicolour, et  » 0/0/1 « indique Virginica). L’erreur de classification est de 2/150 (c’est-à-dire qu’elle classe mal 2 échantillons sur 150).

Le Problème Avec Les Grands Réseaux

Un réseau de neurones peut avoir plus d’une couche cachée: dans ce cas, les couches supérieures « construisent » de nouvelles abstractions au-dessus des couches précédentes. Et comme nous l’avons déjà mentionné, vous pouvez souvent apprendre mieux dans la pratique avec des réseaux plus importants.

Toutefois, l’augmentation du nombre de couches cachées entraîne deux problèmes connus:

  1. Gradients disparaissant (Vanishing gradients): à mesure que nous ajoutons de plus en plus de couches cachées, la rétro-propagation devient de moins en moins utile pour transmettre des informations aux couches inférieures. En effet, lorsque l’information est renvoyée, les gradients commencent à disparaître et deviennent faibles par rapport aux poids des réseaux.
  2. Sur-apprentissage: peut-être le problème central de l’apprentissage automatique (machine learning). En bref, le sur-apprentissage décrit le phénomène d’ajustement trop serré des données d’apprentissage, peut-être avec des hypothèses trop complexes. Dans un tel cas, votre apprenant finit par bien adapter les données d’apprentissage, mais il fera beaucoup, beaucoup plus d’erreurs dans les exemples réels.

Regardons quelques algorithmes du deep learning (apprentissage en profondeur) pour résoudre ces problèmes.

Encodeurs Automatiques (Autoencoders)

La plupart des classes introductives à l’apprentissage automatique (machine learning) ont tendance à s’arrêter avec les réseaux neuronaux de propagation vers l’avant (feedforward). Mais l’espace des réseaux possibles est bien plus riche, alors continuons.

Un encodeurs automatique (autoencoder) est typiquement un réseau de neurones de propagation vers l’avant (feedforward) qui vise à apprendre une représentation (codage) compressée et distribuée d’un ensemble de données.

Deep Learning - Réseau Neuronal De Propagation Vers l'Avant

Conceptuellement, le réseau est formé pour « recréer » l’entrée, c’est-à-dire que l’entrée et les données cibles sont identiques. En d’autres termes: vous essayez de reproduire la même chose que vous avez saisie, mais compressée d’une manière ou d’une autre. C’est une approche déroutante, alors regardons un exemple.

Compression De l’Entrée: Images En Niveaux De Gris

Disons que les données d’apprentissage sont constituées d’images en niveaux de gris 28 x 28 et que la valeur de chaque pixel est fixée à un neurone de couche d’entrée (c’est-à-dire que la couche d’entrée aura 784 neurones). Ensuite, la couche de sortie aurait le même nombre d’unités (784) que la couche d’entrée et la valeur cible pour chaque unité de sortie serait la valeur d’échelle de gris d’un pixel de l’image.

L’intuition derrière cette architecture est que le réseau n’apprendra pas une «cartographie» entre les données d’apprentissage et ses étiquettes, mais apprendra plutôt la structure interne et les caractéristiques des données elles-mêmes. (De ce fait, la couche cachée est également appelée détecteur de caractéristiques.) Habituellement, le nombre d’unités cachées est plus petit que les couches d’entrée / sortie, ce qui oblige le réseau à apprendre uniquement les fonctions les plus importantes et à réduire la dimension.

Nous voulons que quelques petits nœuds au milieu apprennent les données à un niveau conceptuel, produisant une représentation compacte.

En effet, nous voulons que quelques petits nœuds au milieu apprennent vraiment les données à un niveau conceptuel, produisant une représentation compacte qui, d’une certaine manière, capture les caractéristiques fondamentales de notre contribution.

Maladie De La Grippe

Pour continuer à démontrer les encodeurs automatiques (autoencoders), regardons une autre application.

Dans ce cas, nous utiliserons un ensemble de données simple constitué de symptômes de la grippe (crédit à ce poste de blog pour l’idée). Si vous êtes intéressé, le code de cet exemple peut être trouvé dans la méthode testAEBackpropagation.

Voici comment l’ensemble de données se décompose:

  • Il y a six fonctions d’entrée binaires.
  • Les trois premiers sont des symptômes de la maladie. Par exemple, 1 0 0 0 0 0 indique que ce patient a une température élevée, tandis que 0 1 0 0 0 0 indique une toux, 1 1 0 0 0 0 indique une toux et une température élevée, etc.
  • Les trois dernières caractéristiques sont des symptômes « contre »; Quand un patient en a un, il est moins probable qu’il ou elle soit malade. Par exemple, 0 0 0 1 0 0 indique que ce patient a un vaccin antigrippal. Il est possible d’avoir des combinaisons des deux ensembles de caractéristiques: 0 1 0 1 0 0 indique un patient vacciné avec une toux, etc.

    Nous considérons qu’un patient est malade quand il ou elle a au moins deux des trois premières caractéristiques et qu’il est en bonne  santé s’il a au moins deux des trois autres (avec des liens rompant en faveur des patients en bonne santé), par exemple:

    • 111000, 101000, 110000, 011000, 011100 = malade
    • 000111, 001110, 000101, 000011, 000110 = sain

Nous allons former un autoencoder (en utilisant la rétro-propagation) avec six unités d’entrée et six unités de sortie, mais seulement deux unités cachées.

Après plusieurs centaines d’itérations, on observe que lorsque chacun des échantillons « malades » est présenté au réseau d’apprentissage automatique, l’une des deux unités cachées (la même unité pour chaque échantillon « malade ») présente toujours une valeur d’activation supérieure à l’autre. Au contraire, lorsque l’échantillon « sain » est présenté, l’autre unité cachée a une activation plus élevée.

Retour à l’apprentissage automatique

Essentiellement, nos deux unités cachées ont appris une représentation compacte de l’ensemble de données sur les symptômes de la grippe. Pour voir comment cela se rapporte à l’apprentissage, nous revenons au problème du sur-apprentissage. En formant notre réseau pour apprendre une représentation compacte des données, nous privilégions une représentation plus simple plutôt qu’une hypothèse très complexe qui surclasse les données d’apprentissage.

D’une certaine manière, en favorisant ces représentations plus simples, nous essayons d’apprendre les données dans un sens plus vrai.

Machines De Boltzmann Restreintes

La prochaine étape logique est de regarder la machines Boltzmann restreintes (RBM), un réseau neuronal stochastique génératif qui peut apprendre une distribution de probabilité sur son ensemble d’entrées.

Deep Learning - Machines De Boltzmann Restreintes RBM

Les RBM sont composés d’une couche cachée, visible et biaisée. Contrairement aux réseaux feedforward, les connexions entre les couches visible et cachée ne sont pas dirigées (les valeurs peuvent être propagées dans les directions visibles-cachées et cachées-visibles) et entièrement connectées (chaque unité d’une couche donnée est connectée à chaque unité de la suivante – si nous permettons à une unité de n’importe quelle couche de se connecter à une autre couche, alors nous aurions une machine Boltzmann (plutôt qu’une machine de Boltzmann restreinte). 

Le RBM standard a des unités binaires cachées et visibles: c’est-à-dire que l’activation de l’unité est 0 ou 1 sous une distribution de Bernoulli, mais il existe des variantes avec d’autres non-linéarités.

Alors que les chercheurs connaissent les mécanismes de gestion axée sur les résultats depuis un certain temps, l’introduction récente de l’algorithme d’apprentissage non supervisé par divergence contrastive a suscité un regain d’intérêt.

Divergence Contrastive

L’algorithme de divergence contrastive à une seule étape (CD-1) fonctionne comme ceci:

  1. Phase Positive:

    • Un échantillon d’entrée v est serré sur la couche d’entrée.
    • v est propagé à la couche cachée de manière similaire aux réseaux feedforward. Le résultat des activations de couches cachées est h.
  2. Phase Negative :

    • Propagez h vers la couche visible avec le résultat v’ (les connexions entre les couches visibles et cachés ne sont pas dirigées et permettent donc un mouvement dans les deux sens).
    • Propager le nouveau v ‘retour à la couche cachée avec les activations résultat h‘.
  3. Mise à jour de poids:Deep Learning - Mise à jours

 

a est le taux d’apprentissage et v, v ‘, h, h’ et w sont des vecteurs.

L’intuition derrière l’algorithme est que la phase positive (h donné v) reflète la représentation interne du réseau des données du monde réel. Pendant ce temps, la phase négative représente une tentative de recréer les données basées sur cette représentation interne (v ‘donné h). L’objectif principal est que les données générées soient aussi proches que possible du monde réel et cela se reflète dans la formule de mise à jour des poids.

En d’autres termes, le réseau a une certaine perception de la façon dont les données d’entrée peuvent être représentées, de sorte qu’il essaie de reproduire les données basées sur cette perception. Si sa reproduction n’est pas assez proche de la réalité, elle fait un ajustement et essaie à nouveau.

Retournons à La Grippe

Pour démontrer la divergence contrastive, nous utiliserons le même ensemble de données sur les symptômes que précédemment. Le réseau de test est un RBM avec six unités visibles et deux unités cachées. Nous allons former le réseau en utilisant la divergence contrastive avec les symptômes v attachés à la couche visible. Pendant le test, les symptômes sont à nouveau présentés à la couche visible; ensuite, les données sont propagées à la couche cachée. Les unités cachées représentent l’état malade/sain, une architecture très similaire à l’autoencoder (propagation des données de la couche visible à la couche cachée).

Après plusieurs centaines d’itérations, on peut observer le même résultat qu’avec les auto-encodeurs: une des unités cachées a une valeur d’activation plus élevée lorsque l’un des échantillons « malades » est présenté, tandis que l’autre est toujours plus actif pour les échantillons « sains ».

Deep Networks (Réseaux Profonds)

Nous avons maintenant démontré que les couches cachées des auto-encodeurs et des RBM agissent comme des détecteurs de fonctionnalités efficaces; mais il est rare que nous puissions utiliser ces fonctionnalités directement. En fait, l’ensemble de données ci-dessus est plus une exception qu’une règle. Au lieu de cela, nous devons trouver un moyen d’utiliser indirectement ces fonctionnalités détectées.

Heureusement, il a été découvert que ces structures peuvent être empilées pour former des réseaux profonds. Ces réseaux peuvent être formés avec avidité, une couche à la fois, pour aider à surmonter le gradient de fuite et les problèmes de sur-adaptation associés à la rétro-propagation classique.

Les structures résultantes sont souvent assez puissantes, produisant des résultats impressionnants. Prenez, par exemple, le fameux papier « chat » de Google dans lequel ils utilisent un type spécial d’auto-encodeurs profonds pour « apprendre » la détection de visage humain et de chat à partir de données non marquées.

Regardons de plus près.

Encodeurs Automatiques Empilés

Comme son nom l’indique, ce réseau se compose de plusieurs auto-encodeurs empilés.

Deep Learning - Auto-Encodeurs Empilés

La couche cachée de l’autoencoder t agit comme une couche d’entrée pour l’autoencoder t + 1. La couche d’entrée du premier autoencoder est la couche d’entrée pour l’ensemble du réseau. La procédure d’apprentissage par couche gourmande fonctionne comme ceci:

  1. Entraînez le premier auto-encodeur (t = 1, ou les connexions rouges dans la figure ci-dessus, mais avec une couche de sortie supplémentaire) individuellement en utilisant la méthode de rétro-propagation avec toutes les données d’entraînement disponibles.
  2. Entraînez le second autoencoder t = 2 (connexions vertes). Puisque la couche d’entrée pour t = 2 est la couche cachée de t = 1, nous ne sommes plus intéressés par la couche de sortie de t = 1 et nous l’enlevons du réseau. L’apprentissage commence en serrant un échantillon d’entrée dans la couche d’entrée de t = 1, qui se propage vers la couche de sortie de t = 2. Ensuite, les poids (input-hidden et hidden-output) de t = 2 sont mis à jour en utilisant backpropagation. t = 2 utilise tous les échantillons d’apprentissage, similaires à t = 1.
  3. Répétez la procédure précédente pour toutes les couches (c.-à-d., Supprimez la couche de sortie du codeur automatique précédent, remplacez-la par un autre auto-encodeur et entraînez-vous avec la rétro-propagation).
  4. Les étapes 1-3 sont appelées pré-entraînement et laissent les poids correctement initialisés. Cependant, il n’y a pas de correspondance entre les données d’entrée et les étiquettes de sortie. Par exemple, si le réseau est entraîné à reconnaître des images de chiffres manuscrits, il n’est toujours pas possible de mapper les unités du dernier détecteur de caractéristiques (c’est-à-dire la couche cachée du dernier encodeur automatique) au type de chiffres de l’image. Dans ce cas, la solution la plus courante consiste à ajouter une ou plusieurs couche (s) entièrement connectée (s) à la dernière couche (connexions bleues). Le réseau entier peut maintenant être vu comme un perceptron multicouche et est entraîné en utilisant la rétro-propagation (cette étape est également appelée réglage fin).

Les encodeurs automatiques empilés ont donc pour but de fournir une méthode de pré-entraînement efficace pour initialiser les poids d’un réseau, vous laissant avec un perceptron complexe et multicouche prêt à s’entraîner (ou à affiner).

Réseaux De Croyances Profondes

Comme avec les auto-encodeurs, nous pouvons également empiler des machines Boltzmann pour créer une classe connue sous le nom de réseaux de croyances profondes (DBN).

Deep Learning - Réseaux De Croyances Profondes

Dans ce cas, la couche cachée de RBM t agit comme une couche visible pour RBM t + 1. La couche d’entrée du premier RBM est la couche d’entrée pour l’ensemble du réseau, et la pré-formation glouton par couche fonctionne comme ceci:

  1. Entraînez le premier RBM t = 1 en utilisant la divergence contrastive avec tous les échantillons d’entraînement.
  2. Entraînez le deuxième RBM t = 2. Puisque la couche visible pour t = 2 est la couche cachée de t = 1, l’entraînement commence en serrant l’échantillon d’entrée sur la couche visible de t = 1, qui se propage vers la couche cachée de t = 1. Ces données servent ensuite à initier une formation de divergence contrastive pour t = 2.
  3. Répétez la procédure précédente pour toutes les couches
  4. Tout comme les auto-encodeurs empilés, après la pré-formation, le réseau peut être étendu en connectant une ou plusieurs couches entièrement connectées à la couche masquée RBM finale. Cela forme un perceptron multicouche qui peut ensuite être affiné en utilisant la rétro-propagation.

Cette procédure s’apparente à celle des auto-encodeurs empilés, mais avec les auto-encodeurs remplacés par des RBM et la rétro-propagation remplacée par l’algorithme de divergence contrastive.

(Remarque: pour en savoir plus sur la construction et l’entraînement des auto-encodeurs empilés ou des réseaux de croyances profondes, consultez l’exemple de code ici.)

Réseaux Convolutifs

En tant que dernière architecture du deep learning (apprentissage en profondeur), jetons un coup d’œil aux réseaux convolutifs, une classe particulièrement intéressante et spéciale de réseaux de feedforward qui sont très bien adaptés à la reconnaissance d’images.

Deep Learning - Réseaux Convolutifs

Avant de regarder la structure réelle des réseaux convolutifs, nous définissons d’abord un filtre d’image, ou une région carrée avec des poids associés. Un filtre est appliqué sur une image d’entrée entière et vous appliquerez souvent plusieurs filtres. Par exemple, vous pouvez appliquer quatre filtres 6×6 à une image d’entrée donnée. Ensuite, le pixel de sortie avec les coordonnées 1,1 est la somme pondérée d’un carré 6×6 de pixels d’entrée avec le coin supérieur gauche 1,1 et les poids du filtre (qui est également carré 6×6). Le pixel de sortie 2,1 est le résultat du carré d’entrée avec le coin supérieur gauche 2,1 et ainsi de suite.

Avec cela couvert, ces réseaux sont définis par les propriétés suivantes:

  • Les couches convolutives appliquent un certain nombre de filtres à l’entrée. Par exemple, la première couche convolutive de l’image pourrait avoir quatre filtres 6×6. Le résultat d’un filtre appliqué à travers l’image est appelé carte d’entités (FM) et les cartes d’entités numériques sont égales au nombre de filtres. Si la couche précédente est également convolutive, les filtres sont appliqués sur l’ensemble de ses FM avec des poids différents, de sorte que chaque entrée FM est connectée à chaque sortie FM. L’intuition derrière les poids partagés à travers l’image est que les caractéristiques seront détectées indépendamment de leur emplacement, tandis que la multiplicité des filtres permet à chacun d’eux de détecter différents ensembles de caractéristiques.
  • Les couches de sous-échantillonnage réduisent la taille de l’entrée. Par exemple, si l’entrée est constituée d’une image 32×32 et que la couche a une sous-sous-échantillonnage de 2×2, la valeur de sortie sera une image 16×16, ce qui signifie que 4 pixels (chaque 2×2 carré) sont combinés en une seule sortie pixel. Il existe plusieurs façons de sous-échantillonner, mais les plus populaires sont le regroupement maximal, le regroupement moyen et le regroupement stochastique.

Vous pouvez voir plusieurs exemples de réseaux convolutifs formés (avec rétropropagation) sur l’ensemble de données MNIST (images en niveaux de gris de lettres manuscrites) ici, spécifiquement dans les méthodes testLeNet * (je recommanderais testLeNetTiny2 car il atteint un faible taux d’erreur d’environ 2% dans une période relativement courte). Il y a aussi une bonne visualisation JavaScript d’un réseau similaire ici.

Implémentation

Maintenant que nous avons couvert les variantes de réseau de neurones les plus courantes, j’ai pensé écrire un peu sur les défis posés lors de la mise en œuvre de ces structures d’apprentissage en profondeur.

De manière générale, mon but dans la création d’une bibliothèque Deep Learning était (et est toujours) de construire un cadre basé sur un réseau de neurones répondant aux critères suivants:

  • Une architecture commune capable de représenter divers modèles (toutes les variantes sur les réseaux de neurones que nous avons vues plus haut, par exemple).
  • La possibilité d’utiliser divers algorithmes d’entraînement (rétro-propagation, divergence contrastive, etc.).
  • Performance décente.

Pour satisfaire ces exigences, j’ai adopté une approche à plusieurs niveaux (ou modulaire) pour la conception du logiciel.

Structure

Commençons par les bases:

  • NeuralNetworkImpl est la classe de base pour tous les modèles de réseaux neuronaux.
  • Chaque réseau contient un ensemble de couches (layers).
  • Chaque couche a une liste de connexions, où la connexion est un lien  entre deux couches de sorte que le réseau est un graphique acyclique dirigé.

Cette structure est assez agile pour être utilisée pour les réseaux feedforward classiques, ainsi que pour les RBM et les architectures plus complexes comme ImageNet.

Cela permet également à une couche de faire partie de plus d’un réseau. Par exemple, les couches d’un réseau Deep Belief sont également des couches dans leurs RBM correspondants.

De plus, cette architecture permet à un DBN d’être vu comme une liste de RBM empilés pendant la phase de pré-formation et un réseau feedforward pendant la phase de réglage fin, qui est à la fois intuitivement agréable et commode par programme.

Propagation Des Données

Le module suivant prend en charge la propagation des données à travers le réseau, un processus en deux étapes:

  1. Déterminer l’ordre des couches. Par exemple, pour obtenir les résultats d’un perceptron multicouche, les données sont « attachées » sur la couche d’entrée (d’où il s’agit de la première couche à calculer) et propagées jusqu’à la couche de sortie. Afin de mettre à jour les poids lors de la rétro-propagation, l’erreur de sortie doit être propagée à travers chaque couche dans l’ordre de largeur en premier, à partir de la couche de sortie. Ceci est réalisé en utilisant différentes implémentations de LayerOrderStrategy, qui tire parti de la structure graphique du réseau, en utilisant différentes méthodes de traversée de graphe. Quelques exemples incluent breadth-first strategy (la stratégie de largeur d’abord) et le targeting of a specific layer (ciblage d’une couche spécifique). L’ordre est en fait déterminé par les connexions entre les couches, de sorte que les stratégies renvoient une liste ordonnée de connexions.
  2. Calculez la valeur d’activation. Chaque couche a un ConnectionCalculator associé qui prend sa liste de connexions (de l’étape précédente) et les valeurs d’entrée (d’autres couches) et calcule l’activation résultante. Par exemple, dans un réseau simple feedforward sigmoïdal, ConnectionCalculator de la couche cachée prend les valeurs des couches d’entrée et de polarisation (qui sont, respectivement, les données d’entrée et un tableau de 1s) et les poids entre les unités (dans le cas de couches entièrement connectées, les poids sont réellement stockés dans une connexion FullyConnected en tant que matrice), calcule la somme pondérée et envoie le résultat dans la fonction sigmoïde. Les calculateurs de connexion mettent en œuvre une variété de fonctions de transfert (par exemple, somme pondérée, convolution) et d’activation (par exemple, logistique et tanh pour perceptron multicouche, binaire pour RBM). La plupart d’entre eux peuvent être exécutés sur un GPU en utilisant Aparapi et utilisable avec une formation en mini-batch.

Calcul GPU Avec Aparapi

Comme je l’ai mentionné plus tôt, l’une des raisons pour lesquelles les réseaux de neurones ont fait leur réapparition ces dernières années est que leurs méthodes d’entraînement sont très propices au parallélisme, ce qui vous permet d’accélérer considérablement l’entraînement avec GPGPU. Dans ce cas, j’ai choisi de travailler avec la librairie Aparapi pour ajouter le support GPU.

Aparapi impose des restrictions importantes sur les calculateurs de connexion:

  • Seuls les tableaux (et variables) unidimensionnels de types de données primitifs sont autorisés.
  • Seules les méthodes membres de la classe Aparapi Kernel sont autorisées à être appelées à partir du code exécutable GPU.

En tant que tel, la plupart des données (poids, d’entrée et de sortie des tableaux) sont stockées dans les instances de la matrice, qui utilisent des tableaux flottants unidimensionnels intérieurement. Tous les calculateurs de connexion Aparapi utilisent AparapiWeightedSum (pour les couches entièrement connectées et les fonctions d’entrée de somme pondérée), AparapiSubsampling2D (pour les couches de sous-échantillonnage) ou AparapiConv2D (pour les couches convolutives). Certaines de ces limitations peuvent être surmontées avec l’introduction de l’architecture système hétérogène. Aparapi permet également d’exécuter le même code sur les deux CPU et GPU.

Entraînement

Le module de formation met en œuvre divers algorithmes d’entraînement. Il repose sur les deux modules précédents. Par exemple, BackPropagationTrainer (tous les formateurs utilisent la classe de base Trainer) utilise un calculateur de couche feedforward pour la phase feedforward et un calculateur de couche first-first spécial pour propager l’erreur et mettre à jour les poids.

Mon dernier travail est sur le support de Java 8 et d’autres améliorations, seront bientôt fusionnées en master.

Conclusion

Le but de ce tutoriel d’apprentissage en profondeur Java était de vous donner une brève introduction au domaine des algorithmes d’apprentissage profond, en commençant par l’unité de composition la plus basique (le perceptron) et en progressant à travers diverses architectures efficaces et populaires, comme celle de machines Boltzmann restreintes.

Les idées derrière les « neural networks » (réseaux de neurones) existent depuis longtemps; mais aujourd’hui, vous ne pouvez pas mettre les pieds dans la communauté de l’apprentissage automatique (machine learning) sans avoir entendu parler de réseaux profonds (deep networks) ou d’un autre apprentissage en profondeur (deep learning). Hype ne devrait pas être confondu avec la justification, mais avec les progrès de l’informatique GPGPU et les progrès impressionnants réalisés par des chercheurs comme Geoffrey Hinton, Yoshua Bengio, Yann LeCun et Andrew Ng, le domaine montre certainement beaucoup de promesses. Il n’y a pas de meilleur moment pour se familiariser et s’impliquer comme aujourd’hui.

Note: L’article Original en Anglais  est à son auteur très bien connu Ivan Vasilev. Si vous voulez en savoir plus, DeepLearning.net, un portail pour tout savoir et comprendre à propos de l’apprentissage en profondeur (deep learning). Il a de bons tutoriels, une bibliothèque de logiciels et une excellente liste de lecture.

 

LAISSER UN COMMENTAIRE

Please enter your comment!
Please enter your name here

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.