提交 f75d4053 编写于 作者: A Aston Zhang

revise mlp

上级 44d95a76
......@@ -12,7 +12,7 @@ from mxnet.gluon import loss as gloss, nn
## 定义模型
和Softmax回归唯一的不同在于,我们多加了一个全连接层作为隐藏层,其中该层的隐藏单元个数为256,并使用ReLU作为激活函数。
和Softmax回归唯一的不同在于,我们多加了一个全连接层作为隐藏层。它的隐藏单元个数为256,并使用ReLU作为激活函数。
```{.python .input n=5}
net = nn.Sequential()
......
......@@ -70,7 +70,7 @@ loss = gloss.SoftmaxCrossEntropyLoss()
训练多层感知机的步骤和之前训练Softmax回归的步骤没什么区别。我们直接调用`gluonbook`包中的`train_cpu`函数,它的实现已经在[“Softmax回归——从零开始”](softmax-regression-scratch.md)一节里介绍了。
这里我们设超参数迭代周期为5,学习率为0.5。
我们在这里设超参数迭代周期数为5,学习率为0.5。
```{.python .input n=8}
num_epochs = 5
......@@ -82,7 +82,7 @@ gb.train_cpu(net, train_iter, test_iter, loss, num_epochs, batch_size,
## 小结
* 我们可以通过手动定义模型及其参数来实现简单的多层感知机。
* 当多层感知机的层数较多时,本节的实现方法会显得较繁琐例如在定义模型参数的时候。
* 当多层感知机的层数较多时,本节的实现方法会显得较繁琐例如在定义模型参数的时候。
## 练习
......
......@@ -28,15 +28,15 @@ $$
那么,如果隐藏层也只对输入做仿射变换会怎么样呢?设单个样本的特征为$\boldsymbol{x} \in \mathbb{R}^{1 \times x}$,隐藏层的权重参数和偏差参数分别为$\boldsymbol{W}_h \in \mathbb{R}^{x \times h}, \boldsymbol{b}_h \in \mathbb{R}^{1 \times h}$。
假设$\boldsymbol{h} = \boldsymbol{x} \boldsymbol{W}_h + \boldsymbol{b}_h$且$\boldsymbol{o} = \boldsymbol{h} \boldsymbol{W}_o + \boldsymbol{b}_o$,联立两式可得$\boldsymbol{o} = \boldsymbol{x} \boldsymbol{W}_h \boldsymbol{W}_o + \boldsymbol{b}_h \boldsymbol{W}_o + \boldsymbol{b}_o$:它等价于单层神经网络的输出$\boldsymbol{o} = \boldsymbol{x} \boldsymbol{W}^\prime + \boldsymbol{b}^\prime$,其中$\boldsymbol{W}^\prime = \boldsymbol{W}_h \boldsymbol{W}_o, \boldsymbol{b}^\prime = \boldsymbol{b}_h \boldsymbol{W}_o + \boldsymbol{b}_o$。因此,在隐藏层中使用仿射变换的多层感知机与前面介绍的单层神经网络没什么区别。
假设$\boldsymbol{h} = \boldsymbol{x} \boldsymbol{W}_h + \boldsymbol{b}_h$且$\boldsymbol{o} = \boldsymbol{h} \boldsymbol{W}_o + \boldsymbol{b}_o$,联立两式可得$\boldsymbol{o} = \boldsymbol{x} \boldsymbol{W}_h \boldsymbol{W}_o + \boldsymbol{b}_h \boldsymbol{W}_o + \boldsymbol{b}_o$:它等价于单层神经网络的输出$\boldsymbol{o} = \boldsymbol{x} \boldsymbol{W}^\prime + \boldsymbol{b}^\prime$,其中$\boldsymbol{W}^\prime = \boldsymbol{W}_h \boldsymbol{W}_o, \boldsymbol{b}^\prime = \boldsymbol{b}_h \boldsymbol{W}_o + \boldsymbol{b}_o$。因此,在隐藏层中使用仿射变换的多层感知机与前面介绍的单层神经网络没什么区别。
## 激活函数
通过上面的例子我们发现,必须在隐藏层中使用其他变换,例如添加非线性变换,才能使多层感知机变得有意义。我们将这些非线性变换称为激活函数(activation function)。激活函数能对任意形状的输入都按元素操作且不改变输入的形状。以下列举三种常用的激活函数。
通过上面的例子,我们发现:必须在隐藏层中使用其他变换,例如添加非线性变换,才能使多层感知机变得有意义。我们将这些非线性变换称为激活函数(activation function)。激活函数能对任意形状的输入都按元素操作且不改变输入的形状。以下列举三种常用的激活函数。
### ReLU函数
ReLU(rectified linear unit)函数提供了一个很简单的非线性变换。给定元素$x$,函数定义是
ReLU(rectified linear unit)函数提供了一个很简单的非线性变换。给定元素$x$,该函数定义为
$$\text{relu}(x) = \max(x, 0).$$
......@@ -72,7 +72,7 @@ $$\text{sigmoid}(x) = \frac{1}{1 + \exp(-x)}.$$
我们会在后面“循环神经网络”一章中介绍如何利用sigmoid函数值域在0到1之间这一特性来控制信息在神经网络中的流动。
我们下面绘制sigmoid函数。当元素值接近0时,sigmoid函数接近线性变换。
下面绘制了sigmoid函数。当元素值接近0时,sigmoid函数接近线性变换。
```{.python .input n=3}
xyplot(x.asnumpy(), x.sigmoid().asnumpy(), 'x', 'sigmoid(x)')
......@@ -120,29 +120,29 @@ $$
## 计算梯度
有了多层感知机的损失函数后,优化算法将更新模型参数从而不断降低损失函数的值。我们在前面章节里用了小批量随机梯度下降,和大多数其他优化算法一样,它需要计算损失函数有关的模型参数的梯度。我们可以把数学上对复合函数求梯度的链式法则应用于多层感知机的梯度计算。我们将在后面章节详细介绍深度学习模型中的梯度计算,例如多层感知机的反向传播。
有了多层感知机的损失函数后,优化算法将迭代模型参数从而不断降低损失函数的值。我们在前面章节里用了小批量随机梯度下降,和大多数其他优化算法一样,它需要计算损失函数有关模型参数的梯度。我们可以把数学上对复合函数求梯度的链式法则应用于多层感知机的梯度计算。我们将在后面章节详细介绍深度学习模型中的梯度计算,例如多层感知机的反向传播。
## 衰减和爆炸
需要注意的是,当深度学习模型的层数较多时,模型的数值稳定性容易变差。假设一个层数为$L$的多层感知机的第$l$层$\boldsymbol{H}^{(l)}$的权重参数为$\boldsymbol{W}^{(l)}$,输出层$\boldsymbol{H}^{(L)}$的权重参数为$\boldsymbol{W}^{(L)}$。为了便于讨论,我们也假设不考虑偏差参数,且所有隐藏层的激活函数为$\phi(x) = x$。给定输入$\boldsymbol{X}$,多层感知机的第$l$层的输出$\boldsymbol{H}^{(l)} = \boldsymbol{X} \boldsymbol{W}^{(1)} \boldsymbol{W}^{(2)} \ldots \boldsymbol{W}^{(l)}$,如果层数$l$较大,$\boldsymbol{H}^{(l)}$的计算可能会出现衰减(vanishing)或爆炸(explosion)。举个例子,假如输入和所有层的权重参数都是标量的话,比如0.5和2,多层感知机的第50层输出在输入前的系数分别为$0.5^{50}$(衰减)和$2^{50}$(爆炸)。类似地,当层数较多时,梯度的计算也更容易出现衰减或爆炸。我们会在后面章节介绍梯度的衰减或爆炸,例如循环神经网络的通过时间反向传播。
需要注意的是,当深度学习模型的层数较多时,模型的数值稳定性容易变差。假设一个层数为$L$的多层感知机的第$l$层$\boldsymbol{H}^{(l)}$的权重参数为$\boldsymbol{W}^{(l)}$,输出层$\boldsymbol{H}^{(L)}$的权重参数为$\boldsymbol{W}^{(L)}$。为了便于讨论,我们也假设不考虑偏差参数,且所有隐藏层的激活函数为$\phi(x) = x$。给定输入$\boldsymbol{X}$,多层感知机的第$l$层的输出$\boldsymbol{H}^{(l)} = \boldsymbol{X} \boldsymbol{W}^{(1)} \boldsymbol{W}^{(2)} \ldots \boldsymbol{W}^{(l)}$。此时,如果层数$l$较大,$\boldsymbol{H}^{(l)}$的计算可能会出现衰减(vanishing)或爆炸(explosion)。举个例子,假如输入和所有层的权重参数都是标量的话,比如0.5和2,多层感知机的第50层输出在输入前的系数分别为$0.5^{50}$(衰减)和$2^{50}$(爆炸)。类似地,当层数较多时,梯度的计算也更容易出现衰减或爆炸。我们会在后面章节介绍梯度的衰减或爆炸,例如循环神经网络的通过时间反向传播。
## 随机初始化模型参数
在神经网络中,我们需要随机初始化模型参数。
在神经网络中,我们需要随机初始化模型参数。下面我们来解释这一点。
以图3.3为例,假设输出层只保留一个输出单元$o_1$(删去$o_2, o_3$和指向它们的箭头),且隐藏层使用相同的激活函数。如果初始化后每个隐藏单元的参数都相同,那么在模型训练时每个隐藏单元将根据相同输入计算出相同的值。接下来输出层也将从各个隐藏单元拿到完全一样的值。在迭代每个隐藏单元的参数时,这些参数在每轮迭代的值都相同。那么,由于每个隐藏单元拥有相同激活函数和相同参数,所有隐藏单元将继续根据下一次迭代时的相同输入计算出相同的值。如此周而复始。这种情况下,无论隐藏单元个数有多大,隐藏层本质上只有1个隐藏单元在发挥作用。因此,我们通常会随机初始化神经网络的模型参数,例如每个神经元的权重参数。
### MXNet的默认随机初始化
随机初始化模型参数的方法有很多。在[“线性回归——使用Gluon”](linear-regression-gluon.md)一节中,我们使用`net.initialize(init.Normal(sigma=0.01))`使模型`net`的权重参数采用正态分布的随机初始化方式。如果不指定初始化方法,例如`net.initialize()`,我们将使用MXNet的默认随机初始化方法。默认的随机初始化方法使得权重参数每个元素服从-0.07到0.07之间的均匀分布,偏差参数全部清零。
随机初始化模型参数的方法有很多。在[“线性回归——使用Gluon”](linear-regression-gluon.md)一节中,我们使用`net.initialize(init.Normal(sigma=0.01))`使模型`net`的权重参数采用正态分布的随机初始化方式。如果不指定初始化方法,例如`net.initialize()`,我们将使用MXNet的默认随机初始化方法。默认的随机初始化中,权重参数每个元素随机采样于-0.07到0.07之间的均匀分布,偏差参数全部清零。
### Xavier随机初始化
还有一种比较常用的随机初始化方法叫做Xavier随机初始化 [1]。假设某全连接层的输入个数为$a$,输出个数为$b$,Xavier随机初始化将使得该层中每个权重参数都随机采样于均匀分布
还有一种比较常用的随机初始化方法叫做Xavier随机初始化 [1]。假设某全连接层的输入个数为$a$,输出个数为$b$,Xavier随机初始化将使得该层中权重参数的每个元素都随机采样于均匀分布
$$U\left(-\sqrt{\frac{6}{a+b}}, \sqrt{\frac{6}{a+b}}\right).$$
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册