Выполняет ли функция Кераса все задействованные части вычислительного графа? - PullRequest
0 голосов
/ 25 января 2020

Существует несколько вопросов о переполнении стека, связанных с 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)

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