tensorflow: ValueError: tf.function-decorated function tried to create variables on non-first call
Please make sure that this is a bug. As per our GitHub Policy, we only address code/doc bugs, performance issues, feature requests and build/installation issues on GitHub. tag:bug_template
System information
- OS Platform and Distribution (e.g., Linux Ubuntu 16.04): Ubuntu 18.04
- TensorFlow installed from (source or binary): pip
- TensorFlow version (use command below): 2.0.0
- Python version: 3.6.7
- CUDA/cuDNN version: 7.6.0
- GPU model and memory: 1660Ti
Describe the current behavior Error raised when I tried to train a model with function decorated with @tf.function by two different optimizer sequentially ValueError: tf.function-decorated function tried to create variables on non-first call
Describe the expected behavior The model can be trained by two different optimizer sequentially
Code to reproduce the issue Provide a reproducible test case that is the bare minimum necessary to generate the problem.
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras.layers import Flatten, Dense
from tensorflow.keras import Model
try:
gpus= tf.config.experimental.list_physical_devices('GPU')
tf.config.experimental.set_memory_growth(gpus[0], True)
except:
print('Failed to configure GPU')
cifar10 = tf.keras.datasets.cifar10
(x_train, y_train), (x_test, y_test) = cifar10.load_data()
x_train = x_train / 255.0
class MyModel(Model):
def __init__(self):
super(MyModel, self).__init__()
self.flatten = Flatten()
self.d1 = Dense(20, activation='relu')
self.d2 = Dense(10, activation='softmax')
def call(self, x):
x = self.flatten(x)
x = self.d1(x)
return self.d2(x)
optimizer = keras.optimizers.Adam(0.001)
optimizer2 = keras.optimizers.SGD(0.01)
model = MyModel()
@tf.function # it will work correctly if this line is disabled but the training becomes very slow
def train_step(model, data, labels, optimizer):
with tf.GradientTape() as tape:
pred = model(data)
loss = keras.losses.SparseCategoricalCrossentropy()(labels, pred)
grads = tape.gradient(loss, model.trainable_variables)
optimizer.apply_gradients(zip(grads, model.trainable_variables))
train_step(model, x_train[:10], y_train[:10], optimizer) # this works
train_step(model, x_train[:10], y_train[:10], optimizer2) # it can't work
Other info / logs
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-7-f4e941ca2116> in <module>
1 train_step(model, x_train[:10], y_train[:10], optimizer)
----> 2 train_step(model, x_train[:10], y_train[:10], optimizer2)
~/venv_tf2.0/lib/python3.6/site-packages/tensorflow_core/python/eager/def_function.py in __call__(self, *args, **kwds)
455
456 tracing_count = self._get_tracing_count()
--> 457 result = self._call(*args, **kwds)
458 if tracing_count == self._get_tracing_count():
459 self._call_counter.called_without_tracing()
~/venv_tf2.0/lib/python3.6/site-packages/tensorflow_core/python/eager/def_function.py in _call(self, *args, **kwds)
485 # In this case we have created variables on the first call, so we run the
486 # defunned version which is guaranteed to never create variables.
--> 487 return self._stateless_fn(*args, **kwds) # pylint: disable=not-callable
488 elif self._stateful_fn is not None:
489 # Release the lock early so that multiple threads can perform the call
~/venv_tf2.0/lib/python3.6/site-packages/tensorflow_core/python/eager/function.py in __call__(self, *args, **kwargs)
1820 def __call__(self, *args, **kwargs):
1821 """Calls a graph function specialized to the inputs."""
-> 1822 graph_function, args, kwargs = self._maybe_define_function(args, kwargs)
1823 return graph_function._filtered_call(args, kwargs) # pylint: disable=protected-access
1824
~/venv_tf2.0/lib/python3.6/site-packages/tensorflow_core/python/eager/function.py in _maybe_define_function(self, args, kwargs)
2148 graph_function = self._function_cache.primary.get(cache_key, None)
2149 if graph_function is None:
-> 2150 graph_function = self._create_graph_function(args, kwargs)
2151 self._function_cache.primary[cache_key] = graph_function
2152 return graph_function, args, kwargs
~/venv_tf2.0/lib/python3.6/site-packages/tensorflow_core/python/eager/function.py in _create_graph_function(self, args, kwargs, override_flat_arg_shapes)
2039 arg_names=arg_names,
2040 override_flat_arg_shapes=override_flat_arg_shapes,
-> 2041 capture_by_value=self._capture_by_value),
2042 self._function_attributes,
2043 # Tell the ConcreteFunction to clean up its graph once it goes out of
~/venv_tf2.0/lib/python3.6/site-packages/tensorflow_core/python/framework/func_graph.py in func_graph_from_py_func(name, python_func, args, kwargs, signature, func_graph, autograph, autograph_options, add_control_dependencies, arg_names, op_return_value, collections, capture_by_value, override_flat_arg_shapes)
913 converted_func)
914
--> 915 func_outputs = python_func(*func_args, **func_kwargs)
916
917 # invariant: `func_outputs` contains only Tensors, CompositeTensors,
~/venv_tf2.0/lib/python3.6/site-packages/tensorflow_core/python/eager/def_function.py in wrapped_fn(*args, **kwds)
356 # __wrapped__ allows AutoGraph to swap in a converted function. We give
357 # the function a weak reference to itself to avoid a reference cycle.
--> 358 return weak_wrapped_fn().__wrapped__(*args, **kwds)
359 weak_wrapped_fn = weakref.ref(wrapped_fn)
360
~/venv_tf2.0/lib/python3.6/site-packages/tensorflow_core/python/framework/func_graph.py in wrapper(*args, **kwargs)
903 except Exception as e: # pylint:disable=broad-except
904 if hasattr(e, "ag_error_metadata"):
--> 905 raise e.ag_error_metadata.to_exception(e)
906 else:
907 raise
ValueError: in converted code:
<ipython-input-2-db5119c2db0a>:27 train_step *
optimizer.apply_gradients(zip(grads, model.trainable_variables))
/home/wilson/venv_tf2.0/lib/python3.6/site-packages/tensorflow_core/python/keras/optimizer_v2/optimizer_v2.py:433 apply_gradients
_ = self.iterations
/home/wilson/venv_tf2.0/lib/python3.6/site-packages/tensorflow_core/python/keras/optimizer_v2/optimizer_v2.py:541 __getattribute__
return super(OptimizerV2, self).__getattribute__(name)
/home/wilson/venv_tf2.0/lib/python3.6/site-packages/tensorflow_core/python/keras/optimizer_v2/optimizer_v2.py:655 iterations
aggregation=tf_variables.VariableAggregation.ONLY_FIRST_REPLICA)
/home/wilson/venv_tf2.0/lib/python3.6/site-packages/tensorflow_core/python/keras/optimizer_v2/optimizer_v2.py:805 add_weight
aggregation=aggregation)
/home/wilson/venv_tf2.0/lib/python3.6/site-packages/tensorflow_core/python/training/tracking/base.py:744 _add_variable_with_custom_getter
**kwargs_for_getter)
/home/wilson/venv_tf2.0/lib/python3.6/site-packages/tensorflow_core/python/keras/engine/base_layer_utils.py:139 make_variable
shape=variable_shape if variable_shape else None)
/home/wilson/venv_tf2.0/lib/python3.6/site-packages/tensorflow_core/python/ops/variables.py:258 __call__
return cls._variable_v1_call(*args, **kwargs)
/home/wilson/venv_tf2.0/lib/python3.6/site-packages/tensorflow_core/python/ops/variables.py:219 _variable_v1_call
shape=shape)
/home/wilson/venv_tf2.0/lib/python3.6/site-packages/tensorflow_core/python/ops/variables.py:65 getter
return captured_getter(captured_previous, **kwargs)
/home/wilson/venv_tf2.0/lib/python3.6/site-packages/tensorflow_core/python/eager/def_function.py:413 invalid_creator_scope
"tf.function-decorated function tried to create "
ValueError: tf.function-decorated function tried to create variables on non-first call.
How should I correct it if possible? Or it’s still a bug? related issue #27120 Thanks!
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Comments: 17 (1 by maintainers)
I fix this problem by adding
tf.config.experimental_run_functions_eagerly(True)
after import tensorflow.the following links may help:
https://stackoverflow.com/questions/58352326/running-the-tensorflow-2-0-code-gives-valueerror-tf-function-decorated-functio.
https://www.tensorflow.org/guide/effective_tf2#use_tfconfigexperimental_run_functions_eagerly_when_debugging.
Issue still exists in latest 2.3.1.
Running function eagerly is not a solution.
This is equivalent to remove the
tf.function
decorator, this is unwanted, cf. hgffly’s comment:@tf.function # it will work correctly if this line is disabled but the training becomes very slow
This is great, it worked! Thanks.
I have tried the latest version TF2.1.0rc today, but it still raises errors. Maybe we need to wait longer… XD
If you don’t want to run functions eagerly, add a wrapper, or remove the tf.function decorator, you may find the following a better suggestion:
The optimizer creates variables when
apply_gradients
is called for the first time on it.tf.keras.optimizers.SGD
which is a “stateless” optimizer still creates variables (you can check by callingoptimizer2.variables()
before and after training, and you will see that there is aiter
tf.Variable). Thus, you should create two tf.functions, one for each optimizer, if you would like to train your model with both optimizers.I hope this is helpful!
Thank you. It’s works well!
eagerly = True equals do not use @tf.function
Tested v2.1 and fixes the issue