Wraps a python function into a TensorFlow op that executes it eagerly. This function allows expressing computations in a TensorFlow graph as Python functions. In particular, it wraps a Python function `func` in a once-differentiable TensorFlow operation that executes it with eager execution
(func, inp, Tout, name=None)
| 344 | |
| 345 | @tf_export("py_function") |
| 346 | def eager_py_func(func, inp, Tout, name=None): |
| 347 | """Wraps a python function into a TensorFlow op that executes it eagerly. |
| 348 | |
| 349 | This function allows expressing computations in a TensorFlow graph as |
| 350 | Python functions. In particular, it wraps a Python function `func` |
| 351 | in a once-differentiable TensorFlow operation that executes it with eager |
| 352 | execution enabled. As a consequence, `tf.py_function` makes it |
| 353 | possible to express control flow using Python constructs (`if`, `while`, |
| 354 | `for`, etc.), instead of TensorFlow control flow constructs (`tf.cond`, |
| 355 | `tf.while_loop`). For example, you might use `tf.py_function` to |
| 356 | implement the log huber function: |
| 357 | |
| 358 | ```python |
| 359 | def log_huber(x, m): |
| 360 | if tf.abs(x) <= m: |
| 361 | return x**2 |
| 362 | else: |
| 363 | return m**2 * (1 - 2 * tf.math.log(m) + tf.math.log(x**2)) |
| 364 | |
| 365 | x = tf.compat.v1.placeholder(tf.float32) |
| 366 | m = tf.compat.v1.placeholder(tf.float32) |
| 367 | |
| 368 | y = tf.py_function(func=log_huber, inp=[x, m], Tout=tf.float32) |
| 369 | dy_dx = tf.gradients(y, x)[0] |
| 370 | |
| 371 | with tf.compat.v1.Session() as sess: |
| 372 | # The session executes `log_huber` eagerly. Given the feed values below, |
| 373 | # it will take the first branch, so `y` evaluates to 1.0 and |
| 374 | # `dy_dx` evaluates to 2.0. |
| 375 | y, dy_dx = sess.run([y, dy_dx], feed_dict={x: 1.0, m: 2.0}) |
| 376 | ``` |
| 377 | |
| 378 | You can also use `tf.py_function` to debug your models at runtime |
| 379 | using Python tools, i.e., you can isolate portions of your code that |
| 380 | you want to debug, wrap them in Python functions and insert `pdb` tracepoints |
| 381 | or print statements as desired, and wrap those functions in |
| 382 | `tf.py_function`. |
| 383 | |
| 384 | For more information on eager execution, see the |
| 385 | [Eager guide](https://tensorflow.org/guide/eager). |
| 386 | |
| 387 | `tf.py_function` is similar in spirit to `tf.compat.v1.py_func`, but unlike |
| 388 | the latter, the former lets you use TensorFlow operations in the wrapped |
| 389 | Python function. In particular, while `tf.compat.v1.py_func` only runs on CPUs |
| 390 | and |
| 391 | wraps functions that take NumPy arrays as inputs and return NumPy arrays as |
| 392 | outputs, `tf.py_function` can be placed on GPUs and wraps functions |
| 393 | that take Tensors as inputs, execute TensorFlow operations in their bodies, |
| 394 | and return Tensors as outputs. |
| 395 | |
| 396 | Like `tf.compat.v1.py_func`, `tf.py_function` has the following limitations |
| 397 | with respect to serialization and distribution: |
| 398 | |
| 399 | * The body of the function (i.e. `func`) will not be serialized in a |
| 400 | `GraphDef`. Therefore, you should not use this function if you need to |
| 401 | serialize your model and restore it in a different environment. |
| 402 | |
| 403 | * The operation must run in the same address space as the Python program |
nothing calls this directly
no test coverage detected