Я пытаюсь реализовать модель обучения с несколькими экземплярами с помощью TensorFlow Keras API.Предположим, что входной тензор имеет форму (None, 18, 10, 300)
, и мне нужно выполнить многоэкземплярное обучение с submodel
вдоль axis=1
.Таким образом, ввод для submodel
должен быть (None, 10, 300)
.Предположим, что форма выходного тензора для одного submodel
равна (None, 100)
, затем результат submodel
s объединяется, таким образом, создается выходная форма (None, 18, 100)
.
Я реализовал этот механизм двумя способами, они должны быть функционально равными, однако при обучении модели точность второй реализации на 20% выше, чем у первой реализации (хотя обе не достаточно хороши).Интересно, есть ли функциональная разница между двумя реализациями?Если обе эти реализации не то, что я имею в виду, не могли бы вы дать правильную реализацию?
Реализация 1. В этой реализации разделить входной тензор со слоем keras Lambda
, выполнить submodel
,разверните размер результата в axis=1
, затем объедините результат по axis=1
.
def get_branch_model(input_shape, submodel, args={}):
model_input = tf.keras.Input(input_shape)
sliced_inputs = [tf.keras.layers.Lambda(lambda x: x[:,i])(model_input)
for i in range(input_shape[0])]
sub_instance = submodel(**args)
branch_models = [sub_instance(sliced_inputs[i]) for i in range(input_shape[0])]
expand_layer = tf.keras.layers.Lambda(lambda x: tf.keras.backend.expand_dims(x, axis=1))
expanded_outputs = [expand_layer(branch_models[i]) for i in range(input_shape[0])]
concated_layer = tf.keras.layers.Concatenate(axis=1)(expanded_outputs)
return tf.keras.Model(model_input, concated_layer)
Реализация 2. Эта реализация использует tf.slice
, чтобы разделить входной тензор, выполнить submodel
, развернутьИзмерение результата в axis=1
, затем объединить результат по axis=1
.
def __get_filter_layer(total_dim, target_dim, index):
def tensor_filter(tensor_in):
nonlocal index
begin = [0 if i != target_dim else index for i in range(total_dim)]
size = [-1 if i != target_dim else 1 for i in range(total_dim)]
return tf.squeeze(tf.slice(tensor_in, begin, size), axis=target_dim)
return tf.keras.models.Sequential([
tf.keras.layers.Lambda(tensor_filter)
])
def get_branch_model(input_shape, branch_index, output_shape, submodel, args={}):
model_input = tf.keras.Input(input_shape)
sliced_inputs = [__get_filter_layer(len(input_shape) + 1, branch_index, i)(model_input)
for i in range(input_shape[branch_index - 1])]
sub_instance = submodel(**args)
branch_models = [sub_instance(sliced_inputs[i])
for i in range(input_shape[branch_index - 1])]
expand_layer = tf.keras.layers.Lambda(lambda x: tf.keras.backend.expand_dims(x, axis=1))
expanded_outputs = [expand_layer(branch_models[i]) for i in range(input_shape[0])]
concated_layer = tf.keras.layers.Concatenate(axis=1)(expanded_outputs)
return tf.keras.Model(model_input, concated_layer)
Вход для аргумента input_shape
равен (18, 10, 300)
, а branch_index
равен 1
.submodel
является последовательной моделью, такой как tf.keras.Sequential([tf.keras.layers.Dense(...)])
.