Est-il possible de donner des images de taille variable comme entrée à un réseau neuronal convolutif?
17
Peut-on donner des images de taille variable en entrée à un réseau neuronal convolutif pour la détection d'objets? Si possible, comment pouvons-nous faire cela?
Mais si nous essayons de recadrer l'image, nous perdrons une partie de l'image et si nous essayons de redimensionner, alors, la clarté de l'image sera perdue. Cela signifie-t-il que l'utilisation de la propriété réseau inhérente est la meilleure si la clarté de l'image est le principal point à considérer?
Il existe plusieurs façons de procéder. La plupart d'entre eux ont déjà été couverts dans un certain nombre de publications sur StackOverflow, Quora et d'autres sites Web de contenu.
Pour résumer, la plupart des techniques énumérées peuvent être regroupées en deux classes de solutions, à savoir:
Transformations
Propriété de réseau inhérente
Dans les transformations, on peut rechercher des techniques telles que
Redimensionner , qui est la plus simple de toutes les techniques mentionnées
Recadrage , qui peut être effectué sous forme de fenêtre coulissante ou de recadrage ponctuel avec perte d'informations
On peut également examiner les réseaux qui ont la propriété inhérente d'être immunisés contre la taille de l'entrée en vertu du comportement de couche qui construit le réseau. Des exemples de cela peuvent être trouvés en termes de,
Réseaux entièrement convolutionnels (FCN) , qui n'ont aucune limitation sur la taille d'entrée car une fois que les tailles de noyau et de pas sont décrites, la convolution à chaque couche peut générer des sorties de dimension appropriées en fonction des entrées correspondantes.
Spatial Pyramid Pooling (SPP) , les FCN n'ont pas de couche dense entièrement connectée et sont donc agnostiques à la taille de l'image, mais dites que si l'on voulait utiliser une couche dense sans considérer les transformations d'entrée, alors il y a un papier intéressant qui explique la couche dans un réseau d'apprentissage en profondeur.
Cela semble correct en théorie, mais ne fonctionne pas sur Tensorflow. Quelqu'un a-t-il des implémentations pour cela?
Hossein
1
@Hossein J'ai également rencontré des problèmes d'implémentation pratique, mais j'ai obtenu un CNN de taille variable fonctionnant dans Tensorflow Keras 2.x aujourd'hui avec certaines limitations. J'ai publié un aperçu de l'approche dans ma réponse en ce qui concerne certains détails pratiques. Bonne chance!
J Trana
4
Les couches convolutives et les couches de mise en commun elles-mêmes sont indépendantes des dimensions d'entrée. Cependant, la sortie des couches convolutives aura des tailles spatiales différentes pour des images de tailles différentes, et cela posera un problème si nous avons une couche entièrement connectée par la suite (car notre couche entièrement connectée nécessite une entrée de taille fixe). Il existe plusieurs solutions à cela:
1. Global Pooling: évitez les couches entièrement connectées à la fin des couches convolutives et utilisez plutôt le pooling (tel que Global Average Pooling) pour réduire vos cartes d'entités à partir d'une forme de (N, H, W, C) (avant le pool global ) pour façonner (N, 1,1, C) (après le pool global), où:
N = nombre d'échantillons de mini-lots
H = hauteur spatiale de la carte d'entités
W = largeur spatiale de la carte d'entités
C = nombre de cartes d'entités (canaux)
As peut être vu, la dimensionnalité de sortie (N * C) est maintenant indépendante de la taille spatiale (H, W) des cartes d'entités. En cas de classement, vous pouvez ensuite utiliser une couche entièrement connectée sur le dessus pour obtenir les logits de vos classes.
2. Mise en commun de taille variable:Utilisez des régions de mise en commun de taille variable pour obtenir la même taille de carte d'entités pour différentes tailles d'entrée.
3. Recadrer / redimensionner / recadrer les images d'entrée: vous pouvez essayer de redimensionner / recadrer / recadrer vos images d'entrée pour qu'elles aient toutes la même forme.
Dans le contexte de l'apprentissage par transfert, vous souhaiterez peut-être utiliser des entrées de tailles différentes de celles des entrées d'origine avec lesquelles le modèle a été formé. Voici quelques options pour le faire:
4. Créez de nouveaux calques entièrement connectés: vous pouvez abandonner complètement les calques entièrement connectés d'origine et initialiser un nouveau calque entièrement connecté avec la dimensionnalité dont vous avez besoin, et l'entraîner à partir de zéro.
5. Traitez la couche entièrement connectée comme une convolution: normalement, nous remodelons les cartes d'entités de (N, H, W, C) à (N, H * W * C) avant de les alimenter vers la couche entièrement connectée. Mais vous pouvez également traiter la couche entièrement connectée comme une convolution avec un champ récepteur de (H, W). Ensuite, vous pouvez simplement convoluer ce noyau avec vos cartes de fonctionnalités, quelle que soit leur taille (utilisez un remplissage nul si nécessaire) [http://cs231n.github.io/transfer-learning/ ].
J'ai dû résoudre ce problème aujourd'hui, alors j'ai pensé partager ce que j'ai trouvé qui fonctionnait. J'ai trouvé qu'il y avait pas mal de réponses et de petites friandises «cela pourrait fonctionner en théorie» sur le Web, mais moins d'une pratique «voici comment vous concrétisez cela».
Pour implémenter cela en utilisant Kerens Tensorflow, j'ai dû faire ce qui suit. Peut-être que quelqu'un d'autre peut trouver que certains d'entre eux peuvent être modifiés, détendus ou supprimés.
Définissez l'entrée du réseau pour permettre une entrée de taille variable en utilisant «Aucun» comme dimension d'espace réservé sur la forme_entrée. Voir la réponse de François Chollet ici .
Utilisez les couches convolutives uniquement jusqu'à ce qu'une opération de regroupement global se soit produite (par exemple GlobalMaxPooling2D). Ensuite, des couches denses, etc. peuvent être utilisées car la taille est maintenant fixe.
Utilisez une taille de lot de 1 uniquement. Cela évite de traiter des tailles mixtes dans un lot.
Écrivez une petite séquence personnalisée qui crée des lots de taille 1 à partir de la liste des entrées. J'ai fait cela pour éviter de traiter des tailles différentes dans un seul tableau Numpy.
Utilisez Model.fit_generator sur votre séquence personnalisée pour la formation et la validation. (vs Model.fit)
Pour une raison quelconque, Model.predict_generator est apparu même lors de l'utilisation de la séquence comme ci-dessus. J'ai dû recourir à Model.predict sur des entrées individuelles.
Notez que les appels à Model.predict se sont plaints des performances - ce qui n'est pas surprenant étant donné l'inefficacité de la solution - mais cela fonctionne!
Oui, sélectionnez simplement un réseau fédérateur approprié qui ne dépend pas de la taille de l'image d'entrée pour être une valeur précise - la plupart des réseaux satisfont à ces critères.
Vous ne vous trompez pas, mais votre réponse n'est pas très informative - qu'en est-il de l'étendre pour expliquer pourquoi la plupart des CNN modernes peuvent fonctionner avec des images de taille variable? Aussi, quelles sont les limites de cette variabilité (par exemple, n'essayez pas de mélanger des images de tailles différentes dans le même mini-batch ...)? La plupart des gens issus de MLP à l'ancienne (la longueur d'entrée est fixe) ou de CNN à l'ancienne (AlexNet et VGG-1X), avec leurs Flattencouches embêtantes , ne comprennent pas comment les CNN modernes peuvent en principe prendre des images de n'importe quelle taille.
Les couches convolutives et les couches de mise en commun elles-mêmes sont indépendantes des dimensions d'entrée. Cependant, la sortie des couches convolutives aura des tailles spatiales différentes pour des images de tailles différentes, et cela posera un problème si nous avons une couche entièrement connectée par la suite (car notre couche entièrement connectée nécessite une entrée de taille fixe). Il existe plusieurs solutions à cela:
1. Global Pooling: évitez les couches entièrement connectées à la fin des couches convolutives et utilisez plutôt le pooling (tel que Global Average Pooling) pour réduire vos cartes d'entités à partir d'une forme de (N, H, W, C) (avant le pool global ) pour façonner (N, 1,1, C) (après le pool global), où:
N = nombre d'échantillons de mini-lots
H = hauteur spatiale de la carte d'entités
W = largeur spatiale de la carte d'entités
C = nombre de cartes d'entités (canaux)
As peut être vu, la dimensionnalité de sortie (N * C) est maintenant indépendante de la taille spatiale (H, W) des cartes d'entités. En cas de classement, vous pouvez ensuite utiliser une couche entièrement connectée sur le dessus pour obtenir les logits de vos classes.
2. Mise en commun de taille variable:Utilisez des régions de mise en commun de taille variable pour obtenir la même taille de carte d'entités pour différentes tailles d'entrée.
3. Recadrer / redimensionner / recadrer les images d'entrée: vous pouvez essayer de redimensionner / recadrer / recadrer vos images d'entrée pour qu'elles aient toutes la même forme.
Dans le contexte de l'apprentissage par transfert, vous souhaiterez peut-être utiliser des entrées de tailles différentes de celles des entrées d'origine avec lesquelles le modèle a été formé. Voici quelques options pour le faire:
4. Créez de nouveaux calques entièrement connectés: vous pouvez abandonner complètement les calques entièrement connectés d'origine et initialiser un nouveau calque entièrement connecté avec la dimensionnalité dont vous avez besoin, et l'entraîner à partir de zéro.
5. Traitez la couche entièrement connectée comme une convolution: normalement, nous remodelons les cartes d'entités de (N, H, W, C) à (N, H * W * C) avant de les alimenter vers la couche entièrement connectée. Mais vous pouvez également traiter la couche entièrement connectée comme une convolution avec un champ récepteur de (H, W). Ensuite, vous pouvez simplement convoluer ce noyau avec vos cartes de fonctionnalités, quelle que soit leur taille (utilisez un remplissage nul si nécessaire) [http://cs231n.github.io/transfer-learning/ ].
la source
J'ai dû résoudre ce problème aujourd'hui, alors j'ai pensé partager ce que j'ai trouvé qui fonctionnait. J'ai trouvé qu'il y avait pas mal de réponses et de petites friandises «cela pourrait fonctionner en théorie» sur le Web, mais moins d'une pratique «voici comment vous concrétisez cela».
Pour implémenter cela en utilisant Kerens Tensorflow, j'ai dû faire ce qui suit. Peut-être que quelqu'un d'autre peut trouver que certains d'entre eux peuvent être modifiés, détendus ou supprimés.
Notez que les appels à Model.predict se sont plaints des performances - ce qui n'est pas surprenant étant donné l'inefficacité de la solution - mais cela fonctionne!
la source
Oui, sélectionnez simplement un réseau fédérateur approprié qui ne dépend pas de la taille de l'image d'entrée pour être une valeur précise - la plupart des réseaux satisfont à ces critères.
la source
Flatten
couches embêtantes , ne comprennent pas comment les CNN modernes peuvent en principe prendre des images de n'importe quelle taille.