文章目录
掌握神经网络正向传播与反向传播,tf.GradientTape求导机制以及自定义模型训练操作
1.神经网络的正向传播与反向传播
需要具体了解

2.自动求导机制
梯度求解利器:tf.GradientTape
GradientTape是eager模式下计算梯度用的
GradientTape是eager模式下计算梯度用的
watch(tensor)
作用:确保某个tensor被tape追踪
参数:tensor: 一个Tensor或者一个Tensor列表
gradient(target, sources)
作用:根据tape上面的上下文来计算某个或者某些tensor的梯度参数
target: 被微分的Tensor或者Tensor列表,你可以理解为经过某个函数之后的值
sources: Tensors 或者Variables列表(当然可以只有一个值). 你可以理解为函数的某个变量
返回:
一个列表表示各个变量的梯度值,和source中的变量列表一一对应,表明这个变量的梯度。
上面的例子中的梯度计算部分可以更直观的理解这个函数的用法。

举例:计算y= x2在x=3时的导数**
import tensorflow as tf
x = tf.constant(3.0)
with tf.GradientTape() as g:
# watch作用:确保每个tensor被tape追踪
g.watch(x)
y = x*x
# 求导
# gradient作用是:根据tape来计算某个或某些tensor的梯度,即y导 = 2*x = 2*3 =6
dy_dx = g.gradient(y,x)
print(dy_dx)
# tf.Tensor(6.0, shape=(), dtype=float32)
loss_object = tf.keras.losses.CategoricalCrossentropy()
optimizer = tf.keras.optimizers.Adam()
with tf.GradientTape() as tape:
predictions = model(data) # 正向传播
loss = loss_object(labels,predictions)
gradients = tape.gradient(loss,model.trainable_variables)
optimizer.apply_gradients(zip(gradients,model.trainable_variables))
# 一般在网络中使用时,不需要显示调用watch函数,使用默认设置,GradientTape会监控可训练变量
# apply_gradients(grads_and_vars,name=None)
# 作用:把计算出来的梯度更新到变量上面
# 参数含义:
# grads_and_vars:(gradient,variable)对的列表
# name:操作名
3.案例1:模型自动求导



4.案例2:使用GradientTape自定义训练模型


运行结果:
5.案例3:使用GradientTape自定义训练模型(加入评估函数)
让我们将metric添加到组合中。下面可以在从头开始编写的训练循环中随时使用内置指标
(或编写的自定义指标)。流程如下:
- 在循环开始时初始化metrics
- metric.update_state():每batch之后更新
- metric.result():需要显示metrics的当前值时调用
- metric.reset_states():需要清除metrics状态时重置(通常在每个epoch的结尾)


进行几个epoch运行训练循环
model = MyModel(num_classes=10)
epochs = 3
for epoch in range(epochs):
print('Start of epoch %d'%(epoch,))
# 遍历数据集的batch_size
for step,(x_batch_train,y_batch_train) in enumerate(train_dataset):
# 一个batch
with tf.GradientTape() as tape:
logits = model(x_batch_train)
loss_value = loss_fn(y_batch_train,logits)
grads = tape.gradient(loss_value,model.trainable_weights)
optimizer.apply_gradients(zip(grads,model.trainable_weights))
# 更新训练集的metrics
train_acc_metric(y_batch_train,logits)
# 每200 batches打印一次loss值
if step % 200 == 0:
print('Training loss (for onr batch) at step %s:%s'%(step,float(loss_value)))
print('Seen so far :%s sample'%((step+1) * 64))
# 在每一个epoch结束时显示metrics
train_acc = train_acc_metric.result()
print('Training acc over epoch: %s'%(float(train_acc),))
# 在每个epoch结束时重置训练指标
train_acc_metric.reset_states()
# 在每个epoch结束时运行一个验证集
for x_batch_val,y_batch_val in val_dataset:
val_logits = model(x_batch_val)
# 更新验证集metrics
val_acc_metric(y_batch_val,val_logits)
val_acc = val_acc_metric.result()
print('Validation acc : %s'%(float(val_acc),))
# 重置
val_acc_metric.reset_states()
# 在每个epoch结束时运行一个测试集
for x_batch_test,y_batch_test in test_dataset:
test_logits = model(x_batch_test)
# 更新测试集metrics
test_acc_metric(y_batch_test,test_logits)
test_acc = test_acc_metric.result()
print('Test acc : %s'%(float(test_acc)))
# 重置
test_acc_metric.reset_states()

