3.8多层感知机
3.8.1隐藏层
- 多层感知机中的隐藏层和输出层都是全连接层
- 虽然神经网络引入了隐藏层,确依然等价于一个单层神经网络,输出层权重是Wh * Wo;偏差参数是bhWo + bo
- 即使添加更多的隐藏层,以上设计依然只能与仅含输出层的单层神经网络等价
3.8.2 激活函数
- 上述问题的根源在于全连接层只是对数据做仿射变换,而多个仿射变换的叠加仍然是一个仿射变换
- 解决问题的方式是引入非线性变换。非线性函数被称为激活函数
- 以下是几个常用的激活函数。
(1) ReLu函数
%matplotlib inline
import d2lzh as d2l
from mxnet import autograd, nd
def xyplot(x_vals, y_vals, name):
d2l.set_figsize(figsize = (5, 2.5))
d2l.plt.plot(x_vals.asnumpy(), y_vals.asnumpy())
d2l.plt.xlabel('x')
d2l.plt.ylabel(name + '(x)')
x = nd.arange(-8.0, 8.0, 0.1)
x.attach_grad()
with autograd.record():
y = x.relu()
xyplot(x, y, 'relu')
(2) ReLu函数导数
y.backward()
xyplot(x, x.grad, 'grad of relu')
(3) sigmoid函数
- sigmoid函数是将元素的值变换到0和1之间
- sigmoid在早期的神经网络中较为普遍,目前正被ReLU函数逐渐替代
- 当输入接近0的时候,sigmoid函数接近线性
- 根据链式法则,sigmoid函数的导数为sigmoid’(x) = sigmoid(x)(1 - sigmoid(x))
with autograd.record():
y = x.sigmoid()
xyplot(x, y, 'sigmoid')
(4) sigmoid函数的导数
- 当输入为0时,sigmoid函数的导数达到最大值 0.25;
- 当输入越便宜0时,sigmoid函数的导数越接近0
y.backward()
xyplot(x, x.grad, 'grad of sigmoid')
(5)tanh函数
- 双曲正切函数,将元素的值变换到-1 到 +1 之间
- tanh(x) = (1 - exp(-2x))/(1 + exp(-2x))
- 当输入接近0时,tanh函数接近线性变化换。tanh函数在坐标系的原点上对称
with autograd.record():
y = x.tanh()
xyplot(x, y, 'tanh')
(6)tanh函数导数
- 根据链式法则,tanh函数的导数为 tanh’(x) = 1 - tanh^2(x)
- 当输入为0时,tanh函数的导数达到最大值1;当输入越偏离0时,tanh函数的导数越接近0
y.backward()
xyplot(x, x.grad, 'grad of tanh')
(7)关于求梯度的总结
- 参考文章:https://www.jianshu.com/p/1515015c03f2
- step1: x.attach_grad()
- 是将x加入梯度,申请存储梯度所需要的内存,可通过 x.grad获取x梯度
- step2:定义关于x的函数y,调用record()函数来记录与求梯度有关的 计算
with autograd.record()</