186 votes

Quel est le rôle de "Flatten" dans Keras ?

J'essaie de comprendre le rôle de la Flatten dans Keras. Voici mon code, qui est un simple réseau à deux couches. Il prend en entrée des données bidimensionnelles de forme (3, 2), et sort des données unidimensionnelles de forme (1, 4) :

model = Sequential()
model.add(Dense(16, input_shape=(3, 2)))
model.add(Activation('relu'))
model.add(Flatten())
model.add(Dense(4))
model.compile(loss='mean_squared_error', optimizer='SGD')

x = np.array([[[1, 2], [3, 4], [5, 6]]])

y = model.predict(x)

print y.shape

Cela imprime que y a la forme (1, 4). Cependant, si je supprime le Flatten la ligne, puis il imprime que y a la forme (1, 3, 4).

Je ne comprends pas. D'après ce que je comprends des réseaux neuronaux, le model.add(Dense(16, input_shape=(3, 2))) crée une couche cachée entièrement connectée, avec 16 nœuds. Chacun de ces nœuds est connecté à chacun des 3x2 éléments d'entrée. Par conséquent, les 16 nœuds à la sortie de cette première couche sont déjà "plats". Ainsi, la forme de la sortie de la première couche devrait être (1, 16). Ensuite, la deuxième couche prend cette forme en entrée et produit des données de forme (1, 4).

Donc, si la sortie de la première couche est déjà "plate" et de forme (1, 16), pourquoi dois-je l'aplatir davantage ?

0 votes

Il peut être utile de comprendre Flatten en le comparant à GlobalPooling. stackoverflow.com/a/63502664/10375049

181voto

Marcin Możejko Points 19602

Si vous lisez l'entrée de la documentation de Keras pour Dense vous verrez que cet appel :

Dense(16, input_shape=(5,3))

entraînerait une Dense avec 3 entrées et 16 sorties qui seraient appliquées indépendamment pour chacune des 5 étapes. Ainsi, si D(x) transforme un vecteur à 3 dimensions en un vecteur à 16 dimensions, ce que vous obtiendrez en sortie de votre couche sera une séquence de vecteurs : [D(x[0,:]), D(x[1,:]),..., D(x[4,:])] avec forme (5, 16) . Pour obtenir le comportement que vous avez spécifié, vous devez d'abord Flatten votre entrée à un vecteur 15-d et ensuite appliquer Dense :

model = Sequential()
model.add(Flatten(input_shape=(3, 2)))
model.add(Dense(16))
model.add(Activation('relu'))
model.add(Dense(4))
model.compile(loss='mean_squared_error', optimizer='SGD')

EDIT : Comme certaines personnes ont eu du mal à comprendre - voici une image explicative :

enter image description here

0 votes

Merci pour votre explication. Juste pour clarifier cependant : avec Dense(16, input_shape=(5,3) Chaque neurone de sortie de l'ensemble de 16 (et, pour les 5 ensembles de ces neurones), sera-t-il connecté à tous les (3 x 5 = 15) neurones d'entrée ? Ou bien chaque neurone du premier ensemble de 16 sera-t-il seulement connecté aux 3 neurones du premier ensemble de 5 neurones d'entrée, puis chaque neurone du deuxième ensemble de 16 sera seulement connecté aux 3 neurones du deuxième ensemble de 5 neurones d'entrée, etc..... Je ne sais pas de quoi il s'agit !

1 votes

Vous avez une couche dense qui reçoit 3 neurones et une sortie de 16 qui est appliquée à chacun des 5 ensembles de 3 neurones.

0 votes

Mais les neurones de sortie n'ont-ils pas des connexions avec les 5 ensembles de neurones d'entrée ? La raison pour laquelle j'ai pensé que cela pourrait être le cas, est que dans les réseaux convolutifs, chaque carte de caractéristiques de la première couche prend en entrée les trois canaux (R, G, B) de l'entrée.

111voto

Mahesh Kembhavi Points 767

enter image description here Voici comment Flatten fonctionne en convertissant une matrice en un tableau unique.

44 votes

Oui, mais pourquoi Est-ce nécessaire ? C'est la vraie question, je pense.

2 votes

Merci pour cette figure !

1 votes

Une image vaut mille mots

54voto

prosti Points 4630

courte lecture :

Aplatir un tenseur signifie supprimer toutes les dimensions sauf une. C'est exactement ce que fait la couche Flatten.

longue lecture :

Si nous prenons en considération le modèle original (avec la couche Flatten) créé, nous pouvons obtenir le résumé de modèle suivant :

Layer (type)                 Output Shape              Param #   
=================================================================
D16 (Dense)                  (None, 3, 16)             48        
_________________________________________________________________
A (Activation)               (None, 3, 16)             0         
_________________________________________________________________
F (Flatten)                  (None, 48)                0         
_________________________________________________________________
D4 (Dense)                   (None, 4)                 196       
=================================================================
Total params: 244
Trainable params: 244
Non-trainable params: 0

Pour ce résumé, l'image suivante fournira, nous l'espérons, un peu plus de sens sur les tailles d'entrée et de sortie pour chaque couche.

La forme de sortie pour la couche d'aplatissement est, comme vous pouvez le lire, la suivante (None, 48) . Voici le conseil. Vous devriez le lire (1, 48) ou (2, 48) ou ... ou (16, 48) ... ou (32, 48) , ...

En fait, None sur cette position signifie n'importe quelle taille de lot. Pour les entrées à rappeler, la première dimension signifie la taille du lot et la seconde signifie le nombre de caractéristiques d'entrée.

Le rôle de la Aplatir la couche dans Keras est très simple :

Une opération d'aplatissement sur un tenseur redonne au tenseur une forme égale au nombre d'éléments contenus dans le tenseur. sans inclure la dimension du lot .

enter image description here


Note : J'ai utilisé le model.summary() pour fournir les détails de la forme et des paramètres de sortie.

2 votes

Vous avez dit None signifie n'importe quelle taille de lot, mais pourquoi la forme de sortie de D16 a également None n'est pas 3 la taille du lot ?

1 votes

Non, ce n'est pas le cas : vous pouvez choisir n'importe quelle taille de lot, d'après ce que j'ai compris. Comment êtes-vous parvenu au résultat que la taille du lot debe être 3 ?

4voto

AEngineer Points 102

Je suis tombé sur ce texte récemment, il m'a certainement aidé à comprendre : https://www.cs.ryerson.ca/~aharley/vis/conv/

Il y a donc une entrée, un Conv2D, un MaxPooling2D, etc. Les couches d'aplatissement se trouvent à la fin et montrent exactement comment elles sont formées et comment elles définissent les classifications finales (0-9).

1 votes

C'est génial. Plus encore ici. cs.cmu.edu/~aharley/vis

3voto

Pratima Rathore Points 21

En règle générale, la première couche de votre réseau doit avoir la même forme que vos données. Par exemple, nos données sont des images de 28x28, et 28 couches de 28 neurones seraient infaisables, il est donc plus logique d'aplatir ces 28,28 en 784x1. Au lieu d'écrire tout le code pour gérer cela nous-mêmes, nous ajoutons la couche Flatten() au début, et lorsque les tableaux sont chargés dans le modèle plus tard, ils seront automatiquement aplatis pour nous.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X