This page was translated by the Cloud Translation API.
Switch to English

Model sekwencyjny

Zobacz na TensorFlow.org Uruchom w Google Colab Wyświetl źródło na GitHub Pobierz notatnik

Ustawiać

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

Kiedy używać modelu sekwencyjnego

Model Sequential jest odpowiedni dla zwykłego stosu warstw, w którym każda warstwa ma dokładnie jeden tensor wejściowy i jeden tensor wyjściowy .

Schematycznie następujący model 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)
 

jest odpowiednikiem tej funkcji:

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

Model sekwencyjny nie jest odpowiedni, gdy:

  • Twój model ma wiele wejść lub wiele wyjść
  • Każda z twoich warstw ma wiele wejść lub wiele wyjść
  • Musisz udostępniać warstwy
  • Chcesz nieliniowej topologii (np. Połączenie szczątkowe, model wielogałęziowy)

Tworzenie modelu sekwencyjnego

Możesz stworzyć model sekwencyjny, przekazując listę warstw do konstruktora sekwencyjnego:

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

Jego warstwy są dostępne za pośrednictwem atrybutu 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>]

Możesz również utworzyć model sekwencyjny przyrostowo za pomocą metody add() :

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

Zauważ, że istnieje również odpowiednia metoda pop() do usuwania warstw: model sekwencyjny zachowuje się bardzo podobnie do listy warstw.

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

Zauważ również, że konstruktor Sequential akceptuje argument name , tak jak każda warstwa lub model w Keras. Jest to przydatne do opisywania wykresów TensorBoard nazwami o znaczeniu semantycznym.

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

Określenie kształtu wejściowego z wyprzedzeniem

Ogólnie rzecz biorąc, wszystkie warstwy w Keras muszą znać kształt swoich danych wejściowych, aby móc tworzyć swoje wagi. Kiedy więc tworzysz taką warstwę, początkowo nie ma ona żadnych wag:

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

Tworzy swoje wagi przy pierwszym wywołaniu na wejściu, ponieważ ich kształt zależy od kształtu danych wejściowych:

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

Oczywiście dotyczy to również modeli sekwencyjnych. Kiedy tworzysz instancję modelu sekwencyjnego bez kształtu wejściowego, nie jest on „zbudowany”: nie ma on żadnych wag (a wywołanie model.weights skutkuje błędem stwierdzającym tylko to). Wagi są tworzone, gdy model po raz pierwszy widzi dane wejściowe:

 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

Po „zbudowaniu” modelu można wywołać jego metodę summary() , aby wyświetlić jego zawartość:

 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
_________________________________________________________________

Jednak może być bardzo przydatne podczas budowania modelu sekwencyjnego w sposób przyrostowy, aby móc wyświetlić podsumowanie dotychczasowego modelu, w tym bieżący kształt wyjściowy. W takim przypadku należy rozpocząć model od przekazania obiektu Input do modelu, aby od początku znał jego kształt wejściowy:

 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
_________________________________________________________________

Zwróć uwagę, że obiekt Input nie jest wyświetlany jako część model.layers , ponieważ nie jest warstwą:

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

Prostą alternatywą jest po prostu przekazanie argumentu input_shape do pierwszej warstwy:

 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
_________________________________________________________________

Modele zbudowane z predefiniowanym kształtem wejściowym, takim jak ten, zawsze mają wagi (nawet przed wyświetleniem jakichkolwiek danych) i zawsze mają zdefiniowany kształt wyjściowy.

Ogólnie rzecz biorąc, zaleca się, aby zawsze określać kształt wejściowy modelu sekwencyjnego z wyprzedzeniem, jeśli wiesz, co to jest.

Typowy przebieg debugowania: add() + summary()

Podczas budowania nowej architektury sekwencyjnej przydatne jest stopniowe układanie warstw w stosy za pomocą funkcji add() i częste drukowanie podsumowań modeli. Na przykład umożliwia to monitorowanie, w jaki sposób stos warstw Conv2D i MaxPooling2D zmniejsza próbkowanie map funkcji obrazu:

 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
_________________________________________________________________

Bardzo praktyczne, prawda?

Co zrobić, gdy masz model

Gdy architektura modelu będzie gotowa, będziesz chciał:

Ekstrakcja cech za pomocą modelu sekwencyjnego

Po utworzeniu modelu sekwencyjnego zachowuje się on jak model funkcjonalnego interfejsu API . Oznacza to, że każda warstwa ma atrybut input i output . Te atrybuty można wykorzystać do robienia fajnych rzeczy, takich jak szybkie tworzenie modelu, który wyodrębnia dane wyjściowe wszystkich warstw pośrednich w modelu sekwencyjnym:

 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)
 

Oto podobny przykład, w którym wyodrębniane są funkcje tylko z jednej warstwy:

 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)
 

Przenieś naukę za pomocą modelu sekwencyjnego

Uczenie się transferu polega na zamrażaniu dolnych warstw w modelu i trenowaniu tylko górnych warstw. Jeśli go nie znasz, przeczytaj nasz przewodnik dotyczący transferu nauki .

Oto dwa typowe schematy uczenia się transferu obejmujące modele sekwencyjne.

Po pierwsze, powiedzmy, że masz model sekwencyjny i chcesz zablokować wszystkie warstwy oprócz ostatniej. W takim przypadku wystarczy iterować po model.layers i ustawić layer.trainable = False na każdej warstwie, z wyjątkiem ostatniej. Lubię to:

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

Innym typowym planem jest użycie modelu sekwencyjnego w celu ułożenia wstępnie wytrenowanego modelu i kilku świeżo zainicjowanych warstw klasyfikacji. Lubię to:

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

Jeśli przenosisz naukę, prawdopodobnie będziesz często używać tych dwóch wzorców.

To wszystko, co musisz wiedzieć o modelach sekwencyjnych!

Aby dowiedzieć się więcej o budowaniu modeli w Keras, zobacz: