TL;DR
How can I fix it? Define an input layer:
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)
Accordint to Keras documentation, if a layer has a single node, you can get its input tensor, output tensor, input shape and output shape via:
- layer.input
- layer.output
- layer.input_shape
- layer.output_shape
But in the above example, when we call layer.output_shape
or other attributes, it throws exceptions that seem a bit strange.
If we go deep in the source code, the error caused by inbound nodes.
if not self._inbound_nodes:
raise AttributeError('The layer has never been called '
'and thus has no defined output shape.')
What these inbound nodes are?
A Node describes the connectivity between two layers. Each time a layer is connected to some new input,
a node is added to layer._inbound_nodes.
Each time the output of a layer is used by another layer,
a node is added to layer._outbound_nodes.
As you can see in the above, when self._inbounds_nodes
is None it throws an exception. This means when a layer is not connected to the input layer or more generally, none of the previous layers are connected to an input layer, self._inbounds_nodes
is empty which caused the problem.
Notice that x
in your example, is a tensor and not an input layer. See another example for more clarification:
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)
It is perfectly fine because the input layer is defined.
Note that, in your example, out
is a tensor. The difference between the tf.shape()
function and the .shape
=(get_shape()
) is:
tf.shape(x)
returns a 1-D integer tensor representing the dynamic
shape of x. A dynamic shape will be known only at graph execution time.
x.shape
returns a Python tuple representing the static
shape of x. A static shape, known at graph definition time.
Read more about tensor shape at: https://pgaleone.eu/tensorflow/2018/07/28/understanding-tensorflow-tensors-shape-static-dynamic/