-
Notifications
You must be signed in to change notification settings - Fork 537
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
No more globals. No more tf.Variable
#8
Comments
Hi @odysseus0 , Thanks for your feedback. What they meant by "no more globals" is not that you can't use global variables in your own code (even though, I agree that it's generally bad practice, more on this below). They were talking about the fact that TensorFlow itself will stop using global scopes everywhere. For example,
For the simplicity of the code examples in the notebook, I use global variables rather than wrapping everything in functions or classes, but of course in a real project, it would be much cleaner to create classes to hold these variables, typically by creating a custom Keras layer. You would build the variables in the I hope this helps. If you are still troubled by some of the code examples, please don't hesitate to tell me which ones, this notebook is quite new so it may still contain some errors or unclear code. Hope this helps! |
Thank you so much for your detailed explanation! That makes things so much clearer for someone who just get started with TensorFlow, not even with experience with the TF 1.X version. So to make sure that I understand the point here, the global that gets removed is the global scope of Sorry for making uneducated opinion and thank you again for kind correction. |
You're most welcome, @odysseus0. :) Yes, you are exactly right, the global that gets removed is the global scope of >>> tf.__version__
'1.12.0'
>>> v1 = tf.constant(1., name="v")
>>> v2 = tf.constant(2., name="v")
>>> v3 = tf.constant(3., name="v")
>>> del v1
>>> del v2
>>> del v3
>>> tf.get_default_graph().get_operations()
[<tf.Operation 'v' type=Const>, <tf.Operation 'v_1' type=Const>, <tf.Operation 'v_2' type=Const>]
>>> tf.get_default_graph().get_operation_by_name('v_2')
<tf.Operation 'v_2' type=Const> The fact that operations are automatically added to a global scope was confusing. Plus, this renaming business was pretty bad, especially if you had several libraries adding operations and potentially using conflicting names. And the fact that operations outlive their Python scope (the ops survive even after I deleted >>> tf.reset_default_graph() In contrast, look at how much nicer things are in TensorFlow 2: >>> v1 = tf.constant(1.)
>>> v2 = tf.constant(2.)
>>> v3 = tf.constant(3.)
>>> del v1
>>> v1
Traceback[...]NameError: name 'v1' is not defined
>>> tf.get_default_graph()
Traceback[...]AttributeError: module 'tensorflow' has no attribute 'get_default_graph'
>>> tf.reset_default_graph()
Traceback[...]AttributeError: module 'tensorflow' has no attribute 'reset_default_graph' Basically, the code is just regular Python, with regular logic and scopes. When a Python object is not referenced anymore, it is garbage collected, end of story. There's no default graph, and we don't need to worry about name clashes. Life is so beautiful, sometimes! :) By default, every operation just runs immediately and the outputs are returned straight away. This is called eager execution (or eager mode) and it is the default in TensorFlow 2. But you can also convert your Python code to computation graphs automatically using >>> @tf.function # convert the Python function to a TensorFlow function based on a graph
... def add_5(some_arg):
... return some_arg + 5.
...
>>> add_5(tf.constant(10.)) # we get the result right away
<tf.Tensor: id=20, shape=(), dtype=float32, numpy=15.0>
>>> concrete_function = add_5.get_concrete_function(tf.TensorSpec(shape=[], dtype=tf.float32))
>>> concrete_function
<tensorflow.python.eager.function.ConcreteFunction at 0x12efa40b8>
>>> concrete_function.graph
<tensorflow.python.framework.func_graph.FuncGraph at 0x12f048f98>
>>> concrete_function.graph.get_operations()
[<tf.Operation 'some_arg' type=Placeholder>,
<tf.Operation 'add/y' type=Const>,
<tf.Operation 'add' type=Add>,
<tf.Operation 'Identity' type=Identity>] To generate the graph, TensorFlow traced the Python function, meaning it ran it in graph mode. In this mode, operations don't actually execute any computation, they just get added to a graph. Moreover, Wow, I'm going way too far! I hope I didn't confuse you with all these details. |
That was a great explanation. |
@ageron This is certainly the best explanation I have read about this key difference between TF 1 and TF 2 so far on the internet. You are truly an amazing explainer! I am sure that your new book on TF 2 will be a huge success. Really want to read it myself already. |
The notebook on low level TF API needs major revision as TF 2.0 will at the very least discourages the use of globals through
tf.Variable
and very likely have already entirely ditched it in RFC: Variables in TensorFlow 2.0.Note that the official style guide, Effective TensorFlow 2.0, also explicitly stated: "No more globals!"
The text was updated successfully, but these errors were encountered: