![从零开始学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=1738991709-elzPWAA5tJaV5hgTsShcdj5981XUmgtO-0-ab194a7289b00c12fb563f46d0b91f4d)
(2)代码的运行结果如下,包含权重和偏置信息。
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_33_1.jpg?sign=1738991709-m2tIwext0g0eufph6mRpxL4K4EIiwMjC-0-520c50630c87ce729eadb5f8dd479a6a)
(3)tf.keras非常灵活,还可以分别取出上例中的权重和偏置,代码如下。
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_33_2.jpg?sign=1738991709-Iy4Wx13tPNdTFV5dNnNz3Si1Skez2oVH-0-b5632ef96c4327da084992cead186ad3)
(4)代码的运行结果如下。
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_33_3.jpg?sign=1738991709-GAlpgwOJeTi0d36fOd6wL8qyMkReDDTG-0-b9acf2a15352dbd2c3d07bc7064e0695)
3.4.2 自定义网络层
在实际中,经常需要扩展tf.keras.Layer类并自定义网络层。本节介绍如何自定义网络层。
(1)在自定义网络层的过程中主要使用3个函数,示例代码如下。
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_34_1.jpg?sign=1738991709-eMlE5pKYfRGVmvKi3iewt38v7T0CmZvO-0-ce58ff6b9a9463692d00103d216f7bc6)
说明:调用build()函数构建网络并不是必要的,有时可以在__init__()中构建网络。但是,调用build()函数构建网络的优点是可以动态获取输入数据的shape,大大提高了运行效率。
(2)上述代码的运行结果如下。
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_34_2.jpg?sign=1738991709-nAFuVp4E5L0ZV5VFyPV71rhGFJl0oHdD-0-44b5e3173aadcc02ab97558bacec1d02)
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_35_1.jpg?sign=1738991709-ZIHisQmK3w29rT4XG7RHLZOjXyyI6jeE-0-76618a3daff531c453610d789354ceba)
3.4.3 网络层组合
有很多机器学习模型是不同网络层的组合,网络层组合学习是加快学习速度和精度的重要方法。
(1)使用下面的代码在TensorFlow 2.0中构建一个包含多个网络层的模型。
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_35_2.jpg?sign=1738991709-sUkiEFi9aWjMwLPTphlRGeM18slvS3yV-0-7b544fe4073913ea31c9d50ac3f0f4e2)
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_36_1.jpg?sign=1738991709-nH7JQ8oU0BSAsKPa7ong6y4eeVpy3ThT-0-a58e5fb8aded04ff0e8c872a1aed950f)
说明:该例子是resnet的一个残差块,是“卷积+批标准化+残差连接”的组合。
(2)代码的运行结果如下。
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_36_2.jpg?sign=1738991709-ZWN7qy5HDlMZPpHBN5Hd90ro4MtzuRj8-0-7f807f14977a1a3542298a439ddf20fd)
(3)有时需要构建线性模型,可以直接用tf.keras.Sequential来构建,示例代码如下。
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_36_3.jpg?sign=1738991709-jl0izmGfY0x1GXPA3AdKGLEHU3u8MhgH-0-4b982c15f16ad2930f5ab3ae70f9e0f3)
(4)代码的运行结果如下。
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_36_4.jpg?sign=1738991709-DCaPSFgzErsr7P3k17xIfBjQxzjz0V1G-0-f65209c1c8b881e718373129df1866d6)
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=1738991709-j0OWTBD21GjUTr7lQD12i5QJCV2jPmoc-0-643e39e9f31fc5c4541a24098d9325c0)
(2)代码的运行结果如下。
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_37_2.jpg?sign=1738991709-Bl4IF1kvdcxOLH0AhDGAo4Vtt9qVLAyn-0-1eedb58526c5075c956e6f6b4d83ed8e)
(3)输出中间变量的导数,代码如下。
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_37_3.jpg?sign=1738991709-KUGDJXX2yKk0eVAEPqCmdyh9bLKJSAXo-0-93ac0b192945f866fbeb686ca6efe626)
(4)代码的运行结果如下。
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_37_4.jpg?sign=1738991709-62JigxJtdJQPXIN9xfmlRv5V632gFKO9-0-6665093480567556d6e9ce15deea8b0a)
(5)在默认情况下,GradientTape的资源会在执行tf.GradientTape()后释放。如果希望多次计算梯度,需要创建一个持久的GradientTape。代码如下。
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_37_5.jpg?sign=1738991709-T6WwAsOGQ2BooLVdvWo4E1MQT9biUS31-0-5151d930b77468202731356e72e14f74)
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_38_1.jpg?sign=1738991709-VmHuZiXvaYjXXtdgvzb1tbt0vcXMuWiR-0-5f98730e857c8401553dbc466f9354bd)
(6)代码的运行结果如下。
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_38_2.jpg?sign=1738991709-yb8KqTYxc4axOQfAjIZChb1OlfG85dus-0-346e73efc95473e03c75760b18a2ca42)
(7)因为tape记录了整个操作,所以即使存在Python控制流(如if和while),也能正常处理梯度求导,示例代码如下。
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_38_3.jpg?sign=1738991709-1YyHeq3H1UHWpjcjHzZNwbZ9YB5VJVQ0-0-d267f230f890f803b34dd4594da81f41)
(8)代码的运行结果如下。
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_38_4.jpg?sign=1738991709-U54JTPlZ9NB0kJi0GTphv3Oa8h47Tdf9-0-4572b7e421163293e3650c0baaff6934)
(9)GradientTape上下文管理器在计算梯度时会保持梯度。因此,GradientTape也可以实现高阶梯度计算,示例代码如下。
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_38_5.jpg?sign=1738991709-XqaBfxxZg8RjOkHHU1rywl2omrI659md-0-eb1a09d1c5c870a1b28748c96411214e)
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_39_1.jpg?sign=1738991709-rYdViTkxpGgFz7j8bEAZwMxxvVbi8GHB-0-6f1e128f76548b8a15485922818682b1)
(10)代码的运行结果如下。
![](https://epubservercos.yuewen.com/938466/18002370308013906/epubprivate/OEBPS/Images/39376_39_2.jpg?sign=1738991709-a8cVCVm6zqfMgVeXIolLZy9AdZrUGZPp-0-305ac16e734ce88144a7fd3a82fc491f)
本章介绍了一些TensorFlow 2.0的基本概念并举例进行了说明,后面在使用到这些概念时,会举例对具体的使用方法进行介绍。