AttributeError: у слоя нет входящих узлов, или AttributeError: уровень никогда не вызывался

Мне нужен способ получить форму выходного тензора для любого типа слоя (например, Dense, Conv2D и т. Д.) В TensorFlow. Согласно документации, есть свойство output_shape, которое решает проблему. Однако каждый раз, когда я обращаюсь к нему, я получаю AttributedError.

Вот пример кода, показывающий проблему:

import numpy as np
import tensorflow as tf


x = np.arange(0, 8, dtype=np.float32).reshape((1, 8))
x = tf.constant(value=x, dtype=tf.float32, verify_shape=True)

dense = tf.layers.Dense(units=2)

out = dense(x)

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    res = sess.run(fetches=out)
    print(res)
    print(dense.output_shape)

Оператор print(dense.output_shape) выдаст сообщение об ошибке:

AttributeError: The layer has never been called and thus has no defined output shape.

или print(dense.output) произведет:

AttributeError('Layer ' + self.name + ' has no inbound nodes.')
AttributeError: Layer dense_1 has no inbound nodes.

Есть ли способ исправить ошибку?

P.S .: Я знаю, что в примере выше я могу получить форму выходного тензора через out.get_shape(). Однако я хочу знать, почему свойство output_shape не работает и как это исправить?


person NShiny    schedule 15.01.2019    source источник


Ответы (1)


TL;DR

Как это исправить? Определите входной слой:

x = tf.keras.layers.Input(tensor=tf.ones(shape=(1, 8)))
dense = tf.layers.Dense(units=2)

out = dense(x)

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    res = sess.run(fetches=out)
    print(dense.output_shape) # shape = (1, 2)

В соответствии с документацией Кераса, если слой имеет единственный узел , вы можете получить его входной тензор, выходной тензор, входную форму и выходную форму с помощью:

  • layer.input
  • layer.output
  • layer.input_shape
  • layer.output_shape

Но в приведенном выше примере, когда мы вызываем layer.output_shape или другие атрибуты, он генерирует исключения, которые кажутся немного странными.

Если углубиться в исходный код, ошибка вызвана входящими узлами.

if not self._inbound_nodes:
  raise AttributeError('The layer has never been called '
                       'and thus has no defined output shape.')

Что это за входящие узлы?

Узел описывает связь между двумя уровнями. Каждый раз, когда слой подключается к какому-либо новому входу, узел добавляется в layer._inbound_nodes. Каждый раз, когда выходные данные уровня используются другим слоем, узел добавляется в layer._outbound_nodes.

Как видно из вышеизложенного, когда self._inbounds_nodes равно None, возникает исключение. Это означает, что когда слой не подключен к входному слою или, в более общем смысле, ни один из предыдущих слоев не подключен к входному слою, self._inbounds_nodes пуст, что вызвало проблему.

Обратите внимание, что x в вашем примере - это тензор, а не входной слой. См. Еще один пример для дополнительных разъяснений:

x = tf.keras.layers.Input(shape=(8,))
dense = tf.layers.Dense(units=2)

out = dense(x)

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    res = sess.run(fetches=out, feed_dict={x: np.ones(shape=(1, 8))})
    print(res)
    print(res.shape)  # shape = (1,2)
    print(dense.output_shape)  # shape = (None,2)

Это прекрасно, потому что входной слой определен.


Обратите внимание, что в вашем примере out - это тензор. Разница между функцией tf.shape() и .shape = (_ 11_) заключается в следующем:

tf.shape(x) возвращает одномерный целочисленный тензор, представляющий динамическую форму x. Динамическая форма будет известна только во время выполнения графа.

x.shape возвращает кортеж Python, представляющий статическую форму x. Статическая форма, известная во время определения графика.

Подробнее о форме тензора см .: https://pgaleone.eu/tensorflow/2018/07/28/understanding-tensorflow-tensors-shape-static-dynamic/

person Amir    schedule 15.01.2019
comment
Я не уверен, что ваш ответ поможет мне решить мою проблему. tf.shape работает с тензорами, а tf.layers.Dense не тензор, а слой (т.е. подкласс tf.layers.Layer и tf.keras.layers.Layer. Что касается атрибута x.shape, я не уверен, что вы имеете в виду. Согласно документация Плотный слой не имеет такого атрибута. Что касается динамической формы, то в моем примере это не так. Если я добавлю tf.shape(out).eval() внутри with в моем примере, тогда он вернет [1 2], что означает, что выходной тензор имеет статическую форму. - person NShiny; 16.01.2019
comment
Большое спасибо! Это действительно помогло. - person NShiny; 19.01.2019