3.4 自定义层
机器学习模型通常可以表示为简单网络层的堆叠与组合,TensorFlow提供了常见的网络层,TensorFlow 2.0推荐使用tf.keras来构建网络层,以提高可读性和易用性。
3.4.1 网络层的常见操作
TensorFlow 2.0推荐将tf.keras作为构建神经网络的高级API。本节对常见的网络层操作进行介绍。
(1)构建一个简单的全连接网络,代码如下。
(2)代码的运行结果如下,包含权重和偏置信息。
(3)tf.keras非常灵活,还可以分别取出上例中的权重和偏置,代码如下。
(4)代码的运行结果如下。
3.4.2 自定义网络层
在实际中,经常需要扩展tf.keras.Layer类并自定义网络层。本节介绍如何自定义网络层。
(1)在自定义网络层的过程中主要使用3个函数,示例代码如下。
说明:调用build()函数构建网络并不是必要的,有时可以在__init__()中构建网络。但是,调用build()函数构建网络的优点是可以动态获取输入数据的shape,大大提高了运行效率。
(2)上述代码的运行结果如下。
3.4.3 网络层组合
有很多机器学习模型是不同网络层的组合,网络层组合学习是加快学习速度和精度的重要方法。
(1)使用下面的代码在TensorFlow 2.0中构建一个包含多个网络层的模型。
说明:该例子是resnet的一个残差块,是“卷积+批标准化+残差连接”的组合。
(2)代码的运行结果如下。
(3)有时需要构建线性模型,可以直接用tf.keras.Sequential来构建,示例代码如下。
(4)代码的运行结果如下。
3.4.4 自动求导
TensorFlow使用的求导方法被称为自动微分,它既不是符号求导也不是数值求导,而是两者的结合。
(1)TensorFlow 2.0利用tf.GradientTape API来实现自动求导功能,在tf.GradientTape()上下文中执行的操作都会被记录在“tape”中,然后TensorFlow 2.0使用反向自动微分来计算相关操作的梯度,示例代码如下。
(2)代码的运行结果如下。
(3)输出中间变量的导数,代码如下。
(4)代码的运行结果如下。
(5)在默认情况下,GradientTape的资源会在执行tf.GradientTape()后释放。如果希望多次计算梯度,需要创建一个持久的GradientTape。代码如下。
(6)代码的运行结果如下。
(7)因为tape记录了整个操作,所以即使存在Python控制流(如if和while),也能正常处理梯度求导,示例代码如下。
(8)代码的运行结果如下。
(9)GradientTape上下文管理器在计算梯度时会保持梯度。因此,GradientTape也可以实现高阶梯度计算,示例代码如下。
(10)代码的运行结果如下。
本章介绍了一些TensorFlow 2.0的基本概念并举例进行了说明,后面在使用到这些概念时,会举例对具体的使用方法进行介绍。