Voir sur TensorFlow.org | Exécuter dans Google Colab | Voir la source sur GitHub | Télécharger le cahier |
Installer
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
Quand utiliser un modèle séquentiel
Un Sequential
modèle est approprié pour un empilement simple de couches où chaque couche a exactement un tenseur d'entrée et une tenseur de sortie.
Schématiquement, le suivant Sequential
modèle:
# Define Sequential model with 3 layers
model = keras.Sequential(
[
layers.Dense(2, activation="relu", name="layer1"),
layers.Dense(3, activation="relu", name="layer2"),
layers.Dense(4, name="layer3"),
]
)
# Call model on a test input
x = tf.ones((3, 3))
y = model(x)
équivaut à cette fonction :
# Create 3 layers
layer1 = layers.Dense(2, activation="relu", name="layer1")
layer2 = layers.Dense(3, activation="relu", name="layer2")
layer3 = layers.Dense(4, name="layer3")
# Call layers on a test input
x = tf.ones((3, 3))
y = layer3(layer2(layer1(x)))
Un modèle séquentiel ne convient pas de les cas suivants :
- Votre modèle a plusieurs entrées ou plusieurs sorties
- Chacune de vos couches a plusieurs entrées ou plusieurs sorties
- Vous devez faire le partage de couche
- Vous voulez une topologie non linéaire (par exemple une connexion résiduelle, un modèle multi-branches)
Création d'un modèle séquentiel
Vous pouvez créer un modèle Sequential en passant une liste de couches au constructeur Sequential :
model = keras.Sequential(
[
layers.Dense(2, activation="relu"),
layers.Dense(3, activation="relu"),
layers.Dense(4),
]
)
Ses couches sont accessibles via les layers
attribut:
model.layers
[<keras.layers.core.Dense at 0x7fdc784478d0>, <keras.layers.core.Dense at 0x7fdbbc3c4650>, <keras.layers.core.Dense at 0x7fdbbc3c4a10>]
Vous pouvez également créer un modèle séquentiel progressivement par l' add()
méthode:
model = keras.Sequential()
model.add(layers.Dense(2, activation="relu"))
model.add(layers.Dense(3, activation="relu"))
model.add(layers.Dense(4))
A noter qu'il existe aussi un correspondant pop()
méthode pour éliminer les couches: un modèle séquentiel se comporte très bien comme une liste de couches.
model.pop()
print(len(model.layers)) # 2
2
A noter également que le constructeur séquentiel accepte un name
argument comme une couche ou d'un modèle en Keras. Ceci est utile pour annoter les graphiques TensorBoard avec des noms sémantiquement significatifs.
model = keras.Sequential(name="my_sequential")
model.add(layers.Dense(2, activation="relu", name="layer1"))
model.add(layers.Dense(3, activation="relu", name="layer2"))
model.add(layers.Dense(4, name="layer3"))
Spécification de la forme d'entrée à l'avance
Généralement, toutes les couches de Keras ont besoin de connaître la forme de leurs entrées afin de pouvoir créer leurs poids. Ainsi, lorsque vous créez un calque comme celui-ci, au départ, il n'a pas de poids :
layer = layers.Dense(3)
layer.weights # Empty
[]
Il crée ses poids la première fois qu'il est appelé sur une entrée, puisque la forme des poids dépend de la forme des entrées :
# Call layer on a test input
x = tf.ones((1, 4))
y = layer(x)
layer.weights # Now it has weights, of shape (4, 3) and (3,)
[<tf.Variable 'dense_6/kernel:0' shape=(4, 3) dtype=float32, numpy= array([[ 0.5319189 , -0.8767905 , -0.63919735], [-0.6276014 , 0.1689707 , -0.57695866], [ 0.6710613 , 0.5354214 , -0.00893992], [ 0.15670097, -0.15280598, 0.8865864 ]], dtype=float32)>, <tf.Variable 'dense_6/bias:0' shape=(3,) dtype=float32, numpy=array([0., 0., 0.], dtype=float32)>]
Naturellement, cela s'applique également aux modèles séquentiels. Lorsque vous instanciez un modèle séquentiel sans une forme d'entrée, il est pas « construit »: il n'a pas de poids (et appelant model.weights
résultats dans une erreur indiquant que cela). Les poids sont créés lorsque le modèle voit pour la première fois des données d'entrée :
model = keras.Sequential(
[
layers.Dense(2, activation="relu"),
layers.Dense(3, activation="relu"),
layers.Dense(4),
]
) # No weights at this stage!
# At this point, you can't do this:
# model.weights
# You also can't do this:
# model.summary()
# Call the model on a test input
x = tf.ones((1, 4))
y = model(x)
print("Number of weights after calling the model:", len(model.weights)) # 6
Number of weights after calling the model: 6
Une fois qu'un modèle est « construit », vous pouvez appeler son summary()
méthode pour afficher son contenu:
model.summary()
Model: "sequential_3" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= dense_7 (Dense) (1, 2) 10 _________________________________________________________________ dense_8 (Dense) (1, 3) 9 _________________________________________________________________ dense_9 (Dense) (1, 4) 16 ================================================================= Total params: 35 Trainable params: 35 Non-trainable params: 0 _________________________________________________________________
Cependant, il peut être très utile lors de la création incrémentielle d'un modèle séquentiel de pouvoir afficher le résumé du modèle jusqu'à présent, y compris la forme de sortie actuelle. Dans ce cas, vous devriez commencer votre modèle en passant une Input
objet à votre modèle, de sorte qu'il connaît sa forme d'entrée depuis le début:
model = keras.Sequential()
model.add(keras.Input(shape=(4,)))
model.add(layers.Dense(2, activation="relu"))
model.summary()
Model: "sequential_4" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= dense_10 (Dense) (None, 2) 10 ================================================================= Total params: 10 Trainable params: 10 Non-trainable params: 0 _________________________________________________________________
Notez que l' Input
objet n'apparaît pas dans le cadre de model.layers
, puisqu'il n'est pas une couche:
model.layers
[<keras.layers.core.Dense at 0x7fdbbc37c390>]
Une alternative simple est de passer juste un input_shape
argument à votre première couche:
model = keras.Sequential()
model.add(layers.Dense(2, activation="relu", input_shape=(4,)))
model.summary()
Model: "sequential_5" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= dense_11 (Dense) (None, 2) 10 ================================================================= Total params: 10 Trainable params: 10 Non-trainable params: 0 _________________________________________________________________
Les modèles construits avec une forme d'entrée prédéfinie comme celle-ci ont toujours des poids (même avant de voir des données) et ont toujours une forme de sortie définie.
En général, il est recommandé de toujours spécifier la forme d'entrée d'un modèle séquentiel à l'avance si vous savez de quoi il s'agit.
Un flux de travail de débogage commun: add()
+ summary()
Lors de la construction d' une nouvelle architecture séquentielle, il est utile d'empiler progressivement des couches avec add()
et souvent imprimer des résumés de modèle. Par exemple, cela vous permet de surveiller comment une pile de Conv2D
et MaxPooling2D
couches est sous - échantillonnage des cartes de caractéristiques d'image:
model = keras.Sequential()
model.add(keras.Input(shape=(250, 250, 3))) # 250x250 RGB images
model.add(layers.Conv2D(32, 5, strides=2, activation="relu"))
model.add(layers.Conv2D(32, 3, activation="relu"))
model.add(layers.MaxPooling2D(3))
# Can you guess what the current output shape is at this point? Probably not.
# Let's just print it:
model.summary()
# The answer was: (40, 40, 32), so we can keep downsampling...
model.add(layers.Conv2D(32, 3, activation="relu"))
model.add(layers.Conv2D(32, 3, activation="relu"))
model.add(layers.MaxPooling2D(3))
model.add(layers.Conv2D(32, 3, activation="relu"))
model.add(layers.Conv2D(32, 3, activation="relu"))
model.add(layers.MaxPooling2D(2))
# And now?
model.summary()
# Now that we have 4x4 feature maps, time to apply global max pooling.
model.add(layers.GlobalMaxPooling2D())
# Finally, we add a classification layer.
model.add(layers.Dense(10))
Model: "sequential_6" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= conv2d (Conv2D) (None, 123, 123, 32) 2432 _________________________________________________________________ conv2d_1 (Conv2D) (None, 121, 121, 32) 9248 _________________________________________________________________ max_pooling2d (MaxPooling2D) (None, 40, 40, 32) 0 ================================================================= Total params: 11,680 Trainable params: 11,680 Non-trainable params: 0 _________________________________________________________________ Model: "sequential_6" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= conv2d (Conv2D) (None, 123, 123, 32) 2432 _________________________________________________________________ conv2d_1 (Conv2D) (None, 121, 121, 32) 9248 _________________________________________________________________ max_pooling2d (MaxPooling2D) (None, 40, 40, 32) 0 _________________________________________________________________ conv2d_2 (Conv2D) (None, 38, 38, 32) 9248 _________________________________________________________________ conv2d_3 (Conv2D) (None, 36, 36, 32) 9248 _________________________________________________________________ max_pooling2d_1 (MaxPooling2 (None, 12, 12, 32) 0 _________________________________________________________________ conv2d_4 (Conv2D) (None, 10, 10, 32) 9248 _________________________________________________________________ conv2d_5 (Conv2D) (None, 8, 8, 32) 9248 _________________________________________________________________ max_pooling2d_2 (MaxPooling2 (None, 4, 4, 32) 0 ================================================================= Total params: 48,672 Trainable params: 48,672 Non-trainable params: 0 _________________________________________________________________
Très pratique, non ?
Que faire une fois que vous avez un modèle
Une fois l'architecture de votre modèle prête, vous voudrez :
- Entraînez votre modèle, évaluez-le et exécutez l'inférence. Voir notre guide pour la formation et l' évaluation avec les boucles intégrées
- Enregistrez votre modèle sur le disque et restaurez-le. Voir notre guide sérialisation et économie .
- Accélérez l'entraînement des modèles en tirant parti de plusieurs GPU. Voir notre guide multi-GPU et de la formation distribuée .
Extraction de caractéristiques avec un modèle séquentiel
Une fois qu'un modèle séquentiel a été construit, il se comporte comme un modèle API fonctionnelle . Cela signifie que chaque couche a une input
et output
attribut. Ces attributs peuvent être utilisés pour faire des choses intéressantes, comme créer rapidement un modèle qui extrait les sorties de toutes les couches intermédiaires dans un modèle séquentiel :
initial_model = keras.Sequential(
[
keras.Input(shape=(250, 250, 3)),
layers.Conv2D(32, 5, strides=2, activation="relu"),
layers.Conv2D(32, 3, activation="relu"),
layers.Conv2D(32, 3, activation="relu"),
]
)
feature_extractor = keras.Model(
inputs=initial_model.inputs,
outputs=[layer.output for layer in initial_model.layers],
)
# Call feature extractor on test input.
x = tf.ones((1, 250, 250, 3))
features = feature_extractor(x)
Voici un exemple similaire qui extrait uniquement les entités d'une couche :
initial_model = keras.Sequential(
[
keras.Input(shape=(250, 250, 3)),
layers.Conv2D(32, 5, strides=2, activation="relu"),
layers.Conv2D(32, 3, activation="relu", name="my_intermediate_layer"),
layers.Conv2D(32, 3, activation="relu"),
]
)
feature_extractor = keras.Model(
inputs=initial_model.inputs,
outputs=initial_model.get_layer(name="my_intermediate_layer").output,
)
# Call feature extractor on test input.
x = tf.ones((1, 250, 250, 3))
features = feature_extractor(x)
Transférer l'apprentissage avec un modèle séquentiel
L'apprentissage par transfert consiste à figer les couches inférieures dans un modèle et à n'entraîner que les couches supérieures. Si vous n'êtes pas familier avec, assurez - vous de lire notre guide pour l' apprentissage de transfert .
Voici deux modèles courants d'apprentissage par transfert impliquant des modèles séquentiels.
Tout d'abord, supposons que vous ayez un modèle séquentiel et que vous souhaitiez geler tous les calques sauf le dernier. Dans ce cas, vous simplement itérer sur model.layers
et ensemble layer.trainable = False
sur chaque couche, à l' exception du dernier. Comme ça:
model = keras.Sequential([
keras.Input(shape=(784)),
layers.Dense(32, activation='relu'),
layers.Dense(32, activation='relu'),
layers.Dense(32, activation='relu'),
layers.Dense(10),
])
# Presumably you would want to first load pre-trained weights.
model.load_weights(...)
# Freeze all layers except the last one.
for layer in model.layers[:-1]:
layer.trainable = False
# Recompile and train (this will only update the weights of the last layer).
model.compile(...)
model.fit(...)
Un autre modèle courant consiste à utiliser un modèle séquentiel pour empiler un modèle pré-entraîné et des couches de classification fraîchement initialisées. Comme ça:
# Load a convolutional base with pre-trained weights
base_model = keras.applications.Xception(
weights='imagenet',
include_top=False,
pooling='avg')
# Freeze the base model
base_model.trainable = False
# Use a Sequential model to add a trainable classifier on top
model = keras.Sequential([
base_model,
layers.Dense(1000),
])
# Compile & train
model.compile(...)
model.fit(...)
Si vous transférez l'apprentissage, vous vous retrouverez probablement fréquemment à utiliser ces deux modèles.
C'est à peu près tout ce que vous devez savoir sur les modèles séquentiels !
Pour en savoir plus sur la création de modèles dans Keras, consultez :