Допустим, мы используем TensorFlow r2.0 и говорим, что хотим использовать подмодели в Keras, поэтому у нас есть модель A , например:
def create_model_A(in_num_units, name):
x = tf.keras.Input(shape=(in_num_units))
y = tf.keras.layers.Dense(in_num_units, activation='relu')(x)
y = tf.keras.layers.BatchNormalization()(y)
y = tf.keras.layers.Dense(in_num_units, activation='relu')(y)
y = tf.keras.layers.BatchNormalization()(y)
y = x + y
return tf.keras.Model(x, y, name=name)
и модель * 1006. * B , который использует модель A :
def create_model_B(in_num_units):
x = tf.keras.Input(shape=(in_num_units))
y = create_model_A(x.shape[-1], name='A_1')(x)
y = tf.keras.layers.Dense(in_num_units // 2, name='downsize_1')(y)
y = tf.keras.layers.BatchNormalization()(y)
y = create_model_A(y.shape[-1], name='A_2')(y)
y = tf.keras.layers.Dense(in_num_units // 2, name='downsize_2')(y)
y = tf.keras.layers.BatchNormalization()(y)
y = create_model_A(y.shape[-1], name='A_3')(y)
y = tf.keras.layers.Dense(in_num_units // 2, name='downsize_3')(y)
y = tf.keras.layers.BatchNormalization()(y)
y = create_model_A(y.shape[-1], name='A_4')(y)
return tf.keras.Model(x, y)
Это работает как шарм. Мы можем создать модель B следующим образом:
num_in_units = 500
model = create_model_B(num_in_units) # Works!
И воспользоваться всеми преимуществами tf.keras.Model. Но проблема возникает, когда мы хотим получить результат промежуточного слоя, который имеет подмодель A . Если слой является частью модели B , все работает:
inter_model_1 = tf.keras.Model(
model.input, model.get_layer('downsize_1').output) # Works!
Но если слой относится к подмодели A, он падает с ValueError
. Эта команда:
inter_model_2 = tf.keras.Model(
model.input, model.get_layer('A_3').output) # Does not work!
Дает:
ValueError: Graph disconnected: cannot obtain value for tensor Tensor("input_4:0", shape=(None, 250), dtype=float32) at layer "input_4". The following previous layers were accessed without issue: []
Я не уверен, что понимаю всю внутреннюю механику керас. Но то, что я понимаю, когда погружаюсь в исходный код, состоит в том, что для подмоделей, используемых таким образом, создано два объекта входных тензоров. Они могут быть напечатаны так:
print([n.input_tensors.name for n in model.get_layer('A_3').inbound_nodes])
['input_4:0', 'batch_normalization_5/Identity:0']
Один - это подмодель tf.keras.Input
, а другой - вход, связанный с топ-моделью.
При построении новой модели из топ-модели B входного тензора для топ-модели B выходного тензора путь в графе, кажется, правильно проходит мимовход 'batch_normalization_5'
и оба тензора правильно связаны на графике.
Однако при попытке связать тензор входа топ-модели B с подмоделью A выходной тензор, кажется, что выходные тензоры связаны с подмоделью tf.keras.Input
, и оба тензора отключены.
Решение, которое я нашел на данный момент, заключается в использовании версии тензора с топ-модельюmodel.get_layer('A_3').output
:
model.get_layer('A_3')._outbound_nodes[0].input_tensors
Но это кажется слишком сложным и не чистым ... Кроме того, оно не позволяет нам использовать слои внутри модели A .
Интересно, кто-нибудь может дать мне некоторую точность в этом tf.keras
поведении? Правильно ли я это сделал? Это предполагаемое поведение? Это ошибка? Большое спасибо!