Comment initialiser les éléments de la matrice de filtre?

24

J'essaie de mieux comprendre les réseaux de neurones convolutifs en écrivant du code Python qui ne dépend pas des bibliothèques (comme Convnet ou TensorFlow), et je me retrouve coincé dans la littérature sur la façon de choisir des valeurs pour la matrice du noyau, quand effectuer une convolution sur une image.

J'essaie de comprendre les détails de l'implémentation à l'étape entre les cartes d'entités dans l'image ci-dessous montrant les couches d'un CNN.

Couches de réseaux de neurones convolutifs

Selon ce schéma:

Convolution d'une image

Le noyau de la matrice du noyau "parcourt" l'image, créant une carte des caractéristiques, où chaque pixel est la somme de tous les produits par élément entre chaque poids du noyau (ou matrice de filtre) et la valeur de pixel correspondante de l'image d'entrée.

Ma question est: comment initialiser les poids de la matrice du noyau (ou du filtre)?

Dans la démonstration ci-dessus, ce sont simplement des 1 et des 0, mais je suppose que cela est simplifié par souci du diagramme.

Ces poids sont-ils formés à une étape de prétraitement? Ou choisi explicitement par l'utilisateur?

Kai Kuspa
la source

Réponses:

19

On initialise généralement un réseau à partir d'une distribution aléatoire, signifie généralement zéro et un certain soin est apporté au choix de sa variance. De nos jours, avec les progrès des techniques d'optimisation (SGD + Momentum entre autres méthodes) et les non-linéarités d'activation (ReLU et activations de type ReLU permettent une meilleure rétro-projection des signaux de gradient, même dans les réseaux plus profonds), on est en mesure de former des convolutions de pointe réseaux de neurones à partir d'une initialisation aléatoire.

Les propriétés clés sont les suivantes:

  • Pourquoi aléatoire? Pourquoi ne pas tous les initialiser à 0? Un concept important ici est appelé rupture de symétrie . Si tous les neurones ont les mêmes poids, ils produiront les mêmes sorties et nous n'apprendrons pas différentes fonctionnalités. Nous n'apprendrons pas différentes fonctionnalités car pendant l'étape de rétropropagation, toutes les mises à jour de poids seront exactement les mêmes. Donc, commencer par une distribution aléatoire nous permet d'initialiser les neurones pour qu'ils soient différents (avec une probabilité très élevée) et nous permet d'apprendre une hiérarchie de fonctionnalités riche et diversifiée.

  • Pourquoi zéro? Une pratique courante dans l'apprentissage automatique consiste à centrer zéro ou à normaliser les données d'entrée, de sorte que les caractéristiques d'entrée brutes (pour les données d'image, ce seraient des pixels) se situent en moyenne à zéro.

    Nous avons centré nos données à zéro et nous initialiserons au hasard les pondérations de notre réseau (matrices comme vous les avez mentionnées). Quelle distribution choisir? La distribution des données d'entrée sur notre réseau est nulle depuis que nous sommes centrés sur zéro. Supposons que nous initialisions également nos termes de biais à zéro. Lorsque nous initialisons la formation de notre réseau, nous n'avons aucune raison de privilégier un neurone par rapport à l'autre car ils sont tous aléatoires. Une pratique consiste à initialiser au hasard nos poids de manière à ce qu'ils aient tous une sortie d'activation nulle en attente. De cette façon, aucun neurone n'est favorisé pour "s'activer" (avoir une valeur de sortie positive) que tout autre neurone tout en brisant simultanément la symétrie en raison de l'initialisation aléatoire. Eh bien, un moyen simple d'accomplir cela est de choisir une distribution moyenne nulle.

  • Comment choisissons-nous les écarts? Vous ne voulez pas que la variance soit trop grande, même si elle est nulle. Des valeurs extrêmes dans un poids de réseaux profonds peuvent entraîner des sorties d'activation qui augmentent de façon exponentielle, et ce problème peut s'aggraver avec la profondeur du réseau. Cela peut faire des ravages sur la formation de notre réseau. Vous ne voulez pas non plus le choisir trop petit car cela peut ralentir l'apprentissage car nous calculons de très petites valeurs de gradient. Il y a donc un équilibre ici, surtout quand il s'agit de réseaux plus profonds car nous ne voulons pas que nos propagations en avant ou en arrière augmentent ou diminuent de manière exponentielle en profondeur.

    Il existe deux schémas d'initialisation de poids très populaires: Glorot Uniform ( Comprendre la difficulté de former des réseaux de neurones profonds ) et l'initialiseur He Normal ( Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification ).

    Ils sont tous deux construits dans le but de former des réseaux profonds avec le principe de base suivant à l'esprit (citation tirée de l'article Delving Deeper into Rectifiers):

    "Une méthode d'initialisation appropriée devrait éviter de réduire ou de grossir de façon exponentielle les amplitudes des signaux d'entrée."

    En gros, ces deux schémas d'initialisation initialisent la variance de chaque couche afin que la distribution de sortie de chaque neurone soit la même. La section 2.2 de Plonger profondément dans les redresseurs fournit une analyse approfondie.

Une note finale: parfois, vous verrez également des gens utiliser le gaussien avec un écart-type égal à .005 ou .01, ou un autre "petit" écart-type, à travers toutes les couches. D'autres fois, vous verrez des gens jouer avec les variations à la main, effectuant essentiellement une validation croisée pour trouver la configuration la plus performante.

Indie AI
la source
1
Mais qu'en est-il de la forme "X" (faite par 1) du filtre jaune dans le GIF ci-dessus? Je comprends que c'est ce que je voudrais utiliser pour détecter les formes en "X" n'importe où dans l'image, mais comment savoir que "X" est la forme que je veux? J'ai l'impression que la forme du filtre s'apprend automatiquement, mais je ne sais pas comment. C'était peut-être aussi la question du PO?
Felipe Almeida
2

Je ne peux pas faire de commentaire à cause de la mauvaise réputation et j'écris donc ceci en réponse à la question de Felipe Almeida. Après la réponse parfaite d'Indie AI, il n'y a rien à ajouter. Si vous souhaitez détecter des formes spécifiques (comme un X), vous pouvez prédéfinir un filtre spécifique, comme c'est le cas avec la détection des contours. Mais c'est la beauté de l'apprentissage en profondeur, il y a tellement de couches, tellement de filtres et tellement d'itérations que les filtres apprennent à eux seuls presque toutes les formes d'objets nécessaires. Donc théoriquement, s'il y a un X à détecter, l'un des filtres apprendra à détecter un X (comme le filtre jaune)

code mort
la source