PDF 物理页索引 330
文件中的第 331 页 · 印刷页码:314
人工智能与大数据技术导论
下面来创建一个神经网络,通过DNNRegressor类来完成。我们使用hidden units来定义神经网络的结构。hiddenunits提供了一个整数列表,每个整数对应一个隐藏层,代表隐藏层中节点的个数,比如:
上面指定了包含2个隐藏层的神经网络。第一个隐藏层包含3个节点,第二个隐藏层包含10个节点。如果我们想添加更多的层,就可以添加更多的整数到列表中。比如,hidden\_units=[10,20,30,40]将创建4层,分别包含10、20、30和40个节点。默认情况下,所有隐藏层使用ReLU激活函数,并完全连接。
定义特征列和输入函数:
314
PDF 物理页索引 331
文件中的第 332 页 · 印刷页码:315
第10章 神经网络
315
PDF 物理页索引 332
文件中的第 333 页 · 印刷页码:316
人工智能与大数据技术导论
316
PDF 物理页索引 333
文件中的第 334 页 · 印刷页码:317
下面我们训练一个神经网络模型。调整一些超参数,把RMSE降低到110以下(在前面的线性回归例子中,我们认为RMSE110是一个不错的结果)。尝试修改各个设置来提高验证集上的准确率。
对于神经网络而言,过拟合是一个潜在风险。通过检查训练数据上的误差和验证数据上的误差之间的差额,我们可以判断是否开始过拟合了。如果差额开始增加,通常是一个过拟合的信号。
第10章 神经网络
317
PDF 物理页索引 334
文件中的第 335 页 · 印刷页码:318
尝试多种不同的设置。读者可记录这些设置和结果,并进行分析。当你获得一个好的设置时,可以尝试多运行几次,看看能否重现结果。一般而言,可以先使用小的神经网络权重开始,然后逐步加大,查看效果。
开始训练:
结果如图10-13、图10-14所示。
人工智能与大数据技术导论
318
PDF 物理页索引 335
文件中的第 336 页 · 印刷页码:319
下面我们尝试不同的参数:
结果如图10-15、图10-16所示。
一旦满意在验证集上的结果,接下来就可以在测试集上进行测试。在下面的代码中,装载
第10章 神经网络
319
PDF 物理页索引 336
文件中的第 337 页 · 印刷页码:320
测试数据,预处理这些数据,然后调用预测函数。最后计算根均方值:
结果如下:
Final RMSE (on test data): 116.12
10.2 训练神经网络
机器学习的常见任务就是拟合,也就是给定一些样本点,用合适的曲线揭示这些样本点随着自变量的变化关系。深度学习同样也是为了这个目的,只不过此时样本点不再限定为(x,y)点对,而可以是由向量、矩阵等组成的广义点对(X,Y)。此时,(X,Y)之间的关系也变得十分复杂,不太可能用一个简单函数表示。正如前面提到的,我们可以用多层神经网络来表示这样的关系。
Backpropagation(反向传播)算法是最常见的一种多层神经网络训练算法。借助这种算法,梯度下降法在多层神经网络中将成为可行方法。反向传播算法对于快速训练大型神经网络来说至关重要。TensorFlow可自动处理反向传播算法,因此我们不需要对该算法做深入研究。
10.2.1 正向传播算法
在学习反向传播算法的工作原理之前,我们首先了解一下什么是正向传播算法。如图10-17所示,这是一个简单的神经网络(见左图),其中包含一个输入节点、一个输出节点以及两个隐藏层(分别有两个节点)。相邻的层中的节点通过权重 $\mathrm { w _ { i j } }$ 相关联,这些权重是网络参数。如图10-17的中图所示,每个节点都有一个输入x、一个激活函数f(x)以及一个输出y=f(x),必须是非线性函数,否则神经网络就只能学习线性模型。常用的激活函数是S型函数,比如:
$$
f ( x ) = { \frac { 1 } { 1 + e ^ { - x } } }
$$
人工智能与大数据技术导论
320
PDF 物理页索引 337
文件中的第 338 页 · 印刷页码:321
如图10-17右图所示,根据数据自动学习网络的权重,以便让所有输入xinput的预测输出Youtput接近目标Ytarget。为了衡量与该目标的差距,我们使用了一个误差函数E(见图10-17右图的右上端)。常用的误差函数是:
$$
\begin{array} { r } { E ( y _ { o u t p u t } , y _ { t a r g e t } ) { = } \frac { 1 } { 2 } ( y _ { o u t p u t } - y _ { t a r g e t } ) ^ { 2 } } \end{array}
$$
针对图10-17,我们首先看一下什么是正向传播(即从图的底部往上看)。取一个输入样本 $( x _ { i n p u t } , y _ { t a r g e t } )$ ,并更新网络的输入层。为了保持一致性,我们将输入视为与其他任何节点相同,但不具有激活函数,所以:
$$
y _ { 1 } = x _ { i n p u t }
$$
然后,更新第一个隐藏层。我们取上一层节点的输出y,并使用权重来计算下一层节点的输入x,即:
$$
x _ { j } = \sum _ { i \in i n ( j ) } w _ { i j } y _ { i } + b _ { j }
$$
有了上面公式中的x值之后,更新第一个隐藏层中节点的输出。为此,我们使用激活函数
第10章神经网络
321
PDF 物理页索引 338
文件中的第 339 页 · 印刷页码:322
f(x),即 $\scriptstyle \mathbf { y } = \mathbf { f } ( \mathbf { x } )$ 。使用这两个公式,我们可以传播到网络的其余节点,并获得网络的最终输出(一直到最顶端)。
$$
y = f ( x )
$$
$$
x _ { j } = \sum _ { i \in i n ( j ) } w _ { i j } y _ { i } + b _ { j }
$$
10.2.2 反向传播算法
在讲解反向传播算法之前,我们先说明一下误差导数。反向传播算法会对特定样本的预测输出和理想输出进行比较,然后确定网络的每个权重的更新幅度。为此,需要计算误差相对于每个权重的变化情况 $\big ( \frac { d E } { d w _ { i j } } \big )$ 。获得误差导数后,可以使用一种简单的更新法则来更新权重:
$$
w _ { i j } = w _ { i j } - \alpha \frac { d E } { d w _ { i j } }
$$
其中, $\mathrm { a }$ 是一个正常量,称为“学习速率”,我们需要根据经验对该常量进行微调。该更新法则非常简单:如果在权重提高后误差降低了 $( \ \frac { d E } { d w _ { i j } } < 0 )$ ,则提高权重;如果在权重提高后误差也提高了 $( \ \frac { d E } { d w _ { i j } } > 0 )$ ,则降低权重。如图10-18所示,每个权重的连线上都加了误差导数。
人工智能与大数据技术导论
322
PDF 物理页索引 339
文件中的第 340 页 · 印刷页码:323
为了帮助计算 $\frac { d E } { d w _ { i j } }$ ,我们还为每个节点分别存储了两个导数:节点dE/dx的输入以及节点dE/dy的输出(见图10-18的右图,比较左图和右图)。
如图10-18右图所示(见图上箭头),下面开始反向传播误差导数。由于我们拥有此特定输入样本的预测输出,因此可以计算误差随该输出的变化情况。根据误差函数:
$$
\begin{array} { r } { E = \frac { 1 } { 2 } ( y _ { o u t p u t } - y _ { t a r g e t } ) ^ { 2 } } \end{array}
$$
可以得出:
$$
\frac { \partial E } { \partial y _ { o u t p u t } } = y _ { o u t p u t } - y _ { t a r g e t }
$$
有了dE/dy,接下来便可以根据链式法则得出dE/dx(见图10-18,从顶端往下走)。
$$
{ \frac { \partial E } { \partial x } } = { \frac { d y } { d x } } { \frac { \partial E } { \partial y } } = { \frac { d } { d x } } f ( x ) { \frac { \partial E } { \partial y } }
$$
其中,当f(x)是S型激活函数时:
$$
\begin{array} { r } { \frac { d } { d x } f ( x ) = f ( x ) ( 1 - f ( x ) ) } \end{array}
$$
一旦得出相对于某节点的总输入的误差导数,我们便可以得出相对于进入该节点的权重的误差导数:
$$
\frac { \partial E } { \partial w _ { i j } } = \frac { \partial x _ { j } } { \partial w _ { i j } } \frac { \partial E } { \partial x _ { j } } = y _ { i } \frac { \partial E } { \partial x _ { j } }
$$
根据链式法则,我们还可以根据上一层得出dE/dy。此时,形成了一个完整的循环。
$$
\frac { \partial E } { \partial y _ { i } } = \sum _ { j \in o u t ( i ) } \frac { \partial x _ { j } } { \partial y _ { i } } \frac { \partial E } { \partial x _ { j } } = \sum _ { j \in o u t ( i ) } w _ { i j } \frac { \partial E } { \partial x _ { j } }
$$
接下来,只需重复前面的几个公式,直到计算出所有误差导数即可。反向传播完成。
值得注意的是,很多常见情况都会导致反向传播算法出错。
梯度消失
反向传播依赖于梯度。较低层(更接近输入)的梯度可能会变得非常小。在深度网络中,计算这些梯度时,可能涉及许多小项的乘积。当较低层的梯度逐渐消失到0时,这些层的训练速度会非常缓慢,甚至不再训练。ReLU激活函数有助于防止梯度消失。一般来讲,我们尽量将模型的深度限制为最小的有效深度。
梯度爆炸
如果网络中的权重过大,那么较低层的梯度会涉及许多大项的乘积。在这种情况下,梯度就会爆炸:梯度过大导致难以收敛。批标准化可以降低学习速率,因而有助于防止梯度爆炸。
第10章 神经网络
323