Как правильно расширить модели Keras или вставить промежуточные слои в модели Keras, используя get_layer - PullRequest
0 голосов
/ 10 апреля 2020

Допустим, я создаю функциональную модель 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. Что я делаю неправильно и что я должен изменить, чтобы я мог явно подключить / отключить старые слои к моей новой модели?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...