Visualizza su TensorFlow.org | Esegui in Google Colab | Visualizza la fonte su GitHub | Scarica taccuino |
Impostare
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
Quando utilizzare un modello sequenziale
Una Sequential
modello è adatto per una pila di strati piana dove ogni strato ha esattamente un tensore di ingresso ed uno di uscita tensore.
Schematicamente, il seguente Sequential
del modello:
# 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)
è equivalente a questa funzione:
# 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)))
Modello A sequenziale non è appropriata quando:
- Il tuo modello ha più ingressi o più uscite
- Ciascuno dei tuoi livelli ha più ingressi o più uscite
- Devi fare la condivisione dei livelli
- Si desidera una topologia non lineare (ad es. una connessione residua, un modello multiramo)
Creazione di un modello sequenziale
Puoi creare un modello sequenziale passando un elenco di livelli al costruttore sequenziale:
model = keras.Sequential(
[
layers.Dense(2, activation="relu"),
layers.Dense(3, activation="relu"),
layers.Dense(4),
]
)
I suoi strati sono accessibili tramite layers
attributo:
model.layers
[<keras.layers.core.Dense at 0x7fdc784478d0>, <keras.layers.core.Dense at 0x7fdbbc3c4650>, <keras.layers.core.Dense at 0x7fdbbc3c4a10>]
È inoltre possibile creare un modello sequenziale in modo incrementale tramite l' add()
Metodo:
model = keras.Sequential()
model.add(layers.Dense(2, activation="relu"))
model.add(layers.Dense(3, activation="relu"))
model.add(layers.Dense(4))
Nota che c'è anche un corrispondente pop()
metodo per rimuovere gli strati: un modello sequenziale si comporta molto simile a un elenco dei livelli.
model.pop()
print(len(model.layers)) # 2
2
Si noti inoltre che il costruttore sequenziale accetta un name
argomento, proprio come qualsiasi livello o modello Keras. Questo è utile per annotare i grafici TensorBoard con nomi semanticamente significativi.
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"))
Specificare in anticipo la forma di input
In genere, tutti i livelli in Keras devono conoscere la forma dei loro input per poter creare i loro pesi. Quindi, quando crei un livello come questo, inizialmente, non ha pesi:
layer = layers.Dense(3)
layer.weights # Empty
[]
Crea i suoi pesi la prima volta che viene chiamato su un input, poiché la forma dei pesi dipende dalla forma degli input:
# 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)>]
Naturalmente, questo vale anche per i modelli sequenziali. Quando si crea un'istanza di un modello sequenziale, senza una forma di ingresso, non è "costruito": non ha pesi (e chiamando model.weights
risultati in un errore che indica proprio questo). I pesi vengono creati quando il modello vede per la prima volta alcuni dati di input:
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
Una volta che un modello è "costruito", è possibile chiamare la sua summary()
metodo per visualizzare il suo contenuto:
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 _________________________________________________________________
Tuttavia, può essere molto utile quando si costruisce un modello sequenziale in modo incrementale per essere in grado di visualizzare il riepilogo del modello fino a quel momento, inclusa la forma di output corrente. In questo caso, si dovrebbe iniziare il vostro modello passando un Input
oggetto al modello, in modo che conosce la sua forma di ingresso fin dall'inizio:
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 _________________________________________________________________
Si noti che l' Input
oggetto non viene visualizzato come parte di model.layers
, in quanto non è un livello:
model.layers
[<keras.layers.core.Dense at 0x7fdbbc37c390>]
Una semplice alternativa è quella di passare solo un input_shape
argomento per il vostro primo strato:
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 _________________________________________________________________
I modelli creati con una forma di input predefinita come questa hanno sempre dei pesi (anche prima di visualizzare i dati) e hanno sempre una forma di output definita.
In generale, è consigliabile specificare sempre in anticipo la forma di input di un modello sequenziale, se si sa di cosa si tratta.
Un flusso di lavoro di debug comuni: add()
+ summary()
Quando si costruisce una nuova architettura sequenziale, è utile per impilare in modo incrementale strati con add()
e spesso stampare riepiloghi modello. Per esempio, questo consente di monitorare come una pila di Conv2D
e MaxPooling2D
strati è downsampling mappe funzione di immagine:
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 _________________________________________________________________
Molto pratico, vero?
Cosa fare una volta che hai un modello
Una volta che l'architettura del modello è pronta, vorrai:
- Addestra il tuo modello, valutalo ed esegui l'inferenza. Vedi la nostra guida per la formazione e la valutazione con l'in-built loop
- Salva il tuo modello su disco e ripristinalo. Vedi la nostra guida alla serializzazione e risparmio .
- Velocizza l'addestramento del modello sfruttando più GPU. Vedi la nostra guida per multi-GPU e la formazione distribuita .
Estrazione di feature con un modello sequenziale
Una volta che un modello sequenziale è stato costruito, si comporta come un modello di API funzionale . Ciò significa che ogni strato ha un input
e output
attributo. Questi attributi possono essere usati per fare cose pulite, come creare rapidamente un modello che estrae gli output di tutti i livelli intermedi in un modello sequenziale:
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)
Ecco un esempio simile che estrae le feature solo da un livello:
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)
Trasferire l'apprendimento con un modello sequenziale
L'apprendimento del trasferimento consiste nel congelare i livelli inferiori in un modello e addestrare solo i livelli superiori. Se non si ha familiarità con esso, assicuratevi di leggere la nostra guida per l'apprendimento di trasferimento .
Ecco due progetti comuni di apprendimento del trasferimento che coinvolgono i modelli sequenziali.
Innanzitutto, supponiamo che tu abbia un modello sequenziale e desideri congelare tutti i livelli tranne l'ultimo. In questo caso, si sarebbe semplicemente iterare sopra model.layers
e set layer.trainable = False
su ogni livello, tranne l'ultimo. Come questo:
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 altro progetto comune consiste nell'utilizzare un modello sequenziale per impilare un modello pre-addestrato e alcuni livelli di classificazione appena inizializzati. Come questo:
# 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(...)
Se trasferisci l'apprendimento, probabilmente ti ritroverai a utilizzare spesso questi due schemi.
Questo è tutto ciò che devi sapere sui modelli sequenziali!
Per saperne di più sulla creazione di modelli in Keras, vedere: