Achromatopsie volontaire et son traitement dans les réseaux de neurones: convertir un CNN de la couleur aux niveaux de gris (et inversement)
ven. 03 juin 2022
Translations: en
Changer l'espace de couleurs d'entrée d'un réseau de neurones
Les réseaux de neurones convolutifs (CNN pour Convolutional Neural Networks) occupent une place de premier plan en vision par ordinateur moderne. L'approche la plus courante consiste à spécialiser des réseaux sur étagère préentraînés sur de grandes bases de données d'images annotées (le plus souvent ImageNet en classification) sur des jeux de données spécifiques à l'application visée (fine-tuning), de taille plus modeste.
Toutefois, réutiliser un modèle sur étagère n'est pas toujours possible sans adaptation, notamment lorsque les dimensions des images sur lesquelles le réseau a été préentraîné diffèrent de celles des images cibles. Par exemple, la plupart des CNN entraînés sur ImageNet reçoivent en entrée des images 224 × 224 × 3. Bien que les couches convolutives puissent s'appliquer sur des matrices de dimensions quelconques, la présence des couches entièrement connectées contraint généralement la taille des entrées. Ce problème se résout soit par un échantillonnage adaptatif global sur les activations (average pooling dans les ResNet [^he], par exemple) ou par redimensionnement des images aux bonnes dimensions.
Reste une question récurrente qui se pose lorsque le nombre de canaux des images d'entrée change au moment du fine-tuning. La situation la plus classique est la suivante: comment réutiliser un modèle sur étagère prévu pour des images en couleurs (rouge-vert-bleu, RVB) pour des images en niveaux de gris?
Plusieurs publications évoquent ce problème 12, en particulier en imagerie médicale. Tajbakhsh (2016) (cité plus de 1000 fois) explique ainsi: "Because the AlexNet architecture used in our study required color patches as its input, each extracted gray-scale patch was converted to a color patch by repeating the gray channel thrice."
Cette solution consistant à dupliquer trois fois l'image en niveaux de gris est courante. Pourtant, contrairement à une croyance répandue 38456, il n'est pas nécessaire :
- ni de réentraîner un réseau complet sur les images en niveaux de gris,
- ni de dupliquer l'image en niveaux de gris sur 3 canaux pour simuler une image RGB.
Nous allons voir comment il est possible de directement transformer la première couche d'un CNN pour passer d'un modèle compatible RVB à un modèle compatible niveaux de gris (et inversement) à performances équivalentes par une propriété simple mais semble-t-il méconnue des réseaux convolutifs.
Conversion couleurs vers niveaux de gris
Le problème des dimensions ne se pose qu'au niveau de la première couche (que l'on suppose convolutive). En effet, en considérant une image d'entrée \((C, W, H)\) avec \(C\) le nombre de canaux, \(W\) la largeur et \(H\) la hauteur, il est attendu que la première couche est représentée par un tenseur \((C, C', k_w, k_h)\), où \(C'\) correspond au nombre de filtres de dimensions \((k_w, k_h)\) de cette couche. Les couches suivantes travailleront sur ces activations donc il suffit pour convertir le modèle tout entier de reproduire ces mêmes activations et le reste du modèle sera compatible.
Modèle couleurs vers niveaux de gris
Il s'agit du problème le plus fréquent, à en juger par le nombre de questions sur divers forums concernant ce sujet (StackOverflow 7 et Data ScienceExchange 45, forums Mathworks 6, GitHub de Caffe 3, ...). Un seul utilisateur (Ross Wightman) donne une réponse correcte concernant la possibilité de cette conversion mais la réponse n'est pas celle qui est acceptée (!) et elle n'est pas justifiée mathématiquement.
Considérons une couche convolutive à \(p\) canaux d'entrée, \(q\) canaux de sortie et donc \(p \times q\) filtres notés \(w_{i,j}\). On note \(b_j\) les biais, \(x_i\) les activations d'entrée et \(z_j\) les activations de sortie. Par définition, la couche réalise donc l'opération:
où \(\star\) représente indifféremment la corrélation croisée ou la convolution (seule la propriété de distributivité importe). Dans le cas d'une entrée en RVB, \(p = 3\) et les \(x_i\) correspondent aux canaux rouge, vert et bleu (qui ne sont pas égaux a priori).
Néanmoins, supposons les \(x_i\) sont identiques, c'est-à-dire \(\forall i \in [ 1, p ] ~~ x_i = x^*\).
Alors l'équation de la première couche se réécrit :
C'est-à-dire que, dans le cas en niveaux de gris où l'on aurait dupliqué trois fois les valeurs de luminance pour simuler une image RVB, la convolution à 3 canaux d'entrée est équivalente à une convolution à seulement 1 canal d'entrée mais dont chaque filtre \(w^*_j\) correspond à la somme des filtres \(w_{i,j}\) selon \(i\). Les biais sont eux inchangés.
La modification est donc plutôt simple, avec la fonction PyTorch ci-dessous :
from torch import nn
def net_rgb2gray(net, layer_name='conv1'):
layer = net.__getattr__(layer_name)
gray_weights = layer.weight.sum(dim=1, keepdim=True)
use_bias = layer.bias is not None
gray_layer = nn.Conv2d(in_channels=1, kernel_size=layer.kernel_size,
out_channels=layer.out_channels, padding=layer.padding,
stride=layer.stride, dilation=layer.dilation, bias=use_bias)
gray_layer.weight.data = gray_weights
if use_bias:
gray_layer.bias.data = layer.bias.data
net.__setattr__(layer_name, gray_layer)
return net
Niveaux de gris vers couleurs
Inversement, considérons une transformation \(\mathcal{T}\) couleurs \(\rightarrow\) niveaux de gris telle que, en notant \(x_i\) les intensités des couleurs:
Typiquement, la recommandation 709 pour la télévision
HD propose \(\lambda_R = 0,2126,~\lambda_V = 0,7152\) et
\(\lambda_B = 0,0722\). Cette transformation est un standard de
facto suivi notamment par les bibliothèques PIL et
scikit-image.
Considérons un modèle entraîné sur les images \(\mathcal{I}^*\) en niveaux de gris obtenues à partir des images \(\mathcal{I}\) par la transformation \(\mathcal{T}\).
Les activations \(z_j\) pour la première couche s'obtiennent par :
Par identification, il est donc possible de construire un modèle à \(p\) canaux d'entrée (typiquement \(p = 3\)) en remplaçant la convolution initiale par une nouvelle couche en initialisant les filtres \(w_{i,j} = \lambda_i \cdot w^*_j\). Un exemple de fonction permettant de réaliser cette transformation avec PyTorch :
def net_gray2rgb(net, lambdas, layer_name='conv1'):
layer = net.__getattr__(layer_name)
rgb_weights = lambdas * layer.weight.repeat(1, 3, 1, 1)
use_bias = layer.bias is not None
rgb_layer = nn.Conv2d(in_channels=3, kernel_size=layer.kernel_size,
out_channels=layer.out_channels, padding=layer.padding,
stride=layer.stride, dilation=layer.dilation, bias=use_bias)
rgb_layer.weight.data = rgb_weights
if use_bias:
rgb_layer.bias.data = layer.bias.data
net.__setattr__(layer_name, rgb_layer)
return net
Bénéfices de cette approche
Il est permis de s'interroger sur l'intérêt pratique de cette transformation. Les activations étant identiques, les performances sont identiques dans tous les cas et équivalentes au modèle en niveaux de gris sur 3 canaux. Toutefois, au-delà de l'inélégance de la pratique consistant à dupliquer les canaux d'une image en niveau de gris pour la faire rentrer au chausse-pied dans un modèle prévu pour des images couleur, il existe néanmoins sur le papier un avantage concret à cette approche: une (légère) économie de paramètres et un (faible) gain en vitesse d'exécution.
En effet, en évitant de dupliquer les canaux, on compresse effectivement la première couche convolutive \((3, m, k, k)\) en une couche \((1, m, k, k)\) soit 3 fois moins de paramètres pour la première couche. Cela correspond par exemple à 6272 paramètres en moins pour un ResNet classique. Malheureusement, ce gain est modeste par rapport au nombre total de paramètres d'un ResNet, même peu profond (cela représente moins de 1% d'un ResNet-20 réduit pour CIFAR10) et insignifiant pour un VGG-16 dont le nombre de paramètres est dominé de plusieurs ordres de grandeur par les couches entièrement connectées.
Le retrait de \(2/3\) des convolutions initiales, qui sont généralement celles le plus chères à exécuter (car appliquées directement sur l'image entière et avec un noyau de taille souvent nettement supérieure aux couches postérieures) permet de gagner légèrement en temps de calcul. En inférence, pour un ResNet-20, un modeste gain de 1.5% est constaté sur CPU. Sur GPU, aucun gain significatif n'est mesurable, vraisemblablement car les convolutions de la première couche sont traitées en parallèle.
Le principal intérêt semble donc théorique : il semble plus élégant de ne pas dupliquer les calculs ni d'introduire des paramètres qui ne sont pas nécessaires. Cela encourage par ailleurs à faciliter le fine-tuning des modèles. En effet les transformations proposés ci-dessus peuvent permettre d'initialiser un modèle niveaux de gris à partir d'un modèle RVB puis ensuite à spécialiser celui-ci sur un des images en niveaux de gris. C'est par exemple un cas d'application assez courant en imagerie médicale. Le cas inverse (fine-tuning d'un CNN en couleurs à partir d'un modèle préappris en niveaux de gris) est a priori plus exceptionnel mais il demeure théoriquement possible.
-
Nima TAJBAKHSH et al. “Convolutional Neural Networks for Medical Image Analysis : Full Training or Fine Tuning ?”. In : IEEE Transactions on Medical Imaging 35.5 (mai 2016), p. 1299-1312. ↩
-
Brady KIEFFER et al. “Convolutional neural networks for histopathology image classification : Training vs. Using pre-trained networks”. In : 2017 Seventh International Conference on Image Processing Theory, Tools and Applications (IPTA). Nov. 2017, p. 1-6. ↩
-
https://datascience.stackexchange.com/questions/22684/is-it-possible-to-use-grayscale-images-to-existing-model ↩↩
-
https://datascience.stackexchange.com/questions/12717/convert-filters-pre-trained-with-imagenet-to-grayscale ↩↩
-
https://fr.mathworks.com/matlabcentral/answers/374950-how-can-i-make-alexnet-accept-277x277x1-images ↩↩
-
https://stackoverflow.com/questions/51995977/how-can-i-use-a-pre-trained-neural-network-with-grayscale-images ↩
-
https://www.researchgate.net/post/How-To-use-gray-level-images-Ultrasound-in-CNN-as-they-have-1-channel-and-CNN-use-3-channels-RGB ↩
Category: science Tagged: cnn deep learning computer vision
Translations: en