TL;DR 在即将发布(本文章写于 2018-01-06)的 TenserFlow v1.5 中,TensorFlow将会引入一个重要的 User-friendly 特性:Eager Execution. 本文章将展示 Eager Execution 引入的一些新的特性。
安装 TensorFlow 对应的版本
因为 TensorFlow 正式版(写作时间 2018-01-06,此时的正式版本为1.4.1)中还不包含此功能,因此我们需要安装 TensorFlow nightly build 版本。
pip install tf-nightly # or tf-nightly-gpu if you have GPU
特性探索
Eager execution
在开启这个模式后,TensorFlow 将会立即执行操作,返回结果给 Python,而不需要使用 Session.run()
, 例如:
import tensorflow as tf
import tensorflow.contrib.eager as tfe
tfe.enable_eager_execution()
x = [[2]]
m = tf.matmul(x, x)
print(m)
点击这里 launch binder ,在线运行这个例子
你会得到如下显示:
tf.Tensor([[4]], shape=(1, 1), dtype=int32)
Dynamic models
在不具备动态模型的能力前,TensorFlow 中的每一个 operator 都需要明确定声明和定义。在具备的了动态模型能力之后,TensorFlow 具备了从操作中推导操作数类型的能力,让复杂的动态模型容易实现,例如:
import tensorflow as tf
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)
点击这里 launch binder ,在线运行这个例子
如果没有启用 Eager Execution 会显示如下错误:
Using a
tf.Tensor
as a Pythonbool
is not allowed.
原因是在 while not tf.equal(a, 1)
处,如果没有启动 Eager Execution 那么返回的结果是 tf.Tensor
对象,因为还不知道具体的值所以不能转换成bool类型。
Gradients
得益于 Eager Execution 立即执行的特性,Gradients 也可以立即得到,而不用等到运行时才能知道,例子如下:
import tensorflow as tf
import tensorflow.contrib.eager as tfe
tfe.enable_eager_execution()
def square(x):
return tf.multiply(x, x)
grad = tfe.gradients_function(square)
print(square(3.)) # 输出 [9.]
print(grad(3.)) # 输出 [6.]
点击这里 launch binder ,在线运行这个例子
输入的具体情况如下:
tf.Tensor(9.0, shape=(), dtype=float32)
[<tf.Tensor: id=11, shape=(), dtype=float32, numpy=6.0>]
Building models
官方推荐应该使用 Python 的 class 来组织模型结构而不是 function。Eager Execution 带有的 tfe.Network
就是设计用来作为模型的父类的,继承这个类之后就支持网络的套嵌,下面这段代码是官方推荐的简易 MNIST 模型的参考:
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
即使没有训练,我们也能够立即调用它并观察输出:
# Let's make up a blank input image
model = MNISTModel()
batch = tf.zeros([1, 1, 784])
print(batch.shape)
# (1, 1, 784)
result = model(batch)
print(result)
# tf.Tensor([[[ 0. 0., ...., 0.]]], shape=(1, 1, 10), dtype=float32)
这里并不需要使用 placeholders 或者 sessions。当我们第一输入时,模型的参数会被设定好。
为了训练任何模型,我们都需要 loss function,calculate gradients 和 optimizer 去优化参数。 loss function
def loss_function(model, x, y):
y_ = model(x)
return tf.nn.softmax_cross_entropy_with_logits(labels=y, logits=y_)
calculate gradients & optimizer
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)
点击这里 launch binder ,在线运行这个例子
其他特性
还有其他特性,如:
- get the second derivative
- derivative under control flow
- Custom Gradients
这里就不再介绍,感兴趣的可以参考官方文档或者本文的参考文档。