eager execution 用户指南 (包括几个使用动态图的例子)
Eager Execution 是一个运行定义的 接口,一旦被Python调用,就立即执行
当启动Eager Execution时,运算会立刻执行,无需Session.run(),就可以返回值
-
调用
tfe.enable_eager_execution()
启动eagerimport tensorflow.contrib.eager as tfe tfe.enable_eager_execution()
-
动态模型的构建可使用Python控制流
import tensorflow.contrib.eager as tfe tfe.enable_eager_execution() a = tf.constant(12) counter = 0 while not tf.equal(a, 1): if tf.equal(a % 2, 0): a = a / 2 else: a = 3 * a + 1 print(a)
上面 tf.constant(12)张量对象的使用将把所有数学运算提升为张量运算,从而所有的返回值将是张量。
-
梯度
tfe.gradients_function( function) 参数是一个函数,对这个函数进行求导,然后将值带入
自动求导,与pytorch的 autograd 类似
def squre(x): return tf.multiply(x,x) grad = tfe.gradients_function(squre) print(squre(3.)) print(grad(3.)) # 求二阶倒数 gradgrad = tfe.gradients_function(lambda x: grad(x)[0]) print(gradgrad(3.))
自定义梯度:
def log1pexp(x): e = tf.exp(x) def grad(dy): return dy * (1 -1/(1+e)) return tf.log(1+e),grad grad_log1pexp = tfe.gradients_function(log1pexp) # Gradient at x = 0 works as before. print(grad_log1pexp(0.)) # [0.5] # And now gradient computation at x=100 works as well. print(grad_log1pexp(100.)) # [1.0]
梯度扩展:
原始的tf.gradients_function的衍生版本反映了autograd的梯度,可以在一个已有的函数内调用tf.gradients_function N次获得N阶导数,即
def factorial(): def f(x): return tf.pow(x,n) for i in range(n) f = tfe.gradients_function(f) return f(1.)
-
建立模型
创建一个简单的两层网络对标准的MNIS数字进行分类
class MNISTModel(tfe.Network): def __init__(self): super(MNISTModel, self).__init__() self.layer1 = self.track_layer(tf.layers.Dense(units=10)) self.layer2 = self.track_layer(tf.layers.Dense(units=10)) def call(self, input): """Actually runs the model.""" result = self.layer1(input) result = self.layer2(result) return result model = MNISTModel() batch = tf.zeros([1, 1, 784]) print(batch.shape) # (1, 1, 784) result = model(batch) print(result)
这里没有使用占位符或者会话,一旦数据输入,层的参数就被设定好了。
def loss_function(model, x, y): y_ = model(x) return tf.nn.softmax_cross_entropy_with_logits(labels=y, logits=y_) # 开始训练 optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.001) for (x, y) in tfe.Iterator(dataset): grads = tfe.implicit_gradients(loss_function)(model, x, y) optimizer.apply_gradients(grads)
implicit_gradients计算损失函数 关于所有变量的倒数
运用GPU训练
with tf.device("/gpu:0"): for (x, y) in tfe.Iterator(dataset): optimizer.minimize(lambda: loss_function(model, x, y))
optimizer.minimize 与 apply_gradients() 等价
Eager execution 使开发和调试互动性更强,但是 TensorFlow graph 在分布式训练、性能优化和生产部署中也有很多优势。
启动 Eager execution时,执行运算的代码还可以构建一个 描述Eager execution 未启用时的计算图。 为了将模型转化为Graph,只需要在 eager execution 未启用的 Python session 中运行同样的代码 。事例
# graph
x = tf.placeholder(tf.float.32,shape[1,1])
m = tf.matmul(x,x)
with tf.Session() as sess:
print(sess.run(m, feed_dict={x: [[2.]]}))
# Will print [[4.]]
# eager execution
x = [[2.]]
m = tf.matmul(x, x)
print(m)
目前只有少量针对Eager 的API,大多数的API与运算都需要和启动的eager一起工作。
注意
- 读取数据时,不能用排队切换,要使用tf.data 教程1 教程2
- 使用目标导向的层(比如 tf.layer.Conv2D() 或者 Keras 层 ),他们可以直接存储变量,你可以为大多数模型写代码,这对 eager execution 和图构建同样有效。也有一些例外,比如动态模型使用 Python 控制流改变基于输入的计算。一旦调用 tfe.enable_eager_execution(),它不可被关掉。为了获得图行为,需要建立一个新的 Python session。
-
一般使用tf.layer.Conv2D() 或者Kears来构建网络, 然后在main函数中开启eager ececution
tfe.enable_eager_execution
,其他都一样。