Посмотреть на TensorFlow.org | Запустить в Google Colab | Посмотреть исходный код на GitHub | Скачать блокнот |
Настраивать
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
Когда использовать последовательную модель
Sequential
модель подходит для простого стека слоев , где каждый слой имеет ровно один тензор входной и один выходной тензор.
Схематически следующая 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)
эквивалентна этой функции:
# 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)))
Последовательная модель не подходит , когда:
- Ваша модель имеет несколько входов или несколько выходов
- Любой из ваших слоев имеет несколько входов или несколько выходов
- Вам нужно сделать общий доступ к слою
- Вам нужна нелинейная топология (например, остаточное соединение, многоветвевая модель)
Создание последовательной модели
Вы можете создать модель Sequential, передав список слоев конструктору Sequential:
model = keras.Sequential(
[
layers.Dense(2, activation="relu"),
layers.Dense(3, activation="relu"),
layers.Dense(4),
]
)
Ее слои доступны через layers
атрибутов:
model.layers
[<keras.layers.core.Dense at 0x7fdc784478d0>, <keras.layers.core.Dense at 0x7fdbbc3c4650>, <keras.layers.core.Dense at 0x7fdbbc3c4a10>]
Вы также можете создать Последовательная модель пошагово с помощью add()
метод:
model = keras.Sequential()
model.add(layers.Dense(2, activation="relu"))
model.add(layers.Dense(3, activation="relu"))
model.add(layers.Dense(4))
Обратите внимание , что есть также соответствующий pop()
метод для удаления слоев: Последовательная модель ведет себя очень похож на список слоев.
model.pop()
print(len(model.layers)) # 2
2
Также отметим , что последовательный конструктор принимает name
аргумента, так же как и любой слой или модели в Keras. Это полезно для аннотирования графов TensorBoard семантически значимыми именами.
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"))
Предварительное указание входной формы
Как правило, все слои в Keras должны знать форму своих входных данных, чтобы иметь возможность создавать свои веса. Итак, когда вы создаете такой слой, изначально он не имеет весов:
layer = layers.Dense(3)
layer.weights # Empty
[]
Он создает свои веса при первом обращении к входным данным, поскольку форма весов зависит от формы входных данных:
# 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)>]
Естественно, это относится и к моделям Sequential. При создании экземпляра модели последовательной без формы ввода, он не «построен»: он не имеет веса (и вызов model.weights
приводит к ошибке с указанием только это). Веса создаются, когда модель впервые видит некоторые входные данные:
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
После того, как модель «построена», вы можете вызвать его summary()
метод , чтобы отобразить его содержимое:
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 _________________________________________________________________
Однако при поэтапном построении модели Sequential может быть очень полезно иметь возможность отображать сводку модели на данный момент, включая текущую выходную форму. В этом случае, вы должны начать свою модель, передавая Input
объект вашей модели, так что он знает , что его входную форму с самого начала:
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 _________________________________________________________________
Обратите внимание , что Input
объект не отображается как часть model.layers
, так как это не слой:
model.layers
[<keras.layers.core.Dense at 0x7fdbbc37c390>]
Простая альтернатива просто передать input_shape
аргумент первого слоя:
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 _________________________________________________________________
Модели, построенные с такой предопределенной входной формой, всегда имеют вес (даже до того, как будут показаны какие-либо данные) и всегда имеют определенную выходную форму.
Как правило, рекомендуется всегда заранее указывать входную форму последовательной модели, если вы знаете, что это такое.
Обычный рабочий процесс отладки: add()
+ summary()
При создании новой Последовательная архитектуры, полезно постепенно складывать слои с add()
и часто печатать модели сводки. Например, это позволяет отслеживать , как стопка Conv2D
и MaxPooling2D
слоев субдискретизации карты художественных изображений:
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 _________________________________________________________________
Очень практично, правда?
Что делать, если у вас есть модель
Когда архитектура вашей модели будет готова, вы захотите:
- Обучите свою модель, оцените ее и выполните вывод. Смотрите наше руководство по обучению и оценке с помощью встроенных в петлях
- Сохраните вашу модель на диск и восстановите ее. Смотрите наш путеводитель по сериализации и экономии .
- Ускорьте обучение модели, используя несколько графических процессоров. Смотрите наш путеводитель мульти-GPU и распределенное обучение .
Извлечение признаков с последовательной моделью
После того, как последовательная модель была построена, она ведет себя как функциональная модель API . Это означает , что каждый слой имеет input
и output
атрибут. Эти атрибуты можно использовать для выполнения аккуратных действий, например, для быстрого создания модели, которая извлекает выходные данные всех промежуточных слоев в последовательной модели:
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)
Вот аналогичный пример, в котором объекты извлекаются только из одного слоя:
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)
Перенос обучения с последовательной моделью
Трансферное обучение состоит из замораживания нижних слоев модели и обучения только верхних слоев. Если вы не знакомы с ним, убедитесь , чтобы прочитать наше руководство по обучению передачи .
Вот два распространенных плана трансферного обучения с использованием последовательных моделей.
Во-первых, предположим, что у вас есть последовательная модель, и вы хотите заморозить все слои, кроме последнего. В этом случае, вы бы просто итерация над model.layers
и множество layer.trainable = False
на каждом слое, за исключением последнего. Нравится:
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(...)
Другим распространенным планом является использование модели Sequential для объединения предварительно обученной модели и некоторых недавно инициализированных слоев классификации. Нравится:
# 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(...)
Если вы занимаетесь переносом обучения, вы, вероятно, обнаружите, что часто используете эти два паттерна.
Это все, что вам нужно знать о моделях Sequential!
Чтобы узнать больше о построении моделей в Keras, см.: