Un rA�seau de neurones pour OpenSolarMap (2/3)

Un commentaire sur Un rA�seau de neurones pour OpenSolarMap (2/3)

AprA?s avoir essayA� un algorithme trA?s simple, puis un ou plusieurs algorithmes classiques, il est parfois (mais pas toujours) nA�cessaire de mettre en place un algorithme spA�cialisA� dans le problA?me A� rA�soudre. Les rA�seaux de neurones sont une catA�gorieA�d’algorithmes qui ont fait leurs preuves de maniA?re spectaculaire dans le domaine du traitement d’images.

Introduction

Au delA� de l’effet de mode dont ils bA�nA�ficient, les rA�seaux de neurones constituent bel et bien une avancA�eA�majeure en traitement d’images et dans bien d’autresA�domaines. Ce champ de rechercheA�reprA�sente une proportion importante des articles parues dans les revues de rA�fA�rence en machine learning : NIPS et ICML. Le domaine jouit A�galement d’une pleine reconnaissance acadA�mique comme l’illustre la chaire annuelle de l’INRIA au CollA?ge de France en « Informatique et sciences numA�riques » consacrA�e par Yann LeCun aux rA�seaux neuronaux. Cette chaire, cours et sA�minaires inclus, constitue d’ailleurs une excellente introduction aux techniques des rA�seaux neuronaux, parmi les multiples ressources disponibles librement sur Internet.

Les rA�seaux de neurones sont A�tudiA�s depuis les annA�es 50 avec l’invention du perceptron. Mais ceux qui bouleversent la communautA� du machine learning depuis 2011 se dA�nomment plus prA�cisA�ment « rA�seaux de neurones profonds A� convolution » (« deep convolutional neural networks », abrA�gA� parfois enA�CNN pour Convolutional Neural Networks ou encore ConvNets) :

  • neurone : MA?me s’il y a une lointaine analogie entre les neurones biologiques et les neurones informatiques, ils constituent deux domaines d’A�tude A� ne pas confondre. Un neurone informatique prend en entrA�e plusieurs valeurs numA�riques et applique une fonction A� ces entrA�es. Le rA�sultat numA�rique de cette fonction constitue l’unique sortie du neurone. Le neurone Rectified Linear UnitA�(ReLU)A�est majoritairement employA� : chaque entrA�e estA�multipliA�e par un coefficient (ou poids) puis cette somme est renvoyA�e si elle est positive, zA�ro est renvoyA� sinon.

    neurone

    Figure 1 : neurone de type ReLU A� 3 entrA�es.

  • rA�seau : Les neurones sont disposA�s en un rA�seau qui prend la forme de plusieurs couches successives. La premiA?re couche prend en entrA�e les valeurs de l’image (ou d’un autre type d’entrA�e comme du texte ou du son). Les sorties de la premiA?re couche constituent les entrA�es de la deuxiA?me couche, etc. Les sorties de la derniA?re couche sontA�les sorties du rA�seau, mais les valeurs numA�riques qui transitent entre les couches sont cachA�es A� l’utilisateur.A�De lA� vient en partie leur rA�putation d’A?tre des « boA�tes noires ».

    rA�seau

    Figure 2 : rA�seau de neurones A� 3 couches

  • convolution (paragraphe technique A� lire en seconde lecture) : Les rA�seaux A� convolution opA?rent gA�nA�ralement sur des images. La premiA?re couche de neurones est de la mA?me forme que l’image en entrA�e. La sortie de cette premiA?re couche, comme toutes les sorties intermA�diaires, forment des images.A�Au sein d’une couche de neurones, les paramA?tres de chaque neurones sont choisis de telle sorte que la couche applique un filtrage linA�aire puis une rectification. Un filtrage linA�aire est la convolution entre une image d’entrA�e et un filtre linA�aire. Un filtre linA�aire, dans le cas du traitement d’images, se reprA�sente come une petite image, typiquement de taille 3 par 3 pixels ou 5 par 5. Les rA�seaux A� convolution ont l’avantage de tirer partie de la structure gA�omA�trique de l’image d’entrA�e. De plus, chaque couche de neurones est paramA�trA�e par un filtre linA�aire qui est beaucoup plus simple A� apprendre que dans le cas gA�nA�ral. Par exemple, pour une image d’entrA�e de 224 par 224 pixel en noir et blanc, une couche de neurones de la mA?me taille est composA� de 224 A�A�224 neurones et si chaque neurone est connectA� A� chaque pixel d’entrA�e, il y a 224 A�A�224 paramA?tres par neurones. Cela fait un total de 224 A�A�224 A�A�224 A�A�224 = 2.517.630.976A�paramA?tres pour cette seule couche. Il faudrait donc des milliards d’images pour faire apprendre correctement un tel rA�seau. En comparaison, paramA�trer la couche de neurones par un filtre de 3 A�A�3 pixels ne requiert d’apprendre que 9 valeurs numA�riques. ConcrA?tement, cela revient A� mettreA�la majoritA� des poids des neurones A� zA�ro, et A� partager tous les poids restants entre les neurones de la couche. Dans un rA�seau A� convolution, des A�tapes de rA�duction de la taille de l’image s’intercalent entre les couches de neurones. Pour le rA�seau LeNet 5, deux A�tapes de rA�duction, appelA�es « subsampling » alternent avec les deux A�tapes de convolution. Les derniA?res couchent perdent la structure gA�omA�trique en dA�pliant l’image sur une dimension, mais le nombre de paramA?tres A� apprendre est raisonnable du fait de la petite taille des images. Enfin, il faut prA�ciser que, de la mA?me maniA?re qu’une image d’entrA�e peut contenir plusieurs canaux de couleur (rouge, vert et bleu par exemple), les images intermA�diaires se composent de plusieurs canaux. Dans le cas de LeNet 5, les images intermA�diaires se composent de 6 puis de 16 canaux. Au fil de l’apprentissage du rA�seau, chaque canal va se spA�cialiser dans la reconnaissance d’une forme gA�omA�trique particuliA?re.
  • profond : A�Les rA�seaux de neurones traditionnels, A�tudiA�s dans les annA�es 70, utilisaient entre 1 et 3 couches de neurones. On parle de rA�seaux profonds pour parler des architectures avec un nombre A�levA�s de couches qui peut dA�passer la centaine ! Les couches proches de l’image d’entrA�e se spA�cialisent dans la dA�tection de features gA�omA�triques trA?s simplesA�(des coins, des lignes…) alors les couches finales dA�tectent des features abstraites qui dA�pendent de l’usage du rA�seau (des lettres pour un rA�seau de reconnaissance d’A�criture, des objets, des espA?ces d’animaux…).
lenet5

Fgure 3 : rA�seau de neurones LeNet 5

Comme tous les algorithmes dits supervisA�s, les rA�seaux de neurones sont « appris » sur un A�chantillon de donnA�es d’exemples labellisA�s. La mA�thode d’apprentissage utilisA�e, nommA�e backpropagation,A�va modifier petit A� petitA�les paramA?tresA�de chaque couche pour augmenter la qualitA� des prA�dictions jusqu’A� atteindre une situation (localement) optimale. Une fois la phase d’apprentissage terminA�e, le rA�seauA�est capable de faire des prA�dictions sur de nouvelles images.

Les rA�seaux de neurones prA�sentent des performances spectaculaires et inattendues. Une des enjeux thA�orique actuel estA�de comprendreA�ces performances et de les confirmer par des garanties thA�oriques. C’est par exemple l’objet des recherches actuelle de StA�phane Mallat qui travaille sur la mA�thode de scattering,A�apparentA�e aux rA�seaux de neurones.

Librairie, rA�seau et code utilisA�s

Librairie de deep-learning

Les librairies de deep-learning ne manquent pas. La difficultA� est de choisir l’outil qui rA�pond le mieux aux besoinsA�du projet. Pour rA�pondre aux besoins d’OpenSolarMap, l’outil idA�al devra :

  • A?tre utilisable facilement et rapidement, c’est-A�-dire gA�rer lui-mA?me la totalitA� des calculs
  • laisser la possibilitA� de faire des modifications simples sur le rA�seau utilisA�
  • A?tre en open source pour pouvoir A?tre essayA�A�dans l’heure (et passer A� un autre outil s’il ne correspond pas parfaitement)
  • proposer une API en python car c’est le langage que nous utilisons majoritairement A� l’AGD
  • rassembler une communautA� active, pour disposer d’exemples d’utilisation, pour disposer de nombreuses questions/rA�ponses surA�stackoverflow.com, pour pouvoir compter sur l’aide de la communautA� en dernier recours
  • en bonus, pouvoir utiliser la puissance de calcul des GPU.

Parmi d’autres solutions qui auraient satisfait ces critA?res, j’ai choisi KerasA�sur les recommandations d’un confrA?re data-scientist. Je n’ai pas eu A� regretter ce choix, mais si Keras n’avait pas convenu, j’aurais sans doute testA� les outils Caffe, LasagneA�ou le trA?s populaire TorchA�mA?me s’il est A�crit en lua.

RA�seau de neurones VGG16

Concevoir un rA�seau de neurones est une tA?che compliquA�e qui nA�cessite une expA�rience approfondie. En revanche, utiliser une rA�seau de neurones dA�jA� prA?t est beaucoup plus simple et rapide A� mettre en A�uvre. Le « transfer learning » une technique standard expliquA�e dans cesA�notesA�du cours de vision CS231n de Standford.

Il y a dA�jA� de nombreux rA�seaux prA�-entraA�nA�s disponibles. Le projet Model-Zoo de l’universitA� de Berkeley est une liste de ces rA�seaux qui est d’un grand usage pour faire ce choix. Les rA�seaux listA�s par Model-Zoo sont proposA�s en Caffe, mais la plupart des modA?les sont directement utilisables avec d’autres librairies. J’ai choisi arbitrairement le cA�lA?bre rA�seau A� 16 couches VGG16A�du Visual Geometry Group de l’universitA� d’Oxford utilisA� lors de la competitionA�ILSVRC de 2014A�(ImageNet 2014). Il s’agit d’un rA�seau gA�nA�raliste. D’autres rA�seaux auraient pu convenir aussi bien et peut-A?tre mA?me mieux. Ce rA�seau est directement utilisable avec Keras en utilisant le GitHub Gist suivant :A�https://gist.github.com/baraldilorenzo/07d7802847aaad0a35d3

model = Sequential()
model.add(ZeroPadding2D((1,1),input_shape=(3,224,224)))
model.add(Convolution2D(64, 3, 3, activation='relu'))
model.add(ZeroPadding2D((1,1)))
model.add(Convolution2D(64, 3, 3, activation='relu'))
model.add(MaxPooling2D((2,2), strides=(2,2)))

model.add(ZeroPadding2D((1,1)))
model.add(Convolution2D(128, 3, 3, activation='relu'))
model.add(ZeroPadding2D((1,1)))
model.add(Convolution2D(128, 3, 3, activation='relu'))
model.add(MaxPooling2D((2,2), strides=(2,2)))

model.add(ZeroPadding2D((1,1)))
model.add(Convolution2D(256, 3, 3, activation='relu'))
model.add(ZeroPadding2D((1,1)))
model.add(Convolution2D(256, 3, 3, activation='relu'))
model.add(ZeroPadding2D((1,1)))
model.add(Convolution2D(256, 3, 3, activation='relu'))
model.add(MaxPooling2D((2,2), strides=(2,2)))

model.add(ZeroPadding2D((1,1)))
model.add(Convolution2D(512, 3, 3, activation='relu'))
model.add(ZeroPadding2D((1,1)))
model.add(Convolution2D(512, 3, 3, activation='relu'))
model.add(ZeroPadding2D((1,1)))
model.add(Convolution2D(512, 3, 3, activation='relu'))
model.add(MaxPooling2D((2,2), strides=(2,2)))

model.add(ZeroPadding2D((1,1)))
model.add(Convolution2D(512, 3, 3, activation='relu'))
model.add(ZeroPadding2D((1,1)))
model.add(Convolution2D(512, 3, 3, activation='relu'))
model.add(ZeroPadding2D((1,1)))
model.add(Convolution2D(512, 3, 3, activation='relu'))
model.add(MaxPooling2D((2,2), strides=(2,2)))

model.add(Flatten())
model.add(Dense(4096, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(4096, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(1000, activation='softmax'))

La premiA?re ligne dA�finit un modA?le sA�quentiel. D’autre architecturesA�plus compliquA�es existent, mais le rA�seau VGG16 est un empilement de couches dont chaque couche prend en entrA�e le rA�sultat de la couche prA�cA�dente. les lignes

model.add(Convolution2D(xxx, 3, 3, activation='relu'))

dA�finissent des couches de neurones ReLU avec une taille de filtre de 3 par 3 pixels et un nombre de canaux de 34, 128, 256 ou 512. Les lignes

model.add(MaxPooling2D((2,2), strides=(2,2)))

dA�finissent les A�tapes de rA�duction de la taille de l’image le long du rA�seau. La mA�thode Max Pooling est utilisA�e et chaque A�tape divise par 2 la taille. Les lignes

model.add(ZeroPadding2D((1,1)))

sont un dA�tail d’implA�mentation. Pour compenser la taille du filtre de 3 pixels, une bordure de 1 pixel est ajoutA� A� l’image d’entrA�e avant chaque convolution pour que la sortie de la convolution soit de mA?me taille. Enfin, le dernier bloc dA�finit 3 couches de neurones fully-connected.

La taille d’entrA�e spA�cifiA�e est 224 par 224 pixels (par 3 canaux). Chaque couple Zero Padding / Convolution ne modifie pas la taille (A�ventuellement le nombre de canaux) et chaque Max Pooling divise la taille par 2 (sans modifier le nombre de canaux). On peut en dA�duire que l’opA�ration Flatten prend en entrA�e une image de 7 par 7 pixels avec 512 canaux et renvoie un vecteur de taille 25.088. Les deux couches suivantes comptent 4096 neurones puis la derniA?re en compte 1000, qui correspondent aux 1000 classes A� prA�dire pour la compA�tition ImageNet.

Modification du rA�seau

Le rA�seau a A�tA� entraA�nA� pour classer une image parmi 1000 classes de la compA�tition ImageNet et non pas pour distinguer l’orientation des toitures. Mais une propriA�tA� des rA�seaux de neurones est qu’il sont A�galement trA?s efficace pour s’adapter A� des problA?mes voisins. Seules les derniA?res couches sont spA�cialisA�es dans la tA?che A� accomplir tandis que les premiA?res couches rA�solvent des problA?mes de dA�tection trA?s gA�nA�raux. Le transfert learning utilise cet avantage pour utiliser trA?s rapidement un rA�seau pour une nouvelle tA?che. La mA�thode la plus simple, sans fine-tuning, a A�tA� utilisA�e pour OpenSolarMap.

Changement de la taille d’entrA�e

Le rA�seau VGG16 prend en entrA�e des images de taille 224 par 224, or les images de toits ont une taille moyenne de 95 par 93 pixels (voir figure 4). On a le choix d’agrandir les images avant d’appliquer le rA�seau, ou de changer la taille d’entrA�e du rA�seau vers une valeur plus proche de la taille moyenne. La premiA?re approche fournirait des images majoritairementA�floues au rA�seau, c’est pourquoi j’ai choisi la secondeA�approche. La taille de 96 par 96 est idA�ale, car aprA?s les 5 A�tapes de rA�duction, la taille de l’image intermA�diaire tombe « juste » sur 3 par 3 pixels.

La ligne 2 du gist est remplacA�e par :

model.add(ZeroPadding2D((1,1),input_shape=(3,96,96)))
size

Figure 4 : rA�partition des images de toits par taille (x, y)

Transfer learning

Les derniA?res couches sont spA�cifiques au concours ImagetNet et ne sont pas d’utilitA� ici. Ils sont donc retirA�s et le dernier bloc est remplacA� par

model.add(Flatten())

Le choix d’enlever 3 couches est arbitraire. La seule contrainte A� respecter estA�de conserver un nombre de features raisonnables, infA�rieur A� 10.000. Avec ce choix, on compte alors 3 x 3 x 512 = 4608 featutres en sortie du rA�seau. Ce n’est pas une prA�diction de la classe, mais ces features peuvent A?tre utilisA�es par un classifieur comme une rA�gression linA�aire.

RA�sultats

Les 4608 features calculA�es par le rA�seau alimentent un modA?le de rA�gression logistique, rA�gularisA� cette fois. Le paramA?tre de rA�gularisation varie et le taux d’erreur (figure 5) affiche une classique courbe en U du dilemme biais-variance. C’est la valeur qui donne le meilleur rA�sultat qui est retenue.A�La force de la rA�gularisation est un hyperparamA?tre, donc il est indispensable de calculer la performance sur un A�chantillon de validation. Le taux d’erreur sur cet A�chantillon est de 7%.

regul_cnn_lr

Figure 5 : taux d’erreur en fonction de la force de la rA�gularisation

Ce taux d’erreur est bien moins bon que ce qu’il serait possible d’obtenir avec des mA�thodes « state-of-the-art ». Tout d’abord, il faudraitA�tester d’autres rA�seaux que le VGG16, essayer diffA�rents choix de couches A� enlever voire faire duA�fine-tuning… Ici, il s’agissait surtout de dA�montrer qu’il est possible d’arriver trA?s rapidement A� des rA�sultats satisfaisants, en utilisant un rA�seau, une librairie et du code dA�jA� prA?ts A� l’emploi.

À propos de l'auteur:

1 Commentaire

Haut de page