Tensorflow Keras Input layer does not add _keras_shape - python

According to the keras documentation, Input adds the _keras_shape attribute to the input tensor. However, as shown below, this is not the case.
import tensorflow as tf
s = tf.keras.layers.Input(shape=[2], dtype=tf.float32, name='s')
print(s._keras_shape)
Traceback (most recent call last):
File "<input>", line 3, in <module>
AttributeError: 'Tensor' object has no attribute '_keras_shape'
Have I misunderstood something, or is this a bug I should report?
The lack of this attribute makes further Keras functions go haywire:
q_s = q(s)
model = Model(inputs=s, outputs=q_s)
Traceback (most recent call last):
...
File "/home/reuben/.virtualenvs/tensorflow/lib/python3.5/site-packages/keras/engine/network.py", line 253, in <listcomp>
input_shapes=[x._keras_shape for x in self.inputs],
AttributeError: 'Tensor' object has no attribute '_keras_shape'
I'm using tensorflow version '1.11.0-rc2'

The input layer you get appears to be slightly different depending on whether you are importing from keras or whether you're importing it through tensorflow. The keras documentation you linked is based on importing layers from the keras library directly:
For example:
import tensorflow as tf
from keras.layers import Input
s = Input(shape=[2], dtype=tf.float32, name='2')
s._shape_val # None
s._keras_shape # (None, 2)
However importing through tensorflow appears to save the shape in the tensorflow attribute _shape_val instead:
import tensorflow as tf
s = tf.keras.layers.Input(shape=[2], dtype=tf.float32, name='s')
s._shape_val # TensorShape([Dimension(None), Dimension(2)])
s._keras_shape # Error
Your best bet is to just import the layer from keras directly. If you plan to continue using tf.keras instead of the main implementation of keras, you should refer to the tf.keras docs instead of keras.io.

Documentation here does not mention _keras_shape.
"The added Keras attribute is: _keras_history: Last layer applied to the tensor. the entire layer graph is retrievable from that layer, recursively."
When you say "makes further Keras functions go haywire", what do you mean?

Related

ValueError: Model output "Tensor("activation_1/Identity:0", shape=(?, 3), dtype=float32)" has invalid shape

I am trying to run the following github code for stock market prediction:
https://github.com/multidqn/deep-q-trading
using their instructions, I run the following after installing the required libraries:
python main.py 3 0 results_folder
However, when I run the above command, I get the following error:
Using TensorFlow backend.
WARNING:tensorflow:From /Users/anisschohra/.local/lib/python3.7/site-packages/keras/backend/tensorflow_backend.py:68: The name tf.get_default_graph is deprecated. Please use tf.compat.v1.get_default_graph instead.
WARNING:tensorflow:From /Users/anisschohra/.local/lib/python3.7/site-packages/keras/backend/tensorflow_backend.py:508: The name tf.placeholder is deprecated. Please use tf.compat.v1.placeholder instead.
WARNING:tensorflow:From /Users/anisschohra/.local/lib/python3.7/site-packages/keras/backend/tensorflow_backend.py:3837: The name tf.random_uniform is deprecated. Please use tf.random.uniform instead.
Traceback (most recent call last):
File "main.py", line 92, in <module>
ensembleFolderName=sys.argv[3]
File "/Users/anisschohra/deep-q-trading/deepQTrading.py", line 68, in __init__
enable_double_dqn=True,enable_dueling_network=True)
File "/Users/anisschohra/.local/lib/python3.7/site-packages/rl/agents/dqn.py", line 107, in __init__
raise ValueError(f'Model output "{model.output}" has invalid shape. DQN expects a model that has one dimension for each action, in this case {self.nb_actions}.')
ValueError: Model output "Tensor("activation_1/Identity:0", shape=(?, 3), dtype=float32)" has invalid shape. DQN expects a model that has one dimension for each action, in this case 3.
Could you please help me fix the issue and run the code successfully? I have looked for the error but did not find a solution that works. The model architecture in their code (main.py) is as follows:
model = Sequential()
model.add(Flatten(input_shape=(1,1,68)))
model.add(Dense(35,activation='linear'))
model.add(LeakyReLU(alpha=.001))
model.add(Dense(nb_actions))
model.add(Activation('linear'))
Thanks in advance.
I have the same problem with you, and I`m not so familiar with RL but I guess I reached the cause.
if list(model.output.shape) != list((None, self.nb_actions)):
raise ValueError(f'Model output "{model.output}" has invalid shape. DQN expects a model that has one dimension for each action, in this case {self.nb_actions}.')
According to the traceback, this is the code which causes the problem.
Your model`s output shape is a tensor object, so list(model.output.shape) will be like [Dimension(None), Dimension(3)], but list((None, self.nb_actions)) is [None, 3], so it will be judged as different.
So I think if there is a way that can convert shape of the model`s output to numpy or list object we can solve this problem. Sorry for my poor English!

I can't load my trained h5 model with load.models(), how do I fix this error?

So I think tensorflow.keras and the independant keras packages are in conflict and I can't load my model, which I have made with transfer learning.
Import in the CNN ipynb:
!pip install tensorflow-gpu==2.0.0b1
import tensorflow as tf
from tensorflow import keras
print(tf.__version__)
Loading this pretrained model
base_model = keras.applications.xception.Xception(weights="imagenet",
include_top=False)
avg = keras.layers.GlobalAveragePooling2D()(base_model.output)
output = keras.layers.Dense(n_classes, activation="softmax")(avg)
model = keras.models.Model(inputs=base_model.input, outputs=output)
Saving with:
model.save('Leavesnet Model 2.h5')
Then in the new ipynb for the already trained model (the imports are the same as in the CNN ipynb:
from keras.models import load_model
model =load_model('Leavesnet Model.h5')
I get the error:
AttributeError Traceback (most recent call last)
<ipython-input-4-77ca5a1f5f24> in <module>()
2 from keras.models import load_model
3
----> 4 model =load_model('Leavesnet Model.h5')
13 frames
/usr/local/lib/python3.6/dist-packages/keras/backend/tensorflow_backend.py in placeholder(shape, ndim, dtype, sparse, name)
539 x = tf.sparse_placeholder(dtype, shape=shape, name=name)
540 else:
--> 541 x = tf.placeholder(dtype, shape=shape, name=name)
542 x._keras_shape = shape
543 x._uses_learning_phase = False
AttributeError: module 'tensorflow' has no attribute 'placeholder'
I think there might be a conflict between tf.keras and the independant keras, can someone help me out?
Yes, there is a conflict between tf.keras and keras packages, you trained the model using tf.keras but then you are loading it with the keras package. That is not supported, you should use only one version of this package.
The specific problem is that you are using TensorFlow 2.0, but the standalone keras package does not support TensorFlow 2.0 yet.
Try to replace
from keras.models import load_model
model =load_model('Leavesnet Model.h5')
with
model = tf.keras.models.load_model(model_path)
It works for me, and I am using:
tensorflow version: 2.0.0
keras version: 2.3.1
You can check the following:
https://www.tensorflow.org/api_docs/python/tf/keras/models/load_model?version=stable
I think downgrading your keras or tensorflow will not be that much suitable because you need to retrain your model for various dependencies. Why not try to load the weights instead of loading the model?
here is a piece of code
import tensorflow as tf
{your code here}
#save the weights
model.save_weights('model_checkpoint')
#initialise the model again (example - MobileNetv2)
encoder = MobileNetV2(input_tensor=inputs, weights="imagenet", include_top=False, alpha=0.35)
#load the weights
encoder.load_weights('model_checkpoint')
and you are good to go

AttributeError when using callback Tensorboard on Keras: 'Model' object has no attribute 'run_eagerly'

I have built a model using the functional API from Keras, and when I am adding the tensorboard instance to my callbacks in my model.fit() function, it throws an Error: "AttributeError: 'Model' object has no attribute 'run_eagerly'"
The Model class does indeed not have an attribute run_eagerly, but in the Keras doc, it says that it can be passed as parameter to the model.compile() function. This returns
"ValueError: ('Some keys in session_kwargs are not supported at this time: %s', dict_keys(['run_eagerly']))"
Does this mean I don't have a suitable version of Tensorflow/Keras?
Tensorflow: 1.14.0
Keras: 2.2.4-tf
model = Model(inputs=[input_ant1, input_ant2], outputs=main_output)
tensorboard = TensorBoard(log_dir='.logs/'.format(time()))
[...]
model.fit([input1, input2],[labels], epochs=10, callbacks=[tensorboard])
I got the same error : AttributeError: 'Model' object has no attribute 'run_eagerly'
After two minor changes my tensorboard is running now.
make sure you import tensorboard as follows:
from keras.callbacks import TensorBoard
change the log dir like this:
tensorboard = TensorBoard(log_dir="logs")
I got same error message when I use:
from tensorflow.keras.callbacks import ModelCheckpoint
I fix it with by importing the same as:
from keras.callbacks.callbacks import ModelCheckpoint

Keras + Tensorflow: 'ConvLSTM2D' object has no attribute 'outbound_nodes'

I’m trying to have a ConvLSTM as part of my functioning tensorflow network, because I had some issues with using the tensorflow ConvLSTM implementation, I settled for using the ConvLSTM2D Keras Layer instead.
To make Keras available in my Tensorflow session I used the blogposts suggestion (I’m using the Tensorflow backend):
https://blog.keras.io/keras-as-a-simplified-interface-to-tensorflow-tutorial.html
import tensorflow as tf
sess = tf.Session()
from keras import backend as K
K.set_session(sess)
A snippet of my code (that what causes the issues):
# state has a shape of [1, 75, 32, 32] with batchsize=1
state = tf.concat([screen, screen2, non_spatial], axis=1)
# Reshaping state to get time=1 to have the right shape for the ConvLSTM
state_reshaped = tf.reshape(state, [1, 1, 75, 32, 32])
# Keras ConvLSTM2D Layer
# I tried leaving out the batch_size for the input_shape but it didn't make a difference for the error and it seems to be fine
lstm_layer = ConvLSTM2D(filters=5, kernel_size=(3, 3), input_shape=(1, 1, 75, 32, 32), data_format='channels_first', stateful=True)(state_reshaped)
fc1 = layers.fully_connected(inputs=layers.flatten(lstm_layer), num_outputs=256, activation_fn=tf.nn.relu)
This gives me the following error:
AttributeError: 'ConvLSTM2D' object has no attribute 'outbound_nodes’”
I have no idea what this means. I thought it might has to do with mixing Keras ConvLSTM and tensorflows flatten. So I tried using Keras Flatten() instead like this:
# lstm_layer shape is (5, 5, 30, 30)
lstm_layer = Flatten(data_format='channels_first')(lstm_layer)
fc1 = layers.fully_connected(inputs=lstm_layer, num_outputs=256, activation_fn=tf.nn.relu)
and got the following error: ValueError: The last dimension of the inputs to 'Dense' should be defined. Found 'None'.
This error is caused by Flatten(), for whatever reason, having an output shape of (?, ?) and the fullyconnected layer needing to have a defined shape for the last dimension but I don't understand why it would be undefined. It was defined before.
Using Reshape((4500,))(lstm_layer) instead gives me the same no attribute 'outbound_nodes' error.
I googled the issue and I seem to not be the only one but I couldn't find a solution.
How can I solve this issue?
Is the unknown output shape of Flatten() a bug or wanted behavior, if so why?
I encountered the same problem and had a bit of a dig into the tensorflow code. The problem is that there was some refactoring done for Keras 2.2.0 and tf.keras hasn't yet been updated to this new API.
The 'outbound_nodes' attribute was renamed to '_outbound_nodes' in Keras 2.2.0. It's pretty easy to fix, there's two references in base.py you need to update:
/site-packages/tensorflow/python/layers/base.py
After updating it works fine for me.
In my case I was getting the error on a custom subclass, but the following solution can be applied nonetheless, if you subclass ConvLSTM2D and add this to your new class:
#property
def outbound_nodes(self):
if hasattr(self, '_outbound_nodes'):
print("outbound_nodes called but _outbound_nodes found")
return getattr(self, '_outbound_nodes', [])
I found the solution, even though I don't know why it works.
Currently I'm using Tensorflow 1.8 and Keras 2.2. If you downgrade Keras to ~2.1.1 it works without any problems and you can easily use Keras layers together with tensorflow. This fixed AttributeError: 'ConvLSTM2D' object has no attribute 'outbound_nodes’” and then I just used layers.flatten(lstm_layer) and everything worked.
As others have pointed out, this is because of a mismatch between your installed tensorflow and keras libraries.
Their solutions work, but in my opinion, the cleanest and easiest way to solve this is by using the keras layers contained within the tensorflow package itself rather than by using the keras library directly.
i.e, replace
from keras.layers import ConvLSTM2D
by
from tensorflow.python.keras.layers import ConvLSTM2D
This will ensure that your tensorflow and keras function calls / objects are always compatible, and solved this issue for me.

Error when building seq2seq model with tensorflow

I'm trying to understand the seq2seq models defined in seq2seq.py in tensorflow. I use bits of code I copy from the translate.py example that comes with tensorflow. I keep getting the same error and really do not understand where it comes from.
A minimal code example to reproduce the error:
import tensorflow as tf
from tensorflow.models.rnn import rnn_cell
from tensorflow.models.rnn import seq2seq
encoder_inputs = []
decoder_inputs = []
for i in xrange(350):
encoder_inputs.append(tf.placeholder(tf.int32, shape=[None],
name="encoder{0}".format(i)))
for i in xrange(45):
decoder_inputs.append(tf.placeholder(tf.int32, shape=[None],
name="decoder{0}".format(i)))
model = seq2seq.basic_rnn_seq2seq(encoder_inputs,
decoder_inputs,rnn_cell.BasicLSTMCell(512))
The error I get when evaluating the last line (I evaluated it interactively in the python interpreter):
>>> Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/tmp/py1053173el", line 12, in <module>
File "/usr/local/lib/python2.7/dist-packages/tensorflow/models/rnn/seq2seq.py", line 82, in basic_rnn_seq2seq
_, enc_states = rnn.rnn(cell, encoder_inputs, dtype=dtype)
File "/usr/local/lib/python2.7/dist-packages/tensorflow/models/rnn/rnn.py", line 85, in rnn
output_state = cell(input_, state)
File "/usr/local/lib/python2.7/dist-packages/tensorflow/models/rnn/rnn_cell.py", line 161, in __call__
concat = linear.linear([inputs, h], 4 * self._num_units, True)
File "/usr/local/lib/python2.7/dist-packages/tensorflow/models/rnn/linear.py", line 32, in linear
raise ValueError("Linear is expecting 2D arguments: %s" % str(shapes))
ValueError: Linear is expecting 2D arguments: [[None], [None, 512]]
I suspect the error comes from my side :)
On a sidenote. The documentation and the tutorials are really great but the example code for the sequence to sequence model (the english to french translation example) is quite dense. You also have to jump a lot between files to understand what's going on. Me at least got lost several times in the code.
A minimal example (perhaps on some toy data) of constructing and training a basic seq2seq model would really be helpful here. Somebody know if this already exist somewhere?
EDIT
I have fixed the code above according #Ishamael suggestions (meaning, no errors returns) (see below), but there are still some things not clear in this fixed version. My input is a sequence of vectors of length 2 of real valued values. And my output is a sequence of binary vectors of length 22. Should my tf.placeholder code not look like the following? (EDIT yes)
tf.placeholder(tf.float32, shape=[None,2],name="encoder{0}".format(i))
tf.placeholder(tf.float32, shape=[None,22],name="encoder{0}".format(i))
I also had to change tf.int32 to tf.float32 above. Since my output is binary. Should this not be tf.int32 for the tf.placeholder of my decoder? But tensorflow complains again if I do this. I'm not sure what the reasoning is behind this.
The size of my hidden layer is 512 here.
the complete fixed code
import tensorflow as tf
from tensorflow.models.rnn import rnn_cell
from tensorflow.models.rnn import seq2seq
encoder_inputs = []
decoder_inputs = []
for i in xrange(350):
encoder_inputs.append(tf.placeholder(tf.float32, shape=[None,512],
name="encoder{0}".format(i)))
for i in xrange(45):
decoder_inputs.append(tf.placeholder(tf.float32, shape=[None,512],
name="decoder{0}".format(i)))
model = seq2seq.basic_rnn_seq2seq(encoder_inputs,
decoder_inputs,rnn_cell.BasicLSTMCell(512))
Most of the models (seq2seq is not an exception) expect their input to be in batches, so if the shape of your logical input is [n], then a shape of a tensor you will be using as an input to your model should be [batch_size x n]. In practice the first dimension of the shape is usually left out as None and inferred to be the batch size at runtime.
Since the logical input to seq2seq is a vector of numbers, the actual tensor shape should be [None, input_sequence_length]. So fixed code would look along the lines of:
input_sequence_length = 2; # the length of one vector in your input sequence
for i in xrange(350):
encoder_inputs.append(tf.placeholder(tf.int32, shape=[None, input_sequence_length],
name="encoder{0}".format(i)))
(and then the same for the decoder)
There is a self-test method in the translate module that shows its minimal usage.[here]
I just ran the self-test method using.
python translate.py --self_test 1

Categories

Resources