Как мне «сплющить» модель в модели в Керасе - PullRequest
0 голосов
/ 02 ноября 2018

Допустим, у меня есть модель Keras, которую я построил и которая мне нравится:

from keras.layers import Input, Dense, BatchNormalization, Subtract
from keras.models import Model

input_layer = Input((10, ))
x = Dense(5)(input_layer)
output_layer = Dense(10)(x)

model = Model(input_layer, output_layer)

Я могу узнать о своей модели с помощью функции summary() и получаю:

_________________________________________________________________
Layer (type)                 Output Shape              Param #
=================================================================
input_1 (InputLayer)         (None, 10)                0
_________________________________________________________________
dense_1 (Dense)              (None, 5)                 55
_________________________________________________________________
dense_2 (Dense)              (None, 10)                60
=================================================================
Total params: 115
Trainable params: 115
Non-trainable params: 0
_________________________________________________________________

Теперь я хочу попробовать добавить в модель некоторые этапы предварительной и последующей обработки, чтобы, например, я мог сделать следующее:

# Add preprocessing layers
new_input = Input((10,))
x = BatchNormalization()(new_input)
model.layers.pop(0) # remove original input
x = model(x)
# Change the model to residual modeling with a subtract layer
new_output = Subtract()([new_input, x])
new_model = Model(new_input, new_output)

Однако теперь, когда я звоню summary(), я узнаю только о слоях до и после обработки, а не о своей исходной модели:

__________________________________________________________________________________________________
Layer (type)                    Output Shape         Param #     Connected to
==================================================================================================
input_2 (InputLayer)            (None, 10)           0
__________________________________________________________________________________________________
batch_normalization_1 (BatchNor (None, 10)           40          input_2[0][0]
__________________________________________________________________________________________________
model_1 (Model)                 (None, 10)           115         batch_normalization_1[0][0]
__________________________________________________________________________________________________
subtract_1 (Subtract)           (None, 10)           0           input_2[0][0]
                                                                 model_1[1][0]
==================================================================================================
Total params: 155
Trainable params: 135
Non-trainable params: 20
__________________________________________________________________________________________________

Это означает, что вместо того, чтобы каждый слой из первой модели добавлялся к new_model.layers новой модели, вместо этого вся модель добавляется как отдельный элемент в список new_model.layers. Я хочу, чтобы на самом деле этот единственный элемент был выровнен, поэтому резюме будет выглядеть примерно так:


Layer (type)                    Output Shape         Param #     Connected to
==================================================================================================
input_2 (InputLayer)            (None, 10)           0
__________________________________________________________________________________________________
batch_normalization_1 (BatchNor (None, 10)           40          input_2[0][0]
__________________________________________________________________________________________________
dense_1 (Dense)                 (None, 5)            55          batch_normalization_1[0][0]
__________________________________________________________________________________________________
dense_2 (Dense)                 (None, 10)           60          dense_1[0]
__________________________________________________________________________________________________
subtract_1 (Subtract)           (None, 10)           0           input_2[0][0]
                                                                 dense_2[1][0]
==================================================================================================
Total params: 155
Trainable params: 135
Non-trainable params: 20
__________________________________________________________________________________________________

Почему меня это волнует? По сути, я пробую разные подходы к моделированию, в которых я могу опробовать различные комбинации предварительной и последующей обработки вместе с разными базовыми моделями и посмотреть, как это влияет на мои результаты. Однако сравнительно трудно провести сравнительный анализ, когда информация о базовой модели и ее параметрах обернута в один «модельный» слой модели-оболочки, который просто содержит информацию о предварительной и последующей обработке.

1 Ответ

0 голосов
/ 03 ноября 2018

Это правильное поведение Keras, поскольку Model на самом деле наследует от Layer. Вы можете заключить базовую модель в функцию, чтобы предотвратить ее преобразование в Model:

def base_model(input=None):
  input_layer = input or Input((10, ))
  x = Dense(5)(input_layer)
  output_layer = Dense(10)(x)
  if input is None:
    return Model(input_layer, output_layer)
  return output_layer
# Then use it
# Add preprocessing layers
new_input = Input((10,))
x = BatchNormalization()(new_input)
x = base_model(x)
# Change the model to residual modeling with a subtract layer
new_output = Subtract()([new_input, x])
new_model = Model(new_input, new_output)

Если вы пропустите существующий слой, он не будет перенесен, если вы этого не сделаете, он вернет вам Model экземпляр.

...