tensorflow - 在 tensorflow r1.8 中使用 tf.custom_gradient
问题描述
系统信息
- 我是否编写了自定义代码(而不是使用 TensorFlow 中提供的股票示例脚本):Y
- 操作系统平台和发行版(例如,Linux Ubuntu 16.04):Ubuntu 16.04
- TensorFlow 安装自(源或二进制):二进制
- TensorFlow 版本(使用下面的命令):r1.8
- Python版本:2.7.14
- GCC/编译器版本(如果从源代码编译):5.4
- CUDA/cuDNN 版本:8.0/7.0
- GPU型号和显存:GTX1080, 8G
- Bazel 版本:不适用
- 重现的确切命令:python test_script.py
描述问题
您好,我正在尝试使用 tf.custom_gradient 的功能进行custom_gradient操作。我根据网上的API解释做了我的测试代码。但是,custom_gradient 函数似乎存在问题。谢谢!
源代码/日志
import tensorflow as tf
import numpy as np
@tf.custom_gradient
def log1pexp(x):
e = tf.exp(x)
def grad(dy):
return dy * (1 - 1 / (1 + e))
return tf.log(1 + e), grad
x = tf.constant(100.)
f = tf.custom_gradient(log1pexp)
y, dy = f(x)
sess = tf.Session()
print (y.eval(session=sess), y.eval(session=sess).shape)
File "/home/local/home/research/DL/unit_tests/tf_test_custom_grad.py", line 14, in <module>
y, dy = f(x)
File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/ops/custom_gradient.py", line 111, in decorated
return _graph_mode_decorator(f, *args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/ops/custom_gradient.py", line 132, in _graph_mode_decorator
result, grad_fn = f(*args)
File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/framework/ops.py", line 439, in __iter__
"Tensor objects are not iterable when eager execution is not "
TypeError: Tensor objects are not iterable when eager execution is not enabled. To iterate over this tensor use tf.map_fn.
解决方案
如果你只是想测试文档中的代码,这里是方法。
以下代码将给出不稳定的[nan]
结果:
import tensorflow as tf
def log1pexp(x):
return tf.log(1 + tf.exp(x))
x = tf.constant(100.)
y = log1pexp(x)
dy = tf.gradients(y, x)
with tf.Session() as sess:
print(sess.run(dy))
以下代码将给出正确的结果[1.0]
:
import tensorflow as tf
@tf.custom_gradient
def log1pexp(x):
e = tf.exp(x)
def grad(dy):
return dy * (1 - 1 / (1 + e))
return tf.log(1 + e), grad
x = tf.constant(100.)
y = log1pexp(x)
dy = tf.gradients(y, x)
with tf.Session() as sess:
print(sess.run(dy))
细节:
这里的主要问题是你试图log1pexp
在你的代码中装饰两次:一次 with@tf.custom_gradient
和一次 with f = tf.custom_gradient(log1pexp)
。在python中,@tf.custom_gradient
这里相当于log1pexp = tf.custom_gradient(log1pexp)
. 您应该只执行一次,尤其是在这里,原因如下。
tf.custom_gradient
需要调用传递给它的函数以获得函数输出和梯度,即期望两个返回。在装修期间,一切都按预期工作,因为log1pexp
退货tf.log(1 + e)
和grad
。装饰后log1pexp
,log1pexp
(由返回tf.custom_gradient
)成为一个只返回一个张量的新函数tf.log(1 + e)
。当你做f = tf.custom_gradient(log1pexp)
装饰后log1pexp
,tf.custom_gradient
只能得到一个回报,即单张量tf.log(1 + e)
。它将尝试通过迭代这个返回的张量来把这个张量分成两个。但这是错误的,并且不允许,如错误消息所述:
当未启用急切执行时,张量对象不可迭代。
无论如何,你不应该装饰log1pexp
两次。但这就是您收到此错误的原因。还要提一件事,即使您删除了@tf.custom_gradient
. 删除后@tf.custom_gradient
,该行f = tf.custom_gradient(log1pexp)
应按预期工作。但是f
是一个只返回一个张量的函数。y, dy = f(x)
是错误的,将不起作用。