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?
Sequential
model jest odpowiedni dla zwykłego stosu warstw, przy czym każda warstwa ma dokładnie jeden tensor tensor wejście i jedno wyjście.
Schematycznie, co następuje Sequential
model:
# 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 odpowiednia, gdy:
- Twój model ma wiele wejść lub wiele wyjść
- Każda z twoich warstw ma wiele wejść lub wiele wyjść
- Musisz udostępnić warstwy
- Potrzebujesz nieliniowej topologii (np. połączenie resztkowe, model wielorozgałęziony)
Tworzenie modelu sekwencyjnego
Możesz utworzyć model Sequential, przekazując listę warstw do konstruktora Sequential:
model = keras.Sequential(
[
layers.Dense(2, activation="relu"),
layers.Dense(3, activation="relu"),
layers.Dense(4),
]
)
Jej warstwy są dostępne za pośrednictwem layers
atrybutu:
model.layers
[<keras.layers.core.Dense at 0x7fdc784478d0>, <keras.layers.core.Dense at 0x7fdbbc3c4650>, <keras.layers.core.Dense at 0x7fdbbc3c4a10>]
Można również tworzyć sekwencyjnego modelu przyrostowego poprzez add()
metody:
model = keras.Sequential()
model.add(layers.Dense(2, activation="relu"))
model.add(layers.Dense(3, activation="relu"))
model.add(layers.Dense(4))
Należy pamiętać, że istnieje również odpowiadające pop()
metoda usuwania warstw: sekwencyjnego modelu zachowuje się bardzo podobnie do listy warstw.
model.pop()
print(len(model.layers)) # 2
2
Należy również pamiętać, że sekwencyjny konstruktor przyjmuje name
argumentu, podobnie jak każdej warstwy lub model w Keras. Jest to przydatne do opisywania wykresów TensorBoard za pomocą semantycznie znaczących nazw.
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"))
Wcześniejsze określenie kształtu wejściowego
Ogólnie rzecz biorąc, wszystkie warstwy w Keras muszą znać kształt swoich danych wejściowych, aby móc tworzyć swoje wagi. Więc kiedy 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ż kształt wag 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.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)>]
Oczywiście dotyczy to również modeli sekwencyjnych. Podczas wystąpienia sekwencyjnego modelu bez kształtu wejściowego, to nie jest „zbudowany”: to nie ma masę (i wzywaj model.weights
skutkuje błędem podając tylko tego). 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
Gdy model jest „zbudowany”, można nazwać jej summary()
metodę, aby wyświetlić jego zawartość:
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 _________________________________________________________________
Jednak podczas budowania modelu sekwencyjnego może być bardzo przydatne, aby móc wyświetlić dotychczasowe podsumowanie modelu, w tym bieżący kształt wyjściowy. W tym przypadku, należy rozpocząć swój model przechodząc Input
obiektu do danego modelu, tak, że zna jego kształt wejściowy od początku:
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 _________________________________________________________________
Należy pamiętać, że Input
obiektu nie jest wyświetlany jako część model.layers
, ponieważ nie jest to warstwa:
model.layers
[<keras.layers.core.Dense at 0x7fdbbc37c390>]
Prostym rozwiązaniem jest po prostu zdać input_shape
argument pierwszej warstwie:
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 zaleca się, aby zawsze wcześniej określać kształt wejściowy modelu sekwencyjnego, jeśli wiesz, co to jest.
Częstym debugowanie workflow: add()
+ summary()
Przy budowie nowego Sequential architekturę, jest to przydatne, aby stopniowo układać warstwy z add()
i często drukować modelowych podsumowania. Na przykład ten pozwala monitorować stos Conv2D
i MaxPooling2D
warstw mapy funkcji próbkowania 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 robić, gdy masz modelkę
Gdy architektura Twojego modelu będzie gotowa, będziesz chciał:
- Trenuj swój model, oceniaj go i przeprowadzaj wnioskowanie. Zobacz nasz przewodnik szkolenia i oceny z wbudowanej pętli
- Zapisz swój model na dysku i przywróć go. Zobacz nasz przewodnik po serializacji i oszczędności .
- Przyspiesz uczenie modeli dzięki wykorzystaniu wielu procesorów graficznych. Zobacz nasz przewodnik multi-GPU i rozproszonej szkolenia .
Ekstrakcja cech za pomocą modelu sekwencyjnego
Gdy sekwencyjny model został zbudowany, to zachowuje się jak funkcjonalny model API . Oznacza to, że każda warstwa ma input
i output
atrybut. Te atrybuty mogą być używane 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, który wyodrębnia 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)
Transfer uczenia się z modelem sekwencyjnym
Uczenie transferu polega na zamrażaniu dolnych warstw w modelu i trenowaniu tylko górnych warstw. Jeśli nie są zaznajomieni z nim, upewnij się, aby przeczytać nasz przewodnik uczenia transferowego .
Oto dwa popularne schematy uczenia się transferów obejmujące modele sekwencyjne.
Najpierw załóżmy, że masz model sekwencyjny i chcesz zamrozić wszystkie warstwy z wyjątkiem ostatniej. W tym przypadku, po prostu iteracyjne nad model.layers
i zestaw layer.trainable = False
na każdej warstwie, z wyjątkiem ostatniego. 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 powszechnym planem jest użycie modelu sekwencyjnego do ułożenia wstępnie wytrenowanego modelu i niektórych ś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 uczysz się transferów, 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: