![]() | ![]() | ![]() | ![]() |
Installer
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
Quand utiliser un modèle séquentiel
Un modèle Sequential
est approprié pour une pile simple de couches où chaque couche a exactement un tenseur d'entrée et un tenseur de sortie .
Schématiquement, le modèle Sequential
suivant:
# 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 n'est pas approprié lorsque:
- Votre modèle a plusieurs entrées ou plusieurs sorties
- Chacune de vos couches a plusieurs entrées ou plusieurs sorties
- Vous devez faire un partage de couches
- Vous voulez une topologie non linéaire (par exemple une connexion résiduelle, un modèle multi-branches)
Créer un modèle séquentiel
Vous pouvez créer un modèle séquentiel en passant une liste de couches au constructeur séquentiel:
model = keras.Sequential(
[
layers.Dense(2, activation="relu"),
layers.Dense(3, activation="relu"),
layers.Dense(4),
]
)
Ses couches sont accessibles via l'attribut layers
:
model.layers
[<tensorflow.python.keras.layers.core.Dense at 0x7fcf2e879978>, <tensorflow.python.keras.layers.core.Dense at 0x7fcfdad262b0>, <tensorflow.python.keras.layers.core.Dense at 0x7fcf2c237b70>]
Vous pouvez également créer un modèle séquentiel de manière incrémentielle via la méthode add()
:
model = keras.Sequential()
model.add(layers.Dense(2, activation="relu"))
model.add(layers.Dense(3, activation="relu"))
model.add(layers.Dense(4))
Notez qu'il existe également une méthode pop()
correspondante pour supprimer des calques: un modèle séquentiel se comporte comme une liste de calques.
model.pop()
print(len(model.layers)) # 2
2
Notez également que le constructeur Sequential accepte un argument de name
, comme n'importe quel calque ou modèle dans 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
En règle générale, toutes les couches de Keras doivent connaître la forme de leurs entrées afin de pouvoir créer leurs pondérations. 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, car 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.6612724 , 0.23639882, -0.17644602], [ 0.01855636, -0.7009475 , -0.05331248], [ 0.11539507, 0.03737205, -0.7473268 ], [ 0.45032406, 0.13835168, -0.1536408 ]], 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 forme d'entrée, il n'est pas "construit": il n'a pas de poids (et l'appel de model.weights
entraîne une erreur indiquant simplement cela). Les pondérations sont créées 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 sa méthode summary()
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 construction 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 devez démarrer votre modèle en passant un objet Input
à votre modèle, afin qu'il connaisse 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'objet Input
n'est pas affiché dans le cadre de model.layers
, car il ne s'agit pas d'un calque:
model.layers
[<tensorflow.python.keras.layers.core.Dense at 0x7fcf2c24aac8>]
Une alternative simple est de simplement passer un argument input_shape
à 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 créés avec une forme d'entrée prédéfinie comme celle-ci ont toujours des pondérations (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 à l'avance la forme d'entrée d'un modèle séquentiel si vous savez de quoi il s'agit.
Un workflow de débogage courant: add()
+ summary()
Lors de la création d'une nouvelle architecture séquentielle, il est utile d'empiler de manière incrémentielle les couches avec add()
et d'imprimer fréquemment des résumés de modèles. Par exemple, cela vous permet de surveiller comment une pile de couches Conv2D
et MaxPooling2D
-échantillonne les cartes d' MaxPooling2D
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 que votre architecture de modèle est prête, vous voudrez:
- Entraînez votre modèle, évaluez-le et exécutez des inférences. Consultez notre guide de formation et d'évaluation avec les boucles intégrées
- Enregistrez votre modèle sur le disque et restaurez-le. Consultez notre guide de sérialisation et d'enregistrement .
- Accélérez la formation des modèles en tirant parti de plusieurs GPU. Consultez notre guide sur la formation multi-GPU et 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 d'API fonctionnelle . Cela signifie que chaque couche a un attribut d' input
et de output
. 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 seule 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)
Transfert d'apprentissage avec un modèle séquentiel
L'apprentissage par transfert consiste à figer les couches inférieures dans un modèle et à entraîner uniquement les couches supérieures. Si vous ne le connaissez pas, assurez-vous de lire notre guide pour transférer l'apprentissage .
Voici deux plans courants d'apprentissage par transfert impliquant des modèles séquentiels.
Tout d'abord, disons que vous avez un modèle séquentiel et que vous souhaitez figer tous les calques sauf le dernier. Dans ce cas, vous model.layers
simplement sur model.layers
et définissez layer.trainable = False
sur chaque calque, sauf le 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 effectuez un transfert d'apprentissage, vous vous retrouverez probablement à utiliser fréquemment 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, voir: