TensorFlow 的 Eager Execution 是一种命令式编程环境,可立即评估操作,无需构建图:操作会返回具体的值,而不是构建以后再运行的计算图。这样可以轻松地使用 TensorFlow 和调试模型,并且还减少了样板代码。
Eager Execution 是一个灵活的机器学习平台,用于研究和实验,可提供:
直观的界面 - 自然地组织代码结构并使用 Python 数据结构。快速迭代小模型和小型数据集。
更轻松的调试功能 - 直接调用操作以检查正在运行的模型并测试更改。使用标准 Python 调试工具进行即时错误报告。
自然控制流程 - 使用 Python 控制流程而不是图控制流程,简化了动态模型的规范。
from __future__ import absolute_import, division, print_function
import tensorflow as tf
print(tf.__version__)
# 在tensorflow2中默认使用Eager Execution
tf.executing_eagerly()
1.Eager Execution下运算
在Eager Execution下可以直接进行运算,结果会立即返回
x = [[3.]]
m = tf.matmul(x, x)
print(m)
启用Eager Execution会改变TensorFlow操作的行为 - 现在他们会立即评估并将其值返回给Python。tf.Tensor对象引用具体值,而不再是指向计算图中节点的符号句柄。由于在会话中没有构建和运行的计算图,因此使用print()或调试程序很容易检查结果。评估,打印和检查张量值不会破坏计算梯度的流程。
Eager Execution可以与NumPy很好地协作。NumPy操作接受tf.Tensor参数。TensorFlow 数学运算将Python对象和NumPy数组转换为tf.Tensor对象。tf.Tensor.numpy方法将对象的值作为NumPy的ndarray类型返回。
# tf.Tensor对象引用具体值
a = tf.constant([[1,9],[3,6]])
print(a)
# 支持broadcasting(广播:不同shape的数据进行数学运算)
b = tf.add(a, 2)
print(b)
# 支持运算符重载
print(a*b)
# 可以当做numpy数据使用
import numpy as np
s = np.multiply(a,b)
print(s)
# 转换为numpy类型
print(a.numpy())
2.动态控制流
Eager Execution的一个主要好处是在执行模型时可以使用宿主语言(Python)的所有功能。所以,例如,写fizzbuzz很容易:
def fizzbuzz(max_num):
counter = tf.constant(0)
max_num = tf.convert_to_tensor(max_num)
# 使用range遍历
for num in range(1, max_num.numpy()+1):
# 重新转为tensor类型
num = tf.constant(num)
# 使用if-elif 做判断
if int(num % 3) == 0 and int(num % 5) == 0:
print('FizzBuzz')
elif int(num % 3) == 0:
print('Fizz')
elif int(num % 5) == 0:
print('Buzz')
else:
print(num.numpy())
counter += 1 # 自加运算
fizzbuzz(16)
3.在Eager Execution下训练
计算梯度
自动微分对于实现机器学习算法(例如用于训练神经网络的反向传播)来说是很有用的。在 Eager Execution中,使用 tf.GradientTape 来跟踪操作以便稍后计算梯度。
可以用tf.GradientTape来训练和/或计算梯度。它对复杂的训练循环特别有用。
由于在每次调用期间可能发生不同的操作,所有前向传递操作都被记录到“磁带”中。要计算梯度,请向反向播放磁带,然后丢弃。特定的tf.GradientTape只能计算一个梯度; 后续调用会引发运行时错误。
w = tf.Variable([[1.0]])
# 用tf.GradientTape()记录梯度
with tf.GradientTape() as tape:
loss = w*w
grad = tape.gradient(loss, w) # 计算梯度
print(grad)
##训练模型
# 导入mnist数据
(mnist_images, mnist_labels), _ = tf.keras.datasets.mnist.load_data()
# 数据转换
dataset = tf.data.Dataset.from_tensor_slices(
(tf.cast(mnist_images[...,tf.newaxis]/255, tf.float32),
tf.cast(mnist_labels,tf.int64)))
# 数据打乱与分批次
dataset = dataset.shuffle(1000).batch(32)
# 使用Sequential构建一个卷积网络
mnist_model = tf.keras.Sequential([
tf.keras.layers.Conv2D(16,[3,3], activation='relu',
input_shape=(None, None, 1)),
tf.keras.layers.Conv2D(16,[3,3], activation='relu'),
tf.keras.layers.GlobalAveragePooling2D(),
tf.keras.layers.Dense(10)
])
# 展示数据
# 即使没有经过培训,也可以调用模型并在Eager Execution中检查输出
for images,labels in dataset.take(1):
print("Logits: ", mnist_model(images[0:1]).numpy())
# 优化器与损失函数
optimizer = tf.keras.optimizers.Adam()
loss_object = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)
# 按批次训练
# 虽然 keras 模型具有内置训练循环(fit 方法),但有时需要更多自定义设置。下面是一个用 eager 实现的训练循环示例:
loss_history = []
for (batch, (images, labels)) in enumerate(dataset.take(400)):
if batch % 10 == 0:
print('.', end='')
with tf.GradientTape() as tape: #开启一个监视器 监视某个向量
# 获取预测结果
logits = mnist_model(images, training=True)
# 获取损失
loss_value = loss_object(labels, logits)
loss_history.append(loss_value.numpy().mean())
# 获取本批数据梯度 (求导或者偏导)
grads = tape.gradient(loss_value, mnist_model.trainable_variables)
# 反向传播优化 更新权重变量
optimizer.apply_gradients(zip(grads, mnist_model.trainable_variables))
# 绘图展示loss变化
import matplotlib.pyplot as plt
plt.plot(loss_history)
plt.xlabel('Batch #')
plt.ylabel('Loss [entropy]')
4.变量求导优化¶
tf.Variable对象存储在训练期间访问的可变tf.Tensor值,以使自动微分更容易。模型的参数可以作为变量封装在类中。
将tf.Variable 和tf.GradientTape 结合,可以更好地封装模型参数。例如,可以重写上面的自动微分示例为:
class MyModel(tf.keras.Model):
def __init__(self):
super(MyModel, self).__init__()
self.W = tf.Variable(5., name='weight')
self.B = tf.Variable(10., name='bias')
def call(self, inputs):
return inputs * self.W + self.B
# 满足函数3 * x + 2的数据
NUM_EXAMPLES = 2000
training_inputs = tf.random.normal([NUM_EXAMPLES])
noise = tf.random.normal([NUM_EXAMPLES])
training_outputs = training_inputs * 3 + 2 + noise
# 损失函数
def loss(model, inputs, targets):
error = model(inputs) - targets
return tf.reduce_mean(tf.square(error))
# 梯度函数
def grad(model, inputs, targets):
with tf.GradientTape() as tape:
loss_value = loss(model, inputs, targets)
return tape.gradient(loss_value, [model.W, model.B])
# 模型与优化器
model = MyModel()
optimizer = tf.keras.optimizers.SGD(learning_rate=0.01)
print("Initial loss: {:.3f}".format(loss(model, training_inputs, training_outputs)))
# 训练循环, 反向传播优化
for i in range(300):
grads = grad(model, training_inputs, training_outputs)
optimizer.apply_gradients(zip(grads, [model.W, model.B]))
if i % 20 == 0:
print("Loss at step {:03d}: {:.3f}".format(i, loss(model, training_inputs, training_outputs)))
print("Final loss: {:.3f}".format(loss(model, training_inputs, training_outputs)))
print("W = {}, B = {}".format(model.W.numpy(), model.B.numpy()))
后面的代码没看太懂 git地址 https://github.com/czy36mengfei/tensorflow2_tutorials_chinese
请自己下载