На этом шаге мы рассмотрим особенности использования этой модели.
Самый простой способ создать модель Keras - использовать уже знакомый вам класс моделей Sequential.
from tensorflow import keras from tensorflow.keras import layers model = keras.Sequential([ layers.Dense(64, activation="relu"), layers.Dense(10, activation="softmax") ])
Обратите внимание, что эту модель также можно построить, последовательно вызывая метод add(), который действует подобно методу append() списков в языке Python.
model = keras.Sequential() model.add(layers.Dense(64, activation="relu")) model.add(layers.Dense(10, activation="softmax"))
Мы знаем, что слои (точнее, их веса) создаются только в момент первого вызова. Причина подобного поведения в том, что форма слоев зависит от формы входных данных: пока форма входных данных неизвестна, слои не могут быть созданы.
В силу этого предыдущая модель Sequential не будет иметь весов (пример 7.3) до передачи ей некоторых данных или до вызова ее метода build() с описанием формы входных данных (пример 7.4).
print(model.weights) # В этой точке модель еще не построена []
# Этот вызов построит модель - после него модель будет # готова принимать образцы с формой (3,). # None в форме входных данных означает, # что размер пакета может быть любым model.build(input_shape=(None, 3)) # Теперь можно получить веса модели print(model.weights) [<KerasVariable shape=(3, 64), dtype=float32, path=sequential_4/dense_8/kernel>, <KerasVariable shape=(64,), dtype=float32, path=sequential_4/dense_8/bias>, <KerasVariable shape=(64, 10), dtype=float32, path=sequential_4/dense_9/kernel>, <KerasVariable shape=(10,), dtype=float32, path=sequential_4/dense_9/bias>]
После того как модель будет построена, ее содержимое можно вывести вызовом метода summary(), что очень удобно на этапе отладки. Пример 7.5. Метод summary()
print(model.summary())
Model: "sequential_1"
Layer (type) Output Shape Param #
dense_2 (Dense) (None, 64) 256
dense_3 (Dense) (None, 10) 650
Total params: 906 (3.54 KB)
Trainable params: 906 (3.54 KB)
Non-trainable params: 0 (0.00 B)
Как видите, эта модель получила имя sequential_1. В Keras имя можно присвоить чему угодно - каждой модели, каждому слою.
model = keras.Sequential(name="my_example_model") model.add(layers.Dense(64, activation="relu", name="my_first_layer")) model.add(layers.Dense(10, activation="softmax", name="my_last_layer")) model.build((None, 3)) print(model.summary()) Model: "my_example_model" Layer (type) Output Shape Param # my_first_layer (Dense) (None, 64) 256 my_last_layer (Dense) (None, 10) 650 Total params: 906 (3.54 KB) Trainable params: 906 (3.54 KB) Non-trainable params: 0 (0.00 B)
При пошаговом построении модели Sequential удобно иметь возможность посмотреть на ее текущее состояние после добавления очередного слоя. Но сводку невозможно получить, пока модель не построена! Эту проблему можно решить, строя модель Sequential на лету, для чего достаточно заранее объявить форму входных данных. Это можно сделать с помощью класса Input.
model = keras.Sequential() # Использование Input для объявления формы входных данных. # Обратите внимание, что аргумент shape должен определять # форму одного образца, но не пакета model.add(keras.Input(shape=(3,))) model.add(layers.Dense(64, activation="relu"))
Теперь вы сможете вызывать summary() и наблюдать, как меняется форма выходных данных модели по мере добавления дополнительных слоев:
print(model.summary())
Model: "sequential_2"
Layer (type) Output Shape Param #
dense_4 (Dense) (None, 64) 256
Total params: 256 (1.00 KB)
Trainable params: 256 (1.00 KB)
Non-trainable params: 0 (0.00 B)
model.add(layers.Dense(10, activation="softmax")) print(model.summary()) Model: "sequential_2" Layer (type) Output Shape Param # dense_4 (Dense) (None, 64) 256 dense_5 (Dense) (None, 10) 650 Total params: 906 (3.54 KB) Trainable params: 906 (3.54 KB) Non-trainable params: 0 (0.00 B)
Это довольно распространенный прием отладки при работе со слоями, которые применяют сложные преобразования к своим входным данным (например, со сверточными слоями, о которых мы поговорим позже).
На следующем шаге мы начнем знакомиться с функциональным API.