ponder-lab / Hybridize-Functions-Refactoring

Refactorings for optimizing imperative TensorFlow clients for greater efficiency.
Eclipse Public License 2.0
0 stars 0 forks source link

No numpy calls should be a precondition #363

Open khatchad opened 1 month ago

khatchad commented 1 month ago

The numpy API is not directly compatible with tf.function. The code needs to be restructured first. A first step to deal with this is to make no numpy calls a refactoring precondition. Otherwise, we can get an error after running the refactored code, e.g.:

Traceback (most recent call last):
  File "/home/rk1424/git/Python-Subjects/tensorflow-yolov4-tflite/train.py", line 165, in <module>
    app.run(main)
  File "/home/rk1424/.local/lib/python3.10/site-packages/absl/app.py", line 308, in run
    _run_main(main, args)
  File "/home/rk1424/.local/lib/python3.10/site-packages/absl/app.py", line 254, in _run_main
    sys.exit(main(argv))
  File "/home/rk1424/git/Python-Subjects/tensorflow-yolov4-tflite/train.py", line 156, in main
    train_step(image_data, target)
  File "/home/rk1424/.local/lib/python3.10/site-packages/tensorflow/python/util/traceback_utils.py", line 153, in error_handler
    raise e.with_traceback(filtered_tb) from None
  File "/tmp/__autograph_generated_filest45satl.py", line 48, in tf__train_step
    ag__.converted_call(ag__.ld(tf).print, ('=> STEP %4d/%4d   lr: %.6f   giou_loss: %4.2f   conf_loss: %4.2f   prob_loss: %4.2f   total_loss: %4.2f' % (ag__.ld(global_steps), ag__.ld(total_steps), ag__.converted_call(ag__.ld(optimizer).lr.numpy, (), None, fscope), ag__.ld(giou_loss), ag__.ld(conf_loss), ag__.ld(prob_loss), ag__.ld(total_loss)),), None, fscope)
NotImplementedError: in user code:

    File "/home/rk1424/git/Python-Subjects/tensorflow-yolov4-tflite/train.py", line 99, in train_step  *
        tf.print("=> STEP %4d/%4d   lr: %.6f   giou_loss: %4.2f   conf_loss: %4.2f   "

    NotImplementedError: numpy() is only available when eager execution is enabled.

The code for this example is at;

https://github.com/hunglc007/tensorflow-yolov4-tflite/blob/9f16748aa3f45ff240608da4bd9b1216a29127f5/train.py#L98-L110.

The enclosing function should fail refactoring preconditions.

khatchad commented 1 month ago

There's a fundamental reason why numpy calls are disallowed; it has to do with eager vs. deferred execution.

khatchad commented 1 month ago

An example of making the code amenable to hybridization can be found at:

https://github.com/ponder-lab/tensorflow-yolov4-tflite/tree/hyb_amenable

khatchad commented 1 month ago

There are also TF equivalents to numpy calls, e.g.:

diff --git a/tests/keras/test_din.py b/tests/keras/test_din.py
index fda09be..69b2b76 100644
--- a/tests/keras/test_din.py
+++ b/tests/keras/test_din.py
@@ -16,8 +16,8 @@ class TestDIN(tf.test.TestCase, parameterized.TestCase):

     def test_activation_unit_noiteract(self):

-        x = np.random.normal(size=(3, 5))
-        y = np.random.normal(size=(3, 5))
+        x = tf.random.normal(shape=(3, 5))
+        y = tf.random.normal(shape=(3, 5))

         activation_unit = din.ActivationUnit(10, kernel_init="ones")
         outputs = activation_unit(x, y)
@@ -31,8 +31,8 @@ class TestDIN(tf.test.TestCase, parameterized.TestCase):

     def test_activation_unit_iteract(self):

-        x = np.random.normal(size=(3, 5))
-        y = np.random.normal(size=(3, 5))
+        x = tf.random.normal(shape=(3, 5))
+        y = tf.random.normal(shape=(3, 5))

         interacter = tf.keras.layers.Subtract()

And, there's the tf.experimental.numpy module.

khatchad commented 1 month ago

Not only does the function definition itself should not have numpy calls, but transitively there should be no numpy calls.