TensorFlow2教程-Eager Execution

Tensorflow 2.0 的动态图模式

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
请自己下载

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值