Eager Execution

2019/08/15 00:31
阅读数 34

  Tensorflow的Eager Execution是一种命令编程环境,操作会返回具体的值。

  要启动Eager Execution,请将tf.enable_eager_execution()添加到程序或控制台回话的开头。

  启用Eager Execution会改变TensorFlow操作的行为方式,现在他们会立即评估并将值返回给Python。tf.Tensor对象会引用具体值,而不是指向计算图中的节点的符号句柄。由于不需要构建稍后在会话中运行的计算图,因此使用print()或调试程序很容易检查结果。评估、输出和检查张量值不会中断计算梯度的流程。

  tf.Tensor与numpy ndarray可以互相转换。

动态控制流:

  在执行模型时,主机语言的所有功能都可用。

构建模型

  将TensorFlow与Eager与Eager Execution结合使用时,可以编写自己的层或使用在tf.keras.layers程序包中提供的层。

  虽然可以使用任何Python对象表示层,但TensorFlow提供了便利的基类tf.karas.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):
        #权重形状
        self.kernel=self.add_variable("kernel",[input_shape[-1],self.output_units])
    def call(self,input):
        #输出
        return tf.matmul(input,self.kernel)

  最好使用tf.keras.layers.Dense层(而不是上面的MysimpleLayer),它具有其功能的超集(它可以添加偏差)。

  将层组合成模型时,可以使用tf.keras.Sequential表示层线性堆叠的模型。他非常适合基本模型:

model=tf.keras.Sequential([tf.keras.layer.Dense(10,input_shape=(784,)),
tf.keras.layers.Dense(10)])#必须指明第一层的形状

  或者,通过继承tf.keras.Model将模型整理为类。这是一个本身也是层的层容器,允许tf.keras.Model对象包含其他tf.keras.Model对象。

class MniSTModel(tf.keras.Model):
    def __init__(self):
        super(MniSTModel,self).__init__()
        self.dese1=tf.keras.layers.Dense(units=10)
        self.dense2=tf.keras.layers.Dense(units=10)
    def call(self,input):
        result=self.dense1(input)
        result=self.dense2(result)
        result=self.dense2(result)#复用dense2权重
        return result

model=MniSTModel()

计算梯度

  自动微分对于实现机器学习算法(例如神经网络的反向传播)来说很有用。在Eager Execution期间,使用tf.GradientTape跟踪操作以便稍后计算梯度。

  tf.GradientTape是一种选择性功能,可在不跟踪时提供最佳性能。由于在每次调用期间都可能发生不同的操作,因此所有的前向传播都会记录到“磁带"中。要计算梯度,反向播放磁带,然后放弃。特定的tf.gradientTape只能计算一个梯度;随后的调用会抛出运行时错误。

w=tf.Variable([[1.0]])
with tf.GradientTape() as tape:
    loss=w*w

grad=tape.gradient(loss,w)
print(grad)#=>tf.Tensor([[2.]],shape=(1,1),dtype=float32)

训练模型

  以下实例将创建一个多层模型,该模型会对标准MNIST手写数组进行分类。它演示了在Eager Execution环境中构建可训练图的优化器和层API。

#下载mnist数据集
(mnist_images,mnist_labels),_=tf.keras.datasets.mnist.load_data()

dataset=tf.data.Dataset.from_tensor_silices((tf.cast(mnist_images[...,tf.newaxis]/255,tf.float32),tf.cast(mnist_labels,tf.int64)))
dataset=dataset.shuffle(1000).batch(32)

#构建模型
mnist_model=tf.keras.Sequential([tf.keras.layers.Conv2D(16,[3,3],activation='relu'),
    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())

   虽然keras模型具有内置训练循环(使用fit方法),但有时需要更多自定义设置。 下面是一个用eager实现的训练循环示例:

optimizer=tf.train.AdamOptimizer()
loss_history=[]

for (batch,(images,labels)) in enumerate(dataset.take(400)):
    if batch %80==0:
        print()
    print('.',end=' ')
    with tf.GradientTape() as tape:
        logits=mnist_model(images,training=True)
        loss_value=tf.losses.sparse_sorftmax_cross_entropy(labels,logits)
loss_history.append(loss_value.numpy())
grads=tape.gradient(loss_value,mnist_model.variables)
optimizer.apply_gradients(zip(grads,mnist_model.variables),global_step=tf.train.get_or_create_global_step())

import matplotlib.pyplot as plt
plt.plot(loss_history)
plt.xlabel('Batch #')
plt.ylabel('loss [entropy]')
Text(0,0.5,'loss [entropy]')

变量和优化器

  tf.Variable对象会储存在训练期间访问的可变tf.Tensor值,以更加轻松地实现自动微分。模型的参数可作为变量封装在类中。

  通过将tf.Variable与tf.GradientTape结合使用可以更好的封装模型参数。例如,上面的自动微分示例可以重写为:

class Model(tf.keras.Model):
    def __init__(self):
        super(Model,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

#创建小型数据集
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])

#1.建立model实例  2.计算损失函数对W、B的微分  3.更新参数
model=Model()
optimizer=tf.train.GradientDescentOptimizer(learning_rate=0.01)

print('Initial loss:{:.3f}'.format(loss(model,training_inputs,training_outputs)))

#训练xunhuan
for i in range(300):
    grads=grad(model,training_inputs,training_outputs)
    optimizer.apply_gradients(zip(grads,[model.W,model.B]),global_step=tf.train.get_or_create_global_step())
    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()))

 

  

 

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部