Допустим, я создаю функциональную модель Keras. Я пишу модель для демонстрационных целей, но я действительно работаю с предварительно обученной моделью, которую я пытаюсь изменить. Поэтому мне нужно иметь возможность перебирать слои модели и вставлять промежуточные слои.
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers, models
encoder_input = keras.Input(shape=(28, 28, 1), name='original_img')
x = layers.Conv2D(16, 3, activation='relu')(encoder_input)
x = layers.Conv2D(32, 3, activation='relu')(x)
x = layers.Conv2D(64, 3, activation='relu')(x)
x = layers.Conv2D(32, 3, activation='relu')(x)
x = layers.Conv2D(32, 3, activation='relu')(x)
x = layers.Conv2D(16, 3, activation='relu')(x)
encoder = keras.Model(encoder_input, x, name='encoder')
encoder.summary()
Резюме:
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
original_img (InputLayer) (None, 28, 28, 1) 0
_________________________________________________________________
conv2d (Conv2D) (None, 26, 26, 16) 160
_________________________________________________________________
conv2d_1 (Conv2D) (None, 24, 24, 32) 4640
_________________________________________________________________
conv2d_2 (Conv2D) (None, 22, 22, 64) 18496
_________________________________________________________________
conv2d_3 (Conv2D) (None, 20, 20, 32) 18464
_________________________________________________________________
conv2d_4 (Conv2D) (None, 18, 18, 32) 9248
_________________________________________________________________
conv2d_5 (Conv2D) (None, 16, 16, 16) 4624
=================================================================
Total params: 55,632
Trainable params: 55,632
Non-trainable params: 0
Скажем, я хочу расширить / изменить модель, добавив промежуточный слои. Опять же, я буду работать с предварительно обученной загруженной моделью, поэтому представьте, что я не могу просто добавить эти слои в первую часть моей демонстрации.
x = encoder_input
for layer in encoder.layers[1:3]: #start with the original layers
x = layer(x)
x = layers.Conv2D(64, 3, activation='relu')(x) # new layer 1
x = layers.Conv2D(128, 3, activation='relu')(x) # new layer 2
x = layers.Conv2D(32, 3, activation='relu')(x) # new layer 3
for layer in encoder.layers[3:]: #finish with the rest of the original layers
x = layer(x)
new_encoder = keras.Model(encoder_input, x, name='new_encoder')
new_encoder.summary()
Резюме:
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
original_img (InputLayer) (None, 28, 28, 1) 0
_________________________________________________________________
conv2d (Conv2D) (None, 26, 26, 16) 160
_________________________________________________________________
conv2d_1 (Conv2D) (None, 24, 24, 32) 4640
_________________________________________________________________
conv2d_6 (Conv2D) (None, 22, 22, 64) 18496
_________________________________________________________________
conv2d_7 (Conv2D) (None, 20, 20, 128) 73856
_________________________________________________________________
conv2d_8 (Conv2D) (None, 18, 18, 32) 36896
_________________________________________________________________
conv2d_2 (Conv2D) multiple 18496
_________________________________________________________________
conv2d_3 (Conv2D) multiple 18464
_________________________________________________________________
conv2d_4 (Conv2D) multiple 9248
_________________________________________________________________
conv2d_5 (Conv2D) multiple 4624
=================================================================
Total params: 184,880
Trainable params: 184,880
Non-trainable params: 0
Похоже, что encoder.layers [3:] отображает выходные данные как «множественные», поскольку он подключен к уровню conv2d_1 в исходной модели кодера, но к слою conv2d_8 с моделью new_encoder.
Наконец, если я создам другую модель с использованием метода get_layer на последнем слое моей новой модели кодера:
final_model = models.Model(encoder_input, new_encoder.get_layer('conv2d_5').output)
final_model.summary()
Сводка:
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
original_img (InputLayer) (None, 28, 28, 1) 0
_________________________________________________________________
conv2d (Conv2D) (None, 26, 26, 16) 160
_________________________________________________________________
conv2d_1 (Conv2D) (None, 24, 24, 32) 4640
_________________________________________________________________
conv2d_2 (Conv2D) multiple 18496
_________________________________________________________________
conv2d_3 (Conv2D) multiple 18464
_________________________________________________________________
conv2d_4 (Conv2D) multiple 9248
_________________________________________________________________
conv2d_5 (Conv2D) multiple 4624
=================================================================
Total params: 55,632
Trainable params: 55,632
Non-trainable params: 0
Почему метод вывода new_encoder.get_layer ('conv2d_5'). указывает на старую модель? Я хотел бы иметь возможность получить результат на любом данном уровне для моей новой модели, используя метод get_layer. Что я делаю неправильно и что я должен изменить, чтобы я мог явно подключить / отключить старые слои к моей новой модели?