Quelqu'un peut-il expliquer clairement la différence entre les convolutions 1D, 2D et 3D dans les réseaux de neurones convolutifs (en apprentissage profond) à l'aide d'exemples?
126
Quelqu'un peut-il expliquer clairement la différence entre les convolutions 1D, 2D et 3D dans les réseaux de neurones convolutifs (en apprentissage profond) à l'aide d'exemples?
Je veux expliquer avec une image de C3D .
En un mot, la direction convolutionnelle et la forme de sortie sont importantes!
↑↑↑↑↑ Convolutions 1D - Basique ↑↑↑↑↑
import tensorflow as tf
import numpy as np
sess = tf.Session()
ones_1d = np.ones(5)
weight_1d = np.ones(3)
strides_1d = 1
in_1d = tf.constant(ones_1d, dtype=tf.float32)
filter_1d = tf.constant(weight_1d, dtype=tf.float32)
in_width = int(in_1d.shape[0])
filter_width = int(filter_1d.shape[0])
input_1d = tf.reshape(in_1d, [1, in_width, 1])
kernel_1d = tf.reshape(filter_1d, [filter_width, 1, 1])
output_1d = tf.squeeze(tf.nn.conv1d(input_1d, kernel_1d, strides_1d, padding='SAME'))
print sess.run(output_1d)
↑↑↑↑↑ Convolutions 2D - Basique ↑↑↑↑↑
ones_2d = np.ones((5,5))
weight_2d = np.ones((3,3))
strides_2d = [1, 1, 1, 1]
in_2d = tf.constant(ones_2d, dtype=tf.float32)
filter_2d = tf.constant(weight_2d, dtype=tf.float32)
in_width = int(in_2d.shape[0])
in_height = int(in_2d.shape[1])
filter_width = int(filter_2d.shape[0])
filter_height = int(filter_2d.shape[1])
input_2d = tf.reshape(in_2d, [1, in_height, in_width, 1])
kernel_2d = tf.reshape(filter_2d, [filter_height, filter_width, 1, 1])
output_2d = tf.squeeze(tf.nn.conv2d(input_2d, kernel_2d, strides=strides_2d, padding='SAME'))
print sess.run(output_2d)
↑↑↑↑↑ Convolutions 3D - Basique ↑↑↑↑↑
ones_3d = np.ones((5,5,5))
weight_3d = np.ones((3,3,3))
strides_3d = [1, 1, 1, 1, 1]
in_3d = tf.constant(ones_3d, dtype=tf.float32)
filter_3d = tf.constant(weight_3d, dtype=tf.float32)
in_width = int(in_3d.shape[0])
in_height = int(in_3d.shape[1])
in_depth = int(in_3d.shape[2])
filter_width = int(filter_3d.shape[0])
filter_height = int(filter_3d.shape[1])
filter_depth = int(filter_3d.shape[2])
input_3d = tf.reshape(in_3d, [1, in_depth, in_height, in_width, 1])
kernel_3d = tf.reshape(filter_3d, [filter_depth, filter_height, filter_width, 1, 1])
output_3d = tf.squeeze(tf.nn.conv3d(input_3d, kernel_3d, strides=strides_3d, padding='SAME'))
print sess.run(output_3d)
↑↑↑↑↑ Convolutions 2D avec entrée 3D - LeNet, VGG, ..., ↑↑↑↑↑
in_channels = 32 # 3 for RGB, 32, 64, 128, ...
ones_3d = np.ones((5,5,in_channels)) # input is 3d, in_channels = 32
# filter must have 3d-shpae with in_channels
weight_3d = np.ones((3,3,in_channels))
strides_2d = [1, 1, 1, 1]
in_3d = tf.constant(ones_3d, dtype=tf.float32)
filter_3d = tf.constant(weight_3d, dtype=tf.float32)
in_width = int(in_3d.shape[0])
in_height = int(in_3d.shape[1])
filter_width = int(filter_3d.shape[0])
filter_height = int(filter_3d.shape[1])
input_3d = tf.reshape(in_3d, [1, in_height, in_width, in_channels])
kernel_3d = tf.reshape(filter_3d, [filter_height, filter_width, in_channels, 1])
output_2d = tf.squeeze(tf.nn.conv2d(input_3d, kernel_3d, strides=strides_2d, padding='SAME'))
print sess.run(output_2d)
in_channels = 32 # 3 for RGB, 32, 64, 128, ...
out_channels = 64 # 128, 256, ...
ones_3d = np.ones((5,5,in_channels)) # input is 3d, in_channels = 32
# filter must have 3d-shpae x number of filters = 4D
weight_4d = np.ones((3,3,in_channels, out_channels))
strides_2d = [1, 1, 1, 1]
in_3d = tf.constant(ones_3d, dtype=tf.float32)
filter_4d = tf.constant(weight_4d, dtype=tf.float32)
in_width = int(in_3d.shape[0])
in_height = int(in_3d.shape[1])
filter_width = int(filter_4d.shape[0])
filter_height = int(filter_4d.shape[1])
input_3d = tf.reshape(in_3d, [1, in_height, in_width, in_channels])
kernel_4d = tf.reshape(filter_4d, [filter_height, filter_width, in_channels, out_channels])
#output stacked shape is 3D = 2D x N matrix
output_3d = tf.nn.conv2d(input_3d, kernel_4d, strides=strides_2d, padding='SAME')
print sess.run(output_3d)
↑↑↑↑↑ Bonus 1x1 conv dans CNN - GoogLeNet, ..., ↑↑↑↑↑
in_channels = 32 # 3 for RGB, 32, 64, 128, ...
out_channels = 64 # 128, 256, ...
ones_3d = np.ones((1,1,in_channels)) # input is 3d, in_channels = 32
# filter must have 3d-shpae x number of filters = 4D
weight_4d = np.ones((3,3,in_channels, out_channels))
strides_2d = [1, 1, 1, 1]
in_3d = tf.constant(ones_3d, dtype=tf.float32)
filter_4d = tf.constant(weight_4d, dtype=tf.float32)
in_width = int(in_3d.shape[0])
in_height = int(in_3d.shape[1])
filter_width = int(filter_4d.shape[0])
filter_height = int(filter_4d.shape[1])
input_3d = tf.reshape(in_3d, [1, in_height, in_width, in_channels])
kernel_4d = tf.reshape(filter_4d, [filter_height, filter_width, in_channels, out_channels])
#output stacked shape is 3D = 2D x N matrix
output_3d = tf.nn.conv2d(input_3d, kernel_4d, strides=strides_2d, padding='SAME')
print sess.run(output_3d)
- Lien d'origine: LINK
- L'auteur: Martin Görner
- Twitter: @martin_gorner
- Google +: plus.google.com/+MartinGorne
↑↑↑↑↑ Convolutions 1D avec entrée 1D ↑↑↑↑↑
↑↑↑↑↑ Convolutions 1D avec entrée 2D ↑↑↑↑↑
in_channels = 32 # 3, 32, 64, 128, ...
out_channels = 64 # 3, 32, 64, 128, ...
ones_4d = np.ones((5,5,5,in_channels))
weight_5d = np.ones((3,3,3,in_channels,out_channels))
strides_3d = [1, 1, 1, 1, 1]
in_4d = tf.constant(ones_4d, dtype=tf.float32)
filter_5d = tf.constant(weight_5d, dtype=tf.float32)
in_width = int(in_4d.shape[0])
in_height = int(in_4d.shape[1])
in_depth = int(in_4d.shape[2])
filter_width = int(filter_5d.shape[0])
filter_height = int(filter_5d.shape[1])
filter_depth = int(filter_5d.shape[2])
input_4d = tf.reshape(in_4d, [1, in_depth, in_height, in_width, in_channels])
kernel_5d = tf.reshape(filter_5d, [filter_depth, filter_height, filter_width, in_channels, out_channels])
output_4d = tf.nn.conv3d(input_4d, kernel_5d, strides=strides_3d, padding='SAME')
print sess.run(output_4d)
sess.close()
1
, puis → pour la ligne1+stride
. La convolution elle-même est invariante par décalage, alors pourquoi la direction de la convolution est-elle importante?Suite à la réponse de @runhani, j'ajoute quelques détails supplémentaires pour rendre l'explication un peu plus claire et j'essaierai de l'expliquer un peu plus (et bien sûr avec des exemples de TF1 et TF2).
L'un des principaux éléments supplémentaires que j'inclus est,
tf.Variable
Convolution 1D
Voici comment faire une convolution 1D en utilisant TF 1 et TF 2.
Et pour être précis, mes données ont les formes suivantes,
[batch size, width, in channels]
(par exemple1, 5, 1
)[width, in channels, out channels]
(par exemple5, 1, 4
)[batch size, width, out_channels]
(par exemple1, 5, 4
)Exemple TF1
Exemple TF2
C'est beaucoup moins de travail avec TF2 que TF2 n'en a pas besoin
Session
etvariable_initializer
par exemple.À quoi cela pourrait-il ressembler dans la vraie vie?
Comprenons donc ce que cela fait en utilisant un exemple de lissage de signal. Sur la gauche, vous avez l'original et sur la droite, vous avez la sortie d'un Convolution 1D qui a 3 canaux de sortie.
Que signifient plusieurs canaux?
Les canaux multiples sont essentiellement des représentations d'entités multiples d'une entrée. Dans cet exemple, vous avez trois représentations obtenues par trois filtres différents. Le premier canal est le filtre de lissage à pondération égale. Le second est un filtre qui pondère le milieu du filtre plus que les limites. Le filtre final fait le contraire du second. Vous pouvez donc voir comment ces différents filtres produisent des effets différents.
Applications d'apprentissage profond de la convolution 1D
La convolution 1D a été utilisée avec succès pour la tâche de classification des phrases .
Convolution 2D
Arrêt à la convolution 2D. Si vous êtes une personne qui apprend en profondeur, les chances que vous n'ayez pas rencontré de convolution 2D sont… enfin nulles. Il est utilisé dans les CNN pour la classification d'images, la détection d'objets, etc. ainsi que dans les problèmes de PNL impliquant des images (par exemple, la génération de légendes d'images).
Essayons un exemple, j'ai un noyau de convolution avec les filtres suivants ici,
Et pour être précis, mes données ont les formes suivantes,
[batch_size, height, width, 1]
(par exemple1, 340, 371, 1
)[height, width, in channels, out channels]
(par exemple3, 3, 1, 3
)[batch_size, height, width, out_channels]
(par exemple1, 340, 371, 3
)Exemple TF1,
Exemple TF2
À quoi cela pourrait-il ressembler dans la vraie vie?
Ici vous pouvez voir la sortie produite par le code ci-dessus. La première image est l'original et dans le sens des aiguilles d'une montre, vous avez les sorties du 1er filtre, 2ème filtre et 3 filtres.
Que signifient plusieurs canaux?
Dans le contexte de la convolution 2D, il est beaucoup plus facile de comprendre ce que signifient ces multiples canaux. Disons que vous faites de la reconnaissance faciale. Vous pouvez penser à (c'est une simplification très irréaliste mais fait passer le point) à chaque filtre représentant un œil, une bouche, un nez, etc. De sorte que chaque carte de caractéristiques soit une représentation binaire de la présence ou non de cette caractéristique dans l'image que vous avez fournie . Je ne pense pas avoir besoin de souligner que pour un modèle de reconnaissance faciale, ce sont des fonctionnalités très précieuses. Plus d'informations dans cet article .
C'est une illustration de ce que j'essaye d'articuler.
Applications d'apprentissage en profondeur de la convolution 2D
La convolution 2D est très répandue dans le domaine de l'apprentissage profond.
Les CNN (Convolution Neural Networks) utilisent l'opération de convolution 2D pour presque toutes les tâches de vision par ordinateur (par exemple, classification d'images, détection d'objets, classification vidéo).
Convolution 3D
Maintenant, il devient de plus en plus difficile d'illustrer ce qui se passe à mesure que le nombre de dimensions augmente. Mais avec une bonne compréhension du fonctionnement de la convolution 1D et 2D, il est très simple de généraliser cette compréhension à la convolution 3D. Alors voilà.
Et pour être précis, mes données ont les formes suivantes,
[batch size, height, width, depth, in channels]
(par exemple1, 200, 200, 200, 1
)[height, width, depth, in channels, out channels]
(par exemple5, 5, 5, 1, 3
)[batch size, width, height, width, depth, out_channels]
(par exemple1, 200, 200, 2000, 3
)Exemple TF1
Exemple TF2
Applications d'apprentissage profond de la convolution 3D
La convolution 3D a été utilisée lors du développement d'applications d'apprentissage automatique impliquant des données LIDAR (Light Detection and Ranging) qui sont de nature tridimensionnelle.
Quoi ... plus de jargon?: Stride et rembourrage
D'accord, vous y êtes presque. Alors attendez. Voyons ce qu'est la foulée et le rembourrage. Ils sont assez intuitifs si vous pensez à eux.
Si vous traversez un couloir, vous y arrivez plus rapidement en moins d'étapes. Mais cela signifie également que vous avez observé un environnement moindre que si vous traversiez la pièce. Renforcez maintenant notre compréhension avec une jolie image aussi! Comprenons-les via la convolution 2D.
Comprendre la foulée
Lorsque vous utilisez
tf.nn.conv2d
par exemple, vous devez le définir comme un vecteur de 4 éléments. Il n'y a aucune raison d'être intimidé par cela. Il contient simplement les foulées dans l'ordre suivant.Convolution 2D -
[batch stride, height stride, width stride, channel stride]
. Ici, la foulée par lots et la foulée de canal que vous venez de définir sur un (j'implémente des modèles d'apprentissage en profondeur depuis 5 ans et je n'ai jamais eu à les définir sur autre chose). Cela ne vous laisse donc que 2 foulées à définir.Convolution 3D -
[batch stride, height stride, width stride, depth stride, channel stride]
. Ici, vous ne vous souciez que des foulées de hauteur / largeur / profondeur.Comprendre le rembourrage
Maintenant, vous remarquez que peu importe la taille de votre foulée (c'est-à-dire 1), il y a une réduction de dimension inévitable qui se produit pendant la convolution (par exemple, la largeur est de 3 après la convolution d'une image de 4 unités). Ceci n'est pas souhaitable, en particulier lors de la construction de réseaux de neurones à convolution profonde. C'est là que le rembourrage vient à la rescousse. Il existe deux types de rembourrage les plus couramment utilisés.
SAME
etVALID
Ci-dessous, vous pouvez voir la différence.
Dernier mot : si vous êtes très curieux, vous vous demandez peut-être. Nous venons de lancer une bombe sur toute la réduction automatique des dimensions et parlons maintenant de progrès différents. Mais la meilleure chose à propos de la foulée est que vous contrôlez quand et comment les dimensions sont réduites.
la source
CNN 1D, 2D ou 3D fait référence à la direction de convolution, plutôt qu'à la dimension d'entrée ou de filtre.
Pour une entrée de canal, CNN2D est égal à CNN1D est la longueur du noyau = longueur de l'entrée. (1 direction de conv.)
la source
En résumé, dans 1D CNN, le noyau se déplace dans une direction. Les données d'entrée et de sortie de 1D CNN sont à 2 dimensions. Principalement utilisé sur les données de séries chronologiques.
Dans CNN 2D, le noyau se déplace dans 2 directions. Les données d'entrée et de sortie de CNN 2D sont en 3 dimensions. Principalement utilisé sur les données d'image.
Dans 3D CNN, le noyau se déplace dans 3 directions. Les données d'entrée et de sortie du CNN 3D sont en 4 dimensions. Principalement utilisé sur les données d'image 3D (IRM, tomodensitométrie).
Vous pouvez trouver plus de détails ici: https://medium.com/@xzz201920/conv1d-conv2d-and-conv3d-8a59182c4d6
la source