Se usó la API de Cloud Translation para traducir esta página.
Switch to English

El modelo secuencial.

Ver en TensorFlow.org Ejecutar en Google Colab Ver código fuente en GitHub Descargar cuaderno

Preparar

 import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
 

Cuándo usar un modelo secuencial

Un modelo Sequential es apropiado para una pila simple de capas donde cada capa tiene exactamente un tensor de entrada y un tensor de salida .

Esquemáticamente, el siguiente modelo Sequential :

 # 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)
 

es equivalente a esta función:

 # 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 modelo secuencial no es apropiado cuando:

  • Su modelo tiene múltiples entradas o múltiples salidas
  • Cualquiera de sus capas tiene múltiples entradas o múltiples salidas
  • Necesitas compartir capas
  • Desea una topología no lineal (por ejemplo, una conexión residual, un modelo de varias ramas)

Crear un modelo secuencial

Puede crear un modelo secuencial pasando una lista de capas al constructor secuencial:

 model = keras.Sequential(
    [
        layers.Dense(2, activation="relu"),
        layers.Dense(3, activation="relu"),
        layers.Dense(4),
    ]
)
 

Se puede acceder a sus capas mediante el atributo de layers :

 model.layers
 
[<tensorflow.python.keras.layers.core.Dense at 0x7f37ffe66668>,
 <tensorflow.python.keras.layers.core.Dense at 0x7f37f553fc50>,
 <tensorflow.python.keras.layers.core.Dense at 0x7f37680de2b0>]

También puede crear un modelo secuencial de forma incremental a través del método add() :

 model = keras.Sequential()
model.add(layers.Dense(2, activation="relu"))
model.add(layers.Dense(3, activation="relu"))
model.add(layers.Dense(4))
 

Tenga en cuenta que también hay un método pop() correspondiente para eliminar capas: un modelo secuencial se comporta de manera muy similar a una lista de capas.

 model.pop()
print(len(model.layers))  # 2
 
2

También tenga en cuenta que el constructor secuencial acepta un argumento de name , al igual que cualquier capa o modelo en Keras. Esto es útil para anotar gráficos de TensorBoard con nombres semánticamente significativos.

 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"))
 

Especificar la forma de entrada de antemano

En general, todas las capas en Keras necesitan conocer la forma de sus entradas para poder crear sus pesos. Entonces, cuando crea una capa como esta, inicialmente, no tiene pesos:

 layer = layers.Dense(3)
layer.weights  # Empty
 
[]

Crea sus pesos la primera vez que se llama en una entrada, ya que la forma de los pesos depende de la forma de las entradas:

 # 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.8131663 , -0.49988765, -0.02397203],
        [-0.3190418 ,  0.01101786,  0.85226357],
        [-0.602435  , -0.10381919,  0.63280225],
        [-0.3388477 ,  0.11859643, -0.10677373]], dtype=float32)>,
 <tf.Variable 'dense_6/bias:0' shape=(3,) dtype=float32, numpy=array([0., 0., 0.], dtype=float32)>]

Naturalmente, esto también se aplica a los modelos secuenciales. Cuando crea una instancia de un modelo secuencial sin una forma de entrada, no se "construye": no tiene pesos (y al llamar a model.weights produce un error que indica esto). Los pesos se crean cuando el modelo ve por primera vez algunos datos de entrada:

 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 vez que se "construye" un modelo, puede llamar a su método summary() para mostrar su contenido:

 model.summary()
 
Model: "sequential_3"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_7 (Dense)              multiple                  10        
_________________________________________________________________
dense_8 (Dense)              multiple                  9         
_________________________________________________________________
dense_9 (Dense)              multiple                  16        
=================================================================
Total params: 35
Trainable params: 35
Non-trainable params: 0
_________________________________________________________________

Sin embargo, puede ser muy útil cuando se construye un modelo secuencial de forma incremental para poder mostrar el resumen del modelo hasta el momento, incluida la forma de salida actual. En este caso, debe comenzar su modelo pasando un objeto de Input a su modelo, para que conozca su forma de entrada desde el principio:

 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
_________________________________________________________________

Tenga en cuenta que el objeto de Input no se muestra como parte de model.layers , ya que no es una capa:

 model.layers
 
[<tensorflow.python.keras.layers.core.Dense at 0x7f37680deb00>]

Una alternativa simple es simplemente pasar un argumento input_shape a su primera capa:

 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
_________________________________________________________________

Los modelos construidos con una forma de entrada predefinida como esta siempre tienen pesos (incluso antes de ver los datos) y siempre tienen una forma de salida definida.

En general, se recomienda especificar siempre la forma de entrada de un modelo secuencial de antemano si sabe cuál es.

Un flujo de trabajo de depuración común: add() + summary()

Al crear una nueva arquitectura secuencial, es útil apilar capas de forma incremental con add() e imprimir resúmenes de modelos con frecuencia. Por ejemplo, esto le permite controlar cómo una pila de capas Conv2D y MaxPooling2D está MaxPooling2D muestreo de los mapas de características de imagen:

 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
_________________________________________________________________

Muy práctico, ¿verdad?

Qué hacer una vez que tenga un modelo

Una vez que la arquitectura de su modelo esté lista, querrá:

Extracción de características con un modelo secuencial

Una vez que se ha creado un modelo secuencial, se comporta como un modelo API funcional . Esto significa que cada capa tiene un atributo de input y output . Estos atributos se pueden usar para hacer cosas ordenadas, como crear rápidamente un modelo que extraiga los resultados de todas las capas intermedias en un modelo secuencial:

 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)
 

Aquí hay un ejemplo similar que solo extrae entidades de una capa:

 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)
 

Transferir el aprendizaje con un modelo secuencial

El aprendizaje de transferencia consiste en congelar las capas inferiores en un modelo y solo entrenar las capas superiores. Si no está familiarizado con él, asegúrese de leer nuestra guía para transferir el aprendizaje .

Aquí hay dos planos comunes de aprendizaje de transferencia que involucran modelos secuenciales.

Primero, supongamos que tiene un modelo secuencial y desea congelar todas las capas excepto la última. En este caso, simplemente debería iterar sobre model.layers y establecer layer.trainable = False en cada capa, excepto en la última. Me gusta esto:

 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(...)
 

Otro plan común es usar un modelo secuencial para apilar un modelo previamente entrenado y algunas capas de clasificación recién inicializadas. Me gusta esto:

 # 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 transfiere el aprendizaje, probablemente se encontrará con frecuencia usando estos dos patrones.

¡Eso es todo lo que necesita saber sobre los modelos secuenciales!

Para obtener más información sobre la construcción de modelos en Keras, consulte: