lmnt-com / haste

Haste: a fast, simple, and open RNN library
Apache License 2.0
325 stars 27 forks source link

Can't run haste layers in Keras #33

Open mahenning opened 3 years ago

mahenning commented 3 years ago

Hello,

I know this seems more of a debugging problem/problem on my side, but get the following error message when running my code, and it only appears when running it with a haste layer:

Traceback (most recent call last):
  File "<string>", line 1331, in haste_lstm
  File "<string>", line 1379, in haste_lstm_eager_fallback
  File "/mnt/SSD/Marko/Dokumente/Uni/SoSe21/MA/LSTM_testproject/envs/LSTM_testproject/lib/python3.7/site-packages/tensorflow/python/eager/execute.py", line 280, in args_to_matching_eager
    ret = [ops.convert_to_tensor(t, dtype, ctx=ctx) for t in l]
  File "/mnt/SSD/Marko/Dokumente/Uni/SoSe21/MA/LSTM_testproject/envs/LSTM_testproject/lib/python3.7/site-packages/tensorflow/python/eager/execute.py", line 280, in <listcomp>
    ret = [ops.convert_to_tensor(t, dtype, ctx=ctx) for t in l]
  File "/mnt/SSD/Marko/Dokumente/Uni/SoSe21/MA/LSTM_testproject/envs/LSTM_testproject/lib/python3.7/site-packages/tensorflow/python/profiler/trace.py", line 163, in wrapped
    return func(*args, **kwargs)
  File "/mnt/SSD/Marko/Dokumente/Uni/SoSe21/MA/LSTM_testproject/envs/LSTM_testproject/lib/python3.7/site-packages/tensorflow/python/framework/ops.py", line 1540, in convert_to_tensor
    ret = conversion_func(value, dtype=dtype, name=name, as_ref=as_ref)
  File "/mnt/SSD/Marko/Dokumente/Uni/SoSe21/MA/LSTM_testproject/envs/LSTM_testproject/lib/python3.7/site-packages/tensorflow/python/framework/constant_op.py", line 339, in _constant_tensor_conversion_function
    return constant(v, dtype=dtype, name=name)
  File "/mnt/SSD/Marko/Dokumente/Uni/SoSe21/MA/LSTM_testproject/envs/LSTM_testproject/lib/python3.7/site-packages/tensorflow/python/framework/constant_op.py", line 265, in constant
    allow_broadcast=True)
  File "/mnt/SSD/Marko/Dokumente/Uni/SoSe21/MA/LSTM_testproject/envs/LSTM_testproject/lib/python3.7/site-packages/tensorflow/python/framework/constant_op.py", line 276, in _constant_impl
    return _constant_eager_impl(ctx, value, dtype, shape, verify_shape)
  File "/mnt/SSD/Marko/Dokumente/Uni/SoSe21/MA/LSTM_testproject/envs/LSTM_testproject/lib/python3.7/site-packages/tensorflow/python/framework/constant_op.py", line 301, in _constant_eager_impl
    t = convert_to_eager_tensor(value, ctx, dtype)
  File "/mnt/SSD/Marko/Dokumente/Uni/SoSe21/MA/LSTM_testproject/envs/LSTM_testproject/lib/python3.7/site-packages/tensorflow/python/framework/constant_op.py", line 98, in convert_to_eager_tensor
    return ops.EagerTensor(value, ctx.device_name, dtype)
  File "/mnt/SSD/Marko/Dokumente/Uni/SoSe21/MA/LSTM_testproject/envs/LSTM_testproject/lib/python3.7/site-packages/tensorflow/python/keras/engine/keras_tensor.py", line 274, in __array__
    'Cannot convert a symbolic Keras input/output to a numpy array. '
TypeError: Cannot convert a symbolic Keras input/output to a numpy array. This error may indicate that you're trying to pass a symbolic value to a NumPy call, which is not supported. Or, you may be trying to pass Keras symbolic inputs/outputs to a TF API that does not register dispatching, preventing Keras from automatically converting the API call to a lambda layer in the Functional Model.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "/snap/pycharm-professional/237/plugins/python/helpers/pydev/_pydev_bundle/pydev_umd.py", line 197, in runfile
    pydev_imports.execfile(filename, global_vars, local_vars)  # execute the script
  File "/snap/pycharm-professional/237/plugins/python/helpers/pydev/_pydev_imps/_pydev_execfile.py", line 18, in execfile
    exec(compile(contents+"\n", file, 'exec'), glob, loc)
  File "/mnt/SSD/Marko/Dokumente/Uni/SoSe21/MA/time-series-on-joints-emg/src/all_in_one_file.py", line 394, in <module>
    x, state = haste1(x, training=True)
  File "/mnt/SSD/Marko/Dokumente/Uni/SoSe21/MA/LSTM_testproject/envs/LSTM_testproject/lib/python3.7/site-packages/haste_tf/base_rnn.py", line 115, in __call__
    result, state = self.fw_layer(inputs, sequence_length, training)
  File "/mnt/SSD/Marko/Dokumente/Uni/SoSe21/MA/LSTM_testproject/envs/LSTM_testproject/lib/python3.7/site-packages/haste_tf/lstm.py", line 218, in __call__
    zoneout_prob=self.zoneout)
  File "<string>", line 1339, in haste_lstm
  File "/mnt/SSD/Marko/Dokumente/Uni/SoSe21/MA/LSTM_testproject/envs/LSTM_testproject/lib/python3.7/site-packages/tensorflow/python/util/dispatch.py", line 122, in dispatch
    result = dispatcher.handle(op, args, kwargs)
  File "/mnt/SSD/Marko/Dokumente/Uni/SoSe21/MA/LSTM_testproject/envs/LSTM_testproject/lib/python3.7/site-packages/tensorflow/python/keras/layers/core.py", line 1450, in handle
    return TFOpLambda(op)(*args, **kwargs)
  File "/mnt/SSD/Marko/Dokumente/Uni/SoSe21/MA/LSTM_testproject/envs/LSTM_testproject/lib/python3.7/site-packages/tensorflow/python/keras/engine/base_layer.py", line 952, in __call__
    input_list)
  File "/mnt/SSD/Marko/Dokumente/Uni/SoSe21/MA/LSTM_testproject/envs/LSTM_testproject/lib/python3.7/site-packages/tensorflow/python/keras/engine/base_layer.py", line 1091, in _functional_construction_call
    inputs, input_masks, args, kwargs)
  File "/mnt/SSD/Marko/Dokumente/Uni/SoSe21/MA/LSTM_testproject/envs/LSTM_testproject/lib/python3.7/site-packages/tensorflow/python/keras/engine/base_layer.py", line 822, in _keras_tensor_symbolic_call
    return self._infer_output_signature(inputs, args, kwargs, input_masks)
  File "/mnt/SSD/Marko/Dokumente/Uni/SoSe21/MA/LSTM_testproject/envs/LSTM_testproject/lib/python3.7/site-packages/tensorflow/python/keras/engine/base_layer.py", line 863, in _infer_output_signature
    outputs = call_fn(inputs, *args, **kwargs)
  File "/mnt/SSD/Marko/Dokumente/Uni/SoSe21/MA/LSTM_testproject/envs/LSTM_testproject/lib/python3.7/site-packages/tensorflow/python/keras/layers/core.py", line 1327, in _call_wrapper
    return self._call_wrapper(*args, **kwargs)
  File "/mnt/SSD/Marko/Dokumente/Uni/SoSe21/MA/LSTM_testproject/envs/LSTM_testproject/lib/python3.7/site-packages/tensorflow/python/keras/layers/core.py", line 1359, in _call_wrapper
    result = self.function(*args, **kwargs)
TypeError: haste_lstm() missing 1 required positional argument: 'training'

I construct the model with the following code:

inputs = k_l.Input(shape=(train_x.shape[1], train_x.shape[2]))
direction = 'unidirectional' if args.model == 'GRU' else 'bidirectional'
haste1 = haste.LSTM(args.hidden_size, direction=direction, zoneout=0.1, dropout=args.dropout_time)
fc1 = k_l.Dense(args.dense_layers[0], activation='relu', kernel_initializer='he_uniform')
dr1 = k_l.Dropout(0.2)
fc2 = k_l.Dense(1)

x, state = haste1(inputs, training=True)
x = fc1(inputs)
x = dr1(x)
outputs = fc2(x)
model = keras.Model(inputs=inputs, outputs=outputs)
model.compile(loss=loss_func, optimizer=optimizer)
model_hist = model.fit(train_x, train_y, epochs=args.epochs, batch_size=args.batch_size, verbose=1,
                       validation_data=val_data, callbacks=keras_callbacks)

train_x numpy array shape is (21788, 1000, 4) OS: Ubuntu 20.04 Python version: 3.7 Keras: 2.4.3 Tensorflow: 2.4.1 numpy: 1.19.5 GPU: GTX 1060 CUDA: 11.2

Normally I wouldn't post those error messages on github, but as the code would run without the haste layer, I suspect that the cause of the error lies somewhere close to it, and this repo seems to be the best place to ask and I didn't find any solutions elsewhere. I hope you can help me, I'd really like to try out your implementation for my dataset.

thegodone commented 3 years ago

did you get / solve this issue ?

mahenning commented 3 years ago

Unfortunatelly not yet. I tried to run a sequential model with it, but for that it has to be an instance of class Layer. For now I test different possibilities, as the error doesn't give me a starting point for fixing. But if I have a solution for it, I'll post it here.

mahenning commented 3 years ago

Regarding the first error

'Cannot convert a symbolic Keras input/output to a numpy array. ' TypeError: Cannot convert a symbolic Keras input/output to a numpy array. This error may indicate that you're trying to pass a symbolic value to a NumPy call, which is not supported. Or, you may be trying to pass Keras symbolic inputs/outputs to a TF API that does not register dispatching, preventing Keras from automatically converting the API call to a lambda layer in the Functional Model.

In the Keras API docs I found this:

Note that even if eager execution is enabled, Input produces a symbolic tensor-like object (i.e. a placeholder). This symbolic tensor-like object can be used with lower-level TensorFlow ops that take tensors as inputs, as such: this is a logistic regression in Keras x = Input(shape=(32,)) y = Dense(16, activation='softmax')(x) model = Model(x, y)

(This behavior does not work for higher-order TensorFlow APIs such as control flow and being directly watched by a tf.GradientTape).

The last line in which the error message is thrown is the ..keras/layers/core.py:1359, which is wrapped backprop.GradientTape.

with backprop.GradientTape(watch_accessed_variables=True) as tape, \ variable_scope.variable_creator_scope(_variable_creator):

We explicitly drop name arguments here,

  # to guard against the case where an op explicitly has a
  # `name` passed (which is susceptible to producing
  # multiple ops w/ the same name when the layer is reused)
  kwargs.pop('name', None)
  result = self.function(*args, **kwargs)

Does that mean that the haste layers can't be used with an keras Input layer? If so, how can I create a model with them if neither the sequential nor the functional api (requires the input layer AFAIK) can be used? In your example on the main page the layer gets a tensor directly. Do I have to handle batches manually and input the data directly instead of letting the fit function work?

thegodone commented 3 years ago

import numpy as np import tensorflow as tf import haste_tf as haste

train_x = np.random.rand(500,40,20) train_y = np.random.rand(500,40,1)

inputs = tf.keras.Input(shape=(train_x.shape[1], train_x.shape[2])) haste1 = haste.LayerNormGRU(20, direction='unidirectional', zoneout=0.1, dropout=0.1) fc1 = tf.keras.layers.Dense(60, activation='relu', kernel_initializer='he_uniform') dr1 = tf.keras.layers.Dropout(0.2) fc2 = tf.keras.layers.Dense(1)

x, state = haste1(inputs, training=True) x = fc1(inputs) x = dr1(x) outputs = fc2(x)

model = tf.keras.Model(inputs=inputs, outputs=outputs)

print(model.summary())

opt = tf.keras.optimizers.Adam(learning_rate=0.01) model.compile(loss='categorical_crossentropy', optimizer=opt)

model_hist = model.fit(train_x, train_y, epochs=10, batch_size=32, verbose=1)

this code is working for me

mahenning commented 3 years ago

For me the error still remains. What python/Tensorflow version did you use for testing?

thegodone commented 3 years ago

it's a jupyter notebook on a Docker image:

GPU: "NVIDIA-SMI 418.116.00 Driver Version: 418.116.00 CUDA Version: 10.2"

print(tf.version) 2.3.0 from platform import python_version​ print(python_version()) 3.7.10 haste.version print(haste.version) 0.5.0-rc0

NAME="Ubuntu" VERSION="18.04.4 LTS (Bionic Beaver)" ID=ubuntu ID_LIKE=debian PRETTY_NAME="Ubuntu 18.04.4 LTS" VERSION_ID="18.04" HOME_URL="https://www.ubuntu.com/" SUPPORT_URL="https://help.ubuntu.com/" BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/" PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy" VERSION_CODENAME=bionic UBUNTU_CODENAME=bionic

image

I have also a version tf 2.4 / py 3.8 but not tested on this image

thegodone commented 3 years ago

Does it works for you ?

mahenning commented 3 years ago

No. Unfortunately I can't test this in another environment, as haste does not install the libhaste_tf.so when I run pip(3) install haste_tf on neither a second PC (py 3.6) nor my PC with a fresh venv with python 3.8. I tested a haste reinstall in my conda venv with python 3.7 and there the libhaste_tf.so is created (I also checked if it's getting deleted in between). Any idea on that? I understand that this is an unrelated problem to my initial post, so another issue? I really don't get what I'm doing wrong to get all this errors.

mahenning commented 3 years ago

I tested it in a google colab (https://colab.research.google.com/drive/1mHuT35cnW5uOgulDjHGPf88gm74O9Caz?usp=sharing) and there the same error occurs.

max1mn commented 3 years ago

hello, everyone. actually, the 'real' bug here is this - 'TypeError: haste_lstm() missing 1 required positional argument: 'training'

it happens because keras 'wraps' this call in https://github.com/lmnt-com/haste/blob/459608cfdb4de4d28d2213df8e71f005be8d0f35/frameworks/tf/lstm.py#L211 into TFOpLambda

LIB.haste_lstm expects 'training' argument, but when this call is wrapped, this argument is lost because in constructor of TFOpLambda the flag '_expects_training_arg' explicitly set to False and because of that 'training' is removed

this is what happens in tf 2.5.0

p.s. obvious immediate fix - just comment this line in keras sources

mahenning commented 3 years ago

Hey, thank you for figuring that out, I'll try that! But is there hope to get that fixed officially, without changing the keras core file?

mw66 commented 1 year ago

import numpy as np import tensorflow as tf import haste_tf as haste

train_x = np.random.rand(500,40,20) train_y = np.random.rand(500,40,1)

inputs = tf.keras.Input(shape=(train_x.shape[1], train_x.shape[2])) haste1 = haste.LayerNormGRU(20, direction='unidirectional', zoneout=0.1, dropout=0.1) fc1 = tf.keras.layers.Dense(60, activation='relu', kernel_initializer='he_uniform') dr1 = tf.keras.layers.Dropout(0.2) fc2 = tf.keras.layers.Dense(1)

x, state = haste1(inputs, training=True) x = fc1(inputs) x = dr1(x) outputs = fc2(x)

model = tf.keras.Model(inputs=inputs, outputs=outputs)

print(model.summary())

opt = tf.keras.optimizers.Adam(learning_rate=0.01) model.compile(loss='categorical_crossentropy', optimizer=opt)

model_hist = model.fit(train_x, train_y, epochs=10, batch_size=32, verbose=1)

this code is working for me

@thegodone actually, can you add this code as an example of how to mix haste layers into tf.keras model, I think new user will appreciate it.