Существует несколько вопросов о переполнении стека, связанных с function
Кераса, документация которого даже не существует или не дает какой-либо реальной ценной информации о ее цели, AFAIK. Например, Какова цель keras.backend.function () или Keras, Как получить выходные данные каждого слоя? . Однако ни один из них не описывает и не подчеркивает фактическое поведение function
. Итак, я попытался понять, участвуют ли при вычислениях function
предыдущие слои слоя, который мы передаем в качестве вывода в function
, или нет. Например, рассмотрим следующие две модели:
import tensorflow as tf
import numpy as np
def get_model1():
inp = tf.keras.layers.Input(shape=(1,))
x = tf.keras.layers.Dense(8, kernel_initializer="zeros", bias_initializer="zeros")(inp)
x = tf.keras.layers.Dense(16, kernel_initializer="ones", bias_initializer="ones")(x)
out = tf.keras.layers.Dense(1, kernel_initializer="zeros", bias_initializer="zeros")(x)
model = tf.keras.Model(inputs=inp, outputs=out)
model.summary()
return model
def get_model2():
inp = tf.keras.layers.Input(shape=(1,))
x = tf.keras.layers.Dense(8, kernel_initializer="ones", bias_initializer="ones")(inp)
out = tf.keras.layers.Dense(16, kernel_initializer="ones", bias_initializer="ones")(x)
model = tf.keras.Model(inputs=inp, outputs=out)
model.summary()
return model
Различия между этими двумя моделями заключаются в том, что в первой модели есть еще один слой, который является выходным слоем, и параметры первого слоя инициализируются нулями, тогда как во второй модели параметры первого слоя инициализируются единицами.
Если я выполню следующий код,
def example1(data_x):
model = get_model1()
outputs = [layer.output for layer in model.layers]
functors = [tf.keras.backend.function([model.input], [out]) for out in outputs]
for func in functors:
print(func(data_x)[0].shape)
print(func(data_x)[0])
def example2(data_x):
model = get_model2()
print(model(data_x))
if __name__ == '__main__':
data_x = np.array([[1], [2], [3], [4]])
example1(data_x)
example2(data_x)
Первый пример возвращает следующий вывод (для второго слоя с 16 единицами)
[[1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
[1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
[1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
[1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]]
, а второй возвращает следующий (для второго слоя с 16 единицами)
tf.Tensor(
[[17. 17. 17. 17. 17. 17. 17. 17. 17. 17. 17. 17. 17. 17. 17. 17.]
[25. 25. 25. 25. 25. 25. 25. 25. 25. 25. 25. 25. 25. 25. 25. 25.]
[33. 33. 33. 33. 33. 33. 33. 33. 33. 33. 33. 33. 33. 33. 33. 33.]
[41. 41. 41. 41. 41. 41. 41. 41. 41. 41. 41. 41. 41. 41. 41. 41.]], shape=(4, 16), dtype=float32)
Учитывая, что оба слоя с 16 единицами инициализируются с единицами и с учетом этих разных результатов, кажется, что когда я делаю что-то вроде tf.keras.backend.function([model.input], [out])
все слои, предшествующие out
, и, в общем, весь код, связанный с out
и model.input
, также будут выполнены, что означает, что мы действительно выполняем часть модели, а не только слой out
или model.input
, то есть tf.keras.backend.function([model.input], [out])
не означает, что мы создадим функцию, которая соединяет model.input
с out
, но что мы создадим функцию, которая может выполнять все части вычислительного графа, которые соединяют model.input
до out
. Я прав? Это где-нибудь задокументировано?
(в настоящее время я использую TF 2.1)