Veja no TensorFlow.org | Executar no Google Colab | Ver fonte no GitHub | Baixar caderno |
Configurar
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
Quando usar um modelo sequencial
Um Sequential
modelo é apropriado para uma pilha de camadas simples, onde cada camada tem exactamente um tensor de entrada e um tensor de saída.
Esquematicamente, a seguinte Sequential
modelo:
# 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 esta função:
# 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)))
Um modelo sequencial não é apropriada quando:
- Seu modelo tem várias entradas ou várias saídas
- Qualquer uma de suas camadas tem várias entradas ou várias saídas
- Você precisa fazer o compartilhamento de camada
- Você deseja uma topologia não linear (por exemplo, uma conexão residual, um modelo multiramal)
Criando um modelo sequencial
Você pode criar um modelo Sequential passando uma lista de camadas para o construtor Sequential:
model = keras.Sequential(
[
layers.Dense(2, activation="relu"),
layers.Dense(3, activation="relu"),
layers.Dense(4),
]
)
Suas camadas são acessíveis através do layers
atributo:
model.layers
[<keras.layers.core.Dense at 0x7fdc784478d0>, <keras.layers.core.Dense at 0x7fdbbc3c4650>, <keras.layers.core.Dense at 0x7fdbbc3c4a10>]
Você também pode criar um modelo sequencial de forma incremental através do add()
método:
model = keras.Sequential()
model.add(layers.Dense(2, activation="relu"))
model.add(layers.Dense(3, activation="relu"))
model.add(layers.Dense(4))
Note que há também um correspondente pop()
método para remover camadas: a sequenciais se comporta modelo muito parecido com uma lista de camadas.
model.pop()
print(len(model.layers)) # 2
2
Observe também que o construtor Sequential aceita um name
argumento, assim como qualquer camada ou modelo em Keras. Isso é útil para anotar gráficos do TensorBoard com nomes semanticamente 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"))
Especificando a forma de entrada com antecedência
Geralmente, todas as camadas no Keras precisam conhecer a forma de suas entradas para poder criar seus pesos. Então, quando você cria uma camada como esta, inicialmente, ela não tem pesos:
layer = layers.Dense(3)
layer.weights # Empty
[]
Ele cria seus pesos na primeira vez que é chamado em uma entrada, pois a forma dos pesos depende da forma das 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.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, isso também se aplica aos modelos Sequenciais. Quando você criar um modelo sequencial sem uma forma de entrada, não é "construído": não tem pesos (e chamando model.weights
resulta em um erro informando apenas isso). Os pesos são criados quando o modelo vê pela primeira vez alguns dados 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
Uma vez que um modelo é "construído", você pode chamar o seu summary()
método para exibir o seu conteúdo:
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 _________________________________________________________________
No entanto, pode ser muito útil ao construir um modelo Sequencial de forma incremental para poder exibir o resumo do modelo até agora, incluindo a forma de saída atual. Neste caso, você deve começar o seu modelo, passando uma Input
objeto ao seu modelo, para que ele saiba a sua forma de entrada desde o início:
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 _________________________________________________________________
Note-se que a Input
objeto não é exibido como parte de model.layers
, uma vez que não é uma camada:
model.layers
[<keras.layers.core.Dense at 0x7fdbbc37c390>]
Uma alternativa simples é apenas para passar um input_shape
argumento para sua primeira camada:
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 _________________________________________________________________
Modelos construídos com uma forma de entrada predefinida como esta sempre têm pesos (mesmo antes de ver quaisquer dados) e sempre têm uma forma de saída definida.
Em geral, é uma prática recomendada sempre especificar a forma de entrada de um modelo Sequencial com antecedência se você souber qual é.
Um fluxo de trabalho de depuração comum: add()
+ summary()
Quando a construção de uma nova arquitetura seqüencial, é útil para empilhar incrementalmente camadas com add()
e, frequentemente, imprimir resumos modelo. Por exemplo, isto permite-lhe controlar a forma como uma pilha de Conv2D
e MaxPooling2D
camadas é downsampling mapas de características imagem:
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 _________________________________________________________________
Muito prático, certo?
O que fazer depois de ter um modelo
Quando sua arquitetura de modelo estiver pronta, você desejará:
- Treine seu modelo, avalie-o e execute a inferência. Veja o nosso guia para a formação e avaliação com o built-in laços
- Salve seu modelo em disco e restaure-o. Veja o nosso guia para serialização e economia .
- Acelere o treinamento do modelo aproveitando várias GPUs. Veja o nosso guia para multi-GPU e formação distribuída .
Extração de recursos com um modelo sequencial
Uma vez que um modelo sequencial tem sido construído, ele se comporta como um modelo API funcional . Isto significa que cada camada tem uma input
e output
atributo. Esses atributos podem ser usados para fazer coisas legais, como criar rapidamente um modelo que extrai as saídas de todas as camadas intermediárias em um modelo Sequencial:
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)
Aqui está um exemplo semelhante que extrai apenas recursos de uma camada:
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 aprendizado com um modelo sequencial
O aprendizado de transferência consiste em congelar as camadas inferiores em um modelo e treinar apenas as camadas superiores. Se você não estiver familiarizado com ele, certifique-se de ler o nosso guia para a aprendizagem de transferência .
Aqui estão dois modelos comuns de aprendizado de transferência envolvendo modelos sequenciais.
Primeiro, digamos que você tenha um modelo Sequencial e queira congelar todas as camadas, exceto a última. Neste caso, você poderia simplesmente iterar sobre model.layers
e conjunto layer.trainable = False
em cada camada, exceto a última. Como isso:
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(...)
Outro modelo comum é usar um modelo Sequencial para empilhar um modelo pré-treinado e algumas camadas de classificação recém-iniciadas. Como isso:
# 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 você transferir o aprendizado, provavelmente se verá frequentemente usando esses dois padrões.
Isso é tudo o que você precisa saber sobre modelos sequenciais!
Para saber mais sobre a construção de modelos no Keras, consulte: