![从零开始学TensorFlow2.0](https://wfqqreader-1252317822.image.myqcloud.com/cover/188/33692188/b_33692188.jpg)
3.4 自定义层
机器学习模型通常可以表示为简单网络层的堆叠与组合,TensorFlow提供了常见的网络层,TensorFlow 2.0推荐使用tf.keras来构建网络层,以提高可读性和易用性。
3.4.1 网络层的常见操作
TensorFlow 2.0推荐将tf.keras作为构建神经网络的高级API。本节对常见的网络层操作进行介绍。
(1)构建一个简单的全连接网络,代码如下。
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_32_3.jpg?sign=1739260816-4Luu5nqIbMaij1KZ1uY8yibhdh2IUvoU-0-89840973aedba560d825acd423f6cd61)
(2)代码的运行结果如下,包含权重和偏置信息。
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_33_1.jpg?sign=1739260816-MOKBEgoWgtZ2Etpd2zG3LoxNNWkRs3S5-0-ce6b9989777aefb94963fc7c8861d96b)
(3)tf.keras非常灵活,还可以分别取出上例中的权重和偏置,代码如下。
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_33_2.jpg?sign=1739260816-nxoAVLxIDs6iKikN5l2pG0DoVM7kQhWU-0-775acf966ff57d5229db5cb1a9314ee1)
(4)代码的运行结果如下。
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_33_3.jpg?sign=1739260816-YFbVZ4x46YKijNWrpXNuYfTl5JjxA3wZ-0-daf2b390768717b218b899a34fabd6f1)
3.4.2 自定义网络层
在实际中,经常需要扩展tf.keras.Layer类并自定义网络层。本节介绍如何自定义网络层。
(1)在自定义网络层的过程中主要使用3个函数,示例代码如下。
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_34_1.jpg?sign=1739260816-lbo0rUtGtvYmtquSZVBwrhvS94ixVelc-0-3bfa58b390bd4c32848d61caafc76782)
说明:调用build()函数构建网络并不是必要的,有时可以在__init__()中构建网络。但是,调用build()函数构建网络的优点是可以动态获取输入数据的shape,大大提高了运行效率。
(2)上述代码的运行结果如下。
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_34_2.jpg?sign=1739260816-Ozy3s8Towm9vg8yWwsMhYlmSMZYzpWQG-0-bb42ac58f148378043082f7a97ab3c71)
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_35_1.jpg?sign=1739260816-jSXJJeNuVaSWdizzy0iBUpbbvRWzEUGk-0-57246b08b71c9d532434637ace24e35a)
3.4.3 网络层组合
有很多机器学习模型是不同网络层的组合,网络层组合学习是加快学习速度和精度的重要方法。
(1)使用下面的代码在TensorFlow 2.0中构建一个包含多个网络层的模型。
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_35_2.jpg?sign=1739260816-gIIRHKZeT3FezIRh6SafeIVFQZhV2L6u-0-cf2e7382ddee361ef5f66174378e9a62)
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_36_1.jpg?sign=1739260816-dzqCgXhJyZcKSObt4rBhKZMQci4VScJE-0-91cabe7c063b7a565ca4da1ef89dd2fd)
说明:该例子是resnet的一个残差块,是“卷积+批标准化+残差连接”的组合。
(2)代码的运行结果如下。
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_36_2.jpg?sign=1739260816-3MlKDc8jJfyRYUSPETP3bbQeEYu1yxxa-0-c31406fca8ba67174a25e330f40f9cac)
(3)有时需要构建线性模型,可以直接用tf.keras.Sequential来构建,示例代码如下。
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_36_3.jpg?sign=1739260816-BXQfXsfWNznieudOmwfEvJ4k50Czmg9C-0-c33d7916eca002f936101a2cdfcbae6f)
(4)代码的运行结果如下。
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_36_4.jpg?sign=1739260816-6iCVnHMsjhUgMHMmGHCg6zEwTLXGMu0y-0-6dd67e0bc8659a19a9ebaa390cc87953)
3.4.4 自动求导
TensorFlow使用的求导方法被称为自动微分,它既不是符号求导也不是数值求导,而是两者的结合。
(1)TensorFlow 2.0利用tf.GradientTape API来实现自动求导功能,在tf.GradientTape()上下文中执行的操作都会被记录在“tape”中,然后TensorFlow 2.0使用反向自动微分来计算相关操作的梯度,示例代码如下。
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_37_1.jpg?sign=1739260816-LcoSvl4lkwnf05vjHOAIFxZC4g5PqPIB-0-2f69ef762c0e43051242c55c7af18c10)
(2)代码的运行结果如下。
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_37_2.jpg?sign=1739260816-Ln9YIOemYI2nlJNXlmVPvFvADBka3HPi-0-d5ceef247d0039b4b460d87f10928366)
(3)输出中间变量的导数,代码如下。
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_37_3.jpg?sign=1739260816-Tt7VyXrX0ZySPoa6WAipkYE8Dr6ut4YE-0-ebb6295782da1cc731557fe6057001ec)
(4)代码的运行结果如下。
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_37_4.jpg?sign=1739260816-ALgfZ8ZauobN8qHT6OLibCnFzVcsxDgC-0-7c7c6202ba7eed7c3b6da1c7ebe6b62a)
(5)在默认情况下,GradientTape的资源会在执行tf.GradientTape()后释放。如果希望多次计算梯度,需要创建一个持久的GradientTape。代码如下。
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_37_5.jpg?sign=1739260816-jnBBPhJPp2uyYp3iFVVSoUJEEhYthuKG-0-5add31cbfe981acc3a6049b5f5a1c94d)
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_38_1.jpg?sign=1739260816-EsIgTlargAGmnLczLjKd10jf1jM4rG7i-0-7469f9c9814a94040b184e57518feb28)
(6)代码的运行结果如下。
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_38_2.jpg?sign=1739260816-K3DsIxegrJ9hu1wHbzjqpQTE8yzLkPFz-0-8a6c6d323bb9782d901f0373dbd9d16e)
(7)因为tape记录了整个操作,所以即使存在Python控制流(如if和while),也能正常处理梯度求导,示例代码如下。
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_38_3.jpg?sign=1739260816-ql2PCgrmxM9JJ1wDvdNGnkxrGWz4zDpU-0-e6a4243342f29933b95049091ad80800)
(8)代码的运行结果如下。
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_38_4.jpg?sign=1739260816-zHEsdU1c8ULmy139koigVXVbqGJCoWSw-0-090e5fa430a26559aa7b7fc0a95c22a3)
(9)GradientTape上下文管理器在计算梯度时会保持梯度。因此,GradientTape也可以实现高阶梯度计算,示例代码如下。
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_38_5.jpg?sign=1739260816-qi3km9IXM5VNjuu5028lbFpuIwTzjOS6-0-af377155c2615c1eeee99c74c33a6bf5)
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_39_1.jpg?sign=1739260816-znpaANWG7DSXjnMselSqoUjL01gDgKb7-0-05a0a47232f356a42eaa975c5a510639)
(10)代码的运行结果如下。
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_39_2.jpg?sign=1739260816-Q7UGC7Yx312xC2vUwjdwSaZHurlYzfrG-0-3cb8dcf55b29f903ea3029d2b026a5b2)
本章介绍了一些TensorFlow 2.0的基本概念并举例进行了说明,后面在使用到这些概念时,会举例对具体的使用方法进行介绍。