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

El modelo secuencial

Ver en TensorFlow.org Ver 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
  • Quiere una topología no lineal (por ejemplo, una conexión residual, un modelo de varias ramas)

Creando 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),
    ]
)

Sus capas son accesibles a través del atributo de layers :

model.layers
[<tensorflow.python.keras.layers.core.Dense at 0x7f7d1d5c7898>,
 <tensorflow.python.keras.layers.core.Dense at 0x7f7d2f6e0a20>,
 <tensorflow.python.keras.layers.core.Dense at 0x7f7d16beb9b0>]

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 , como 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

Generalmente, todas las capas de 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.06262648,  0.36915624, -0.27826005],
        [-0.6703571 , -0.03467071,  0.80370367],
        [-0.00725174,  0.19120002,  0.34244013],
        [-0.20762473, -0.31104177, -0.26624495]], 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 está "construido": no tiene pesos (y llamar a model.weights da model.weights resultado un error que indica solo 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 un modelo está "construido", puede llamar a su método summary() para mostrar su contenido:

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
_________________________________________________________________

Sin embargo, puede ser muy útil cuando se crea 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 iniciar 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 0x7f7d16b870f0>]

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 cualquier dato) y siempre tienen una forma de salida definida.

En general, es una buena práctica recomendada especificar siempre la forma de entrada de un modelo secuencial por adelantado si sabe cuál es.

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

Al construir una nueva arquitectura secuencial, es útil apilar capas incrementalmente con add() e imprimir con frecuencia resúmenes de modelos. Por ejemplo, esto le permite monitorear cómo una pila de capas Conv2D y MaxPooling2D está MaxPooling2D 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 de API funcional . Esto significa que cada capa tiene un atributo de input y output . Estos atributos se pueden usar para hacer cosas interesantes, como crear rápidamente un modelo que extrae 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 características 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 por 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 por transferencia que involucran modelos secuenciales.

Primero, digamos que tiene un modelo secuencial y desea congelar todas las capas excepto la última. En este caso, simplemente model.layers sobre model.layers y establecería 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 utilizar 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á utilizando con frecuencia 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: