ValueError: Found zero restored functions for caller function

Viewed 792

I have run into this very weird and frustrating streak of errors in TensorFlow. I am using the Shakespeare text generator from this website: (https://www.tensorflow.org/tutorials/text/text_generation) and I got to import my own model and get it to work for my intended purposes the first two times, but then it started yielding the following errors:

ValueError: The same saveable will be restored with two names: ids_from_chars/_table/.ATTRIBUTES/table 

I was able to solve this one with the advice from this link: https://github.com/tensorflow/tensorflow/issues/46867, which suggested that I changed a very specific line of code intended for devs:

"A hack that worked for me was to edit the module throwing the error i.e. changing line number 329 in the file /usr/local/lib/python3.6/dist-packages/tensorflow/python/training/saving/saveable_object_util.py from"

if saveable.op in seen_ops:

to

if saveable.op is not None and saveable.op in seen_ops:

But then I got yet another error:

ValueError: Found zero restored functions for caller function.

From the alert, I suppose it means that TensorFlow is failing to save the model properly, so I tried using other TensorFlow versions such as 2.3, 2.4, and nightly (I am currently using this one), but they all yield some sort of error. I cannot downgrade any further because tf2.2 does not support the StringLookup() function, which I need. I am very stuck so I would appreciate some help.

Additional Info:

  • I am not using Conda but rather another virtual environment: https://www.tensorflow.org/install/pip
  • The model works just fine, but tf fails to import/export the model
  • I already tried several ways of saving the model as a whole (model.save(), tf.saved_model.save(), tf.saved_model.load())
  • I am not sure if I only need the weights, but if I can just do this then a quick explanation on how to do this would be great

Thanks!

1 Answers

I'm facing the same issue. Unfortunately I can't find a solution to the ValueError issue that avoids having to futz with some gnarly parts of the tensorflow library directly. I would suggest that the best way to solve completely will be to narrow down a working version of the tensorflow and keras dependencies with trial and error, as presumably the tutorial worked at some point! I haven't done this yet myself, but from github issues it looks like we're looking at before November of 2020 for a working set of dependencies.

However, if you do just need the weights, the following solution works for me:

import tensorflow as tf
from tensorflow.keras.layers.experimental import preprocessing

from rnn.simple_gru import SimpleGru # This class is nearly identical to MyModel in the tutorial
from predictors.one_step import StepPredictor # This class is nearly identical to OneStep in the tutorial, but change method name generate_one_step to method name predict_step

embedding_dim = 256
rnn_units = 1024

checkpoint_dir =  "training_checkpoints"
checkpoint_path = checkpoint_dir + "/ckpt_20"
print(os.listdir(checkpoint_dir))

corpus_file = ...file saved

tf.config.run_functions_eagerly(True)

text = open(corpus_file, 'rb').read().decode(encoding='utf-8')
vocab = sorted(set(text))
print(f'{len(vocab)} unique characters')

ids_from_chars = preprocessing.StringLookup(
    vocabulary=list(vocab), mask_token=None)
chars_from_ids = tf.keras.layers.experimental.preprocessing.StringLookup(
    vocabulary=ids_from_chars.get_vocabulary(), invert=True, mask_token=None)
def text_from_ids(ids):
    return tf.strings.reduce_join(chars_from_ids(ids), axis=-1)

model = SimpleGru(
    vocab_size=len(ids_from_chars.get_vocabulary()),
    embedding_dim=embedding_dim,
    rnn_units=rnn_units
)
model.built = True

adam = tf.keras.optimizers.Adam(
    learning_rate=tf.Variable(0.001),
    beta_1=tf.Variable(0.9),
    beta_2=tf.Variable(0.999),
    epsilon=tf.Variable(1e-7),
)
adam.iterations
adam.decay = tf.Variable(0.0)
loss = tf.losses.SparseCategoricalCrossentropy(from_logits=True)
model.compile(optimizer=adam, loss=loss)

load_status = model.load_weights(filepath=checkpoint_path)

def split_input_target(sequence):
    input_text = sequence[:-1]
    target_text = sequence[1:]
    return input_text, target_text

all_ids = ids_from_chars(tf.strings.unicode_split(text, 'UTF-8'))
ids_dataset = tf.data.Dataset.from_tensor_slices(all_ids)
seq_length = 100
sequences = ids_dataset.batch(seq_length+1, drop_remainder=True)
dataset = sequences.map(split_input_target)
loss = model.evaluate(dataset)
print("Restored model, loss: {:5.2f}".format(loss))

# Not necessary for this to work, but useful for debugging
load_status.assert_consumed()

step_predictor = StepPredictor(model, chars_from_ids, ids_from_chars)

states = None
next_char = tf.constant(['ROMEO:'])
result = [next_char]

for n in range(100):
  next_char, states = step_predictor.predict_step(next_char, states=states)
  result.append(next_char)

print(tf.strings.join(result)[0].numpy().decode('utf-8'))

While this should work, it takes a long time to load on larger models.

Trying to get_weights from the model does not work for me (AttributeError: '_UserObject' object has no attribute 'get_weights') - this is why I'm loading them from the last checkpoint.

I would personally suggest taking what you've learned from the tutorial and moving on to other things; not everything in the tutorial can work well and much of the behaviour it depends on is poorly documented, outdated or both. I don't think tensorflow follows semver at all either, as there are many breaking changes in v2, which makes things harder.

Related