TensorFlow 版本:1.12.0 > Guide > Eager Execution
Eager Execution 介绍
TensorFlow 的 Eager Execution 是一种命令式编程环境,可立即评估操作,无需构建图:操作会返回具体的值,而不是构建以后再运行的计算图。Eager 模式使得 TensorFlow 的使用和调试变得简单。为了真实地感受 Eager 模式的魅力,推荐大家在交互式 python 解释器中运行本文的代码。
Eager Execution 是一个灵活的机器学习平台,用于研究和实验,可提供:
- 更好的交互 ---------- 可以更自然地组织你的代码,可以直接使用 Python 数据结构。
- 更容易的调试 ---------- 可以直接调用 op 去检查模型的运行过程,测试更改后的模型。 使用标准的 Python 调试工具来检测模型的错误。
- 自然的控制流 ---------- 可以使用 Python 控制流,从而简化动态模型的搭建。
Eager 模式支持绝大多数 TensorFlow op 和 GPU 加速。Eager 模式的使用示例,详见tensorflow/contrib/eager/python/examples。
注意:如果启用 Eager Execution,某些模型的开销可能会增加,我们正在改进性能。
文章目录
1. Eager 模式的开启、基本用法 ¶
要开启 Eager 模式,只需要在 “程序” 或 “控制台会话” 的开始添加 tf.enable_eager_execution()
。不要 将开启 Eager 模式的语句放在程序的其它地方。
import tensorflow as tf
tf.enable_eager_execution()
现在您可以运行 TensorFlow 操作了,结果将立即返回:
tf.executing_eagerly() # => True
x = [[2.]]
m = tf.matmul(x, x)
print("hello, {}".format(m)) # => "hello, [[4.]]"
启用 Eager Execution 会改变 TensorFlow 操作的行为方式 — 现在它们会立即评估并将值返回给 Python。tf.Tensor
对象会引用具体值,而不是指向计算图中的节点的符号句柄。由于 Eager 模式不需要构建稍后在会话中运行的计算图,因此使用 print() 或调试程序很容易检查结果。评估、输出和检查张量值不会中断计算梯度的流程。
Eager Execution 适合与 NumPy 一起使用。NumPy op 可以以 tf.Tensor
为参数。TensorFlow math operations 将 Python 对象和 NumPy 数组转换为 tf.Tensor
对象。tf.Tensor.numpy
方法返回对象的值作为 NumPy ndarray
。
a = tf.constant([[1, 2],
[3, 4]])
print(a)
# => tf.Tensor([[1 2]
# [3 4]], shape=(2, 2), dtype=int32)
# Broadcasting support
b = tf.add(a, 1)
print(b)
# => tf.Tensor([[2 3]
# [4 5]], shape=(2, 2), dtype=int32)
# Operator overloading is supported
print(a * b)
# => tf.Tensor([[ 2 6]
# [12 20]], shape=(2, 2), dtype=int32)
# Use NumPy values
import numpy as np
c = np.multiply(a, b)
print(c)
# => [[ 2 6]
# [12 20]]
# Obtain numpy value from a tensor:
print(a.numpy())
# => [[1 2]
# [3 4]]
tf.contrib.eager
模块的 op 可以同时适用于 eager 和 graph 环境。这在编写兼容 graph 模式的的代码时非常有用。
tfe = tf.contrib.eager
2. Eager 模式下 model 的建立 ¶
很多机器学习模型通常由很多层组合而成。开启 eager 模式后,你可以自定义层 或 使用 tf.keras.layers
里的层。
在使用 Python 对象来表示一个层时,需要从 tf.keras.layers.Layer
继承来编写自定义层:
class MySimpleLayer(tf.keras.layers.Layer):
def __init__(self, output_units):
super(MySimpleLayer, self).__init__()
self.output_units = output_units
def build(self, input_shape):
# The build method gets called the first time your layer is used.
# Creating variables on build() allows you to make their shape depend
# on the input shape and hence removes the need for the user to specify
# full shapes. It is possible to create variables during __init__() if
# you already know their full shapes.
self.kernel = self.add_variable(
"kernel", [input_shape[-1], self.output_units])
def call(self, input):
# Override call() instead of __call__ so we can perform some bookkeeping.
return tf.matmul(input, self.kernel)
使用 tf.keras.layers.Dense
来取代 MySimpleLayer
非常有必要(因为 Dense 的功能包含了 MySimpleLayer 的功能)。
将层组合成模型时,你可以使用 tf.keras.Sequential
来表示模型,其可以线性地多个层堆叠起来。Sequential 在搭建简单模型时非常有用。
model = tf.keras.Sequential([
tf.keras.layers.Dense(10, input_shape=(784,)), # must declare input shape
tf.keras.layers.Dense(10)
])
除了使用 Sequential 来构建模型,也可以从 tf.keras.Model
继承来编写一个模型类表示模型。构建的模型包含了很多层,允许 tf.keras.Model
包含其它 tf.keras.Model
对象。
class MNISTModel(tf.keras.Model):
def __init__(self):
super(MNISTModel, self).__init__()
self.dense1 = tf.keras.layers.Dense(units=10)
self.dense2 = tf.keras.layers.Dense(units=10)
def call(self, input):
"""Run the model."""
result = self.dense1(input)
result = self.dense2(result)
result = self.dense2(result) # reuse variables from dense2 layer
return result
model = MNISTModel()
在 tf.keras.Model
类中不需要设置输入的 shape。
tf.keras.layers
类 创建、包含了该层的模型参数,这些参数 与 实例化出的对象 共存亡。当需要共享层的参数时,共享 实例化出的对象 即可。
3. Eager 模式下 model 的训练 ¶
3.1 计算梯度 ¶
自动微分对于机器学习算法的训练至关重要。在 Eager 模式,为了计算梯度,需要使用 tf.GradientTape
来追踪 op。
tf.GradientTape
是一个