动手学深度学习 3.8 多层感知机
前言
从零开始学习ai文章系列计划是个人在《动手学深度学习》和《磨菇书》两本书的学习中的个人笔记,文章也会以课本中的章节分开,即每个章节一片笔记。我会尽量的把主要内容以及遇到的难点进行记录与解决,如果哪里有错误的欢迎指正。或者不清晰的可以直接查看原文部分。
《动手学深度学习》原文(课本):https://tangshusen.me/Dive-into-DL-PyTorch/#/
《动手学深度学习》代码:https://github.com/ShusenTang/Dive-into-DL-PyTorch
(由于有时候公式太多,可能会直接贴图片)
1.隐藏层

多层感知机中,输入和输出个数分别为4和3,中间的隐藏层中包含了5个隐藏单元(hidden unit)。由于输入层不涉及计算,图3.3中的多层感知机的层数为2。
给定一个小批量样本\(X(n * d)\),其批量大小为 \(n\),输入个数为 \(d\)。
其中隐藏单元个数为 \(h\) 。那么隐藏层的输出(也称为隐藏层变量或隐藏变量)为\(H(n * h)\)。因为隐藏层和输出层均是全连接层,因此 隐藏层的权重参数和偏差参数分别为\(W_h(d * h)\)和\(b_h(1 * h)\)。其中d为前一层输出的列数,而这里的前一层输出则直接是输入样本X。且每个隐藏层节点的输出需要一个偏差b,h个隐藏层节点则需要h个偏差b。
输出层同理,输出层的输出为$ O(n * q) $ 其中 \(q\) 为输出单元个数 。输出层的权重和偏差参数分别为 \(W_o(h * q)\) 和 \(b_o(1*q)\) \[ \begin{aligned} H=XW_h*b_h \\ O=HW_o*b_o \end{aligned} \] 将隐藏层的输出直接作为输出层的输入。如果将以上两个式子联立起来,可以得到 \[ O=(XW_h+b_h)W_o+b_o=XW_hW_o+b_hW_o+b_o \] 从联立后的式子可以看出,虽然神经网络引入了隐藏层,却依然等价于一个单层神经网络。其中输出层权重参数为\(W_hW_o\),偏差为\(b_hW_o+b_o\) 。不难发现,即便再添加更多的隐藏层,以上设计依然只能与仅含输出层的单层神经网络等价。
2. 激活函数
2.1 ReLU函数
上述问题的根源在于全连接层只是对数据做仿射变换(affine transformation),而多个仿射变换的叠加仍然是一个仿射变换。解决问题的一个方法是引入非线性变换,例如对隐藏变量使用按元素运算的非线性函数进行变换,然后再作为下一个全连接层的输入。
这个非线性函数被称为激活函数(activation function)。下面我们介绍几个常用的激活函数。 \[ ReLU(x)=max(x,0) \] 可以看出,ReLU函数只保留正数元素,并将负数元素清零。

下图是ReLU的导数图。显然,当输入为负数时,ReLU函数的导数为0;当输入为正数时,ReLU函数的导数为1。尽管输入为0时ReLU函数不可导,但是我们可以取此处的导数为0。

2.2 sigmoid函数
\[ sigmoid(x)=\frac{1}{1+exp(-x)} \]
sigmoid函数在早期的神经网络中较为普遍,但它目前逐渐被更简单的ReLU函数取代。在后面“循环神经网络”一章中我们会介绍如何利用它值域在0到1之间这一特性来控制信息在神经网络中的流动。
下图是sigmoid函数图

依据链式法则,sigmoid函数的导数 \[ sigmoid'(x)=sigmoid(x)(1-sigmoid(x)) \] 下面绘制了sigmoid函数的导数。当输入为0时,sigmoid函数的导数达到最大值0.25;当输入越偏离0时,sigmoid函数的导数越接近0。

2.3 tanh函数
\[ tanh(x)=\frac{1-exp(-2x)}{1+exp(-2x)} \]

依据链式法则,tanh函数的导数 \[ tanh'(x)=1=tanh^2(x) \] 下面绘制了tanh函数的导数。当输入为0时,tanh函数的导数达到最大值1;当输入越偏离0时,tanh函数的导数越接近0。

3 多层感知机
多层感知机就是含有至少一个隐藏层的由全连接层组成的神经网络,且每个隐藏层的输出通过激活函数进行变换。 \[ \begin{aligned} H=ϕ(XW_h*b_h) \\ O=HW_o*b_o \end{aligned} \] \(ϕ\)表示激活函数。H是隐藏层的计算,O是最后的输出层的计算,因此O不用激活函数处理