《动手学深度学习 Pytorch版》 4.1 多层感知机
%matplotlib inline
import torch
from d2l import torch as d2l
4.1.1 隐藏层
整节理论,详见书本。
以下展示常见的激活函数。
-
ReLU 函数
\[\mathrm{ReLU}(x)=\max(x,0) \]修正线性单元(rectified linear unit,ReLU),通过将相应的激活值设为 0,仅保留正元素丢弃所有负元素。ReLU 函数求导表现特别好:要么让参数消失,要么让参数通过。这使得优化表现更好,并且可以缓解梯度消失问题。
以下为 ReLU 函数图像及其导数图像(在 0 处默认使用左侧导数)。
x = torch.arange(-8.0, 8.0, 0.1, requires_grad=True)
y = torch.relu(x)
d2l.plot(x.detach(), y.detach(), 'x', 'relu(x)', figsize=(5, 2.5))
y.backward(torch.ones_like(x), retain_graph=True)
d2l.plot(x.detach(), x.grad, 'x', 'grad of relu', figsize=(5, 2.5))
-
sigmoid 函数
\[\mathrm{sigmoid}(x)=\frac{1}{1+\exp(-x)} \]sigmoid 函数通常被称为挤压函数(squashing function),它将输入变换为区间 (0, 1) 上的输出。当输入接近 0 时,sigmoid 函数接近线性变换。其导数在输入为 0 时达到最大值 0.25。目前已经很少使用,大部分时候会使用 ReLU 函数。
以下为 sigmoid 函数图像及其导数图像。
y = torch.sigmoid(x)
d2l.plot(x.detach(), y.detach(), 'x', 'sigmoid(x)', figsize=(5, 2.5))
x.grad.data.zero_() # 清除以前的梯度
y.backward(torch.ones_like(x),retain_graph=True)
d2l.plot(x.detach(), x.grad, 'x', 'grad of sigmoid', figsize=(5, 2.5))
-
tanh 函数
\[\mathrm{tanh}(x)=\frac{1-\exp(-2x)}{1+\exp(-2x)} \]双曲正切函数(hyperbolic tangent function),与 sigmoid 函数类似,也能将其压缩转换到区间 (-1,1) 上。当输入在 0 附近时,tanh 函数接近线性变换,但不同于 sigmoid 函数的是,tanh 函数关于坐标原点中心对称。
以下为 tanh 函数图像及其导数图像。
y = torch.tanh(x)
d2l.plot(x.detach(), y.detach(), 'x', 'tanh(x)', figsize=(5, 2.5))
x.grad.data.zero_() # 清除以前的梯度
y.backward(torch.ones_like(x),retain_graph=True)
d2l.plot(x.detach(), x.grad, 'x', 'grad of tanh', figsize=(5, 2.5))
练习
(1)计算 pReLU 激活函数的导数。
(2)证明一个仅使用 ReLU(或pReLU)的多层感知机构造了一个连续的分段线性函数。
不会......
(3)证明 \(\mathrm{tanh}(x)+1=2\mathrm{sigmoid}(2x)\)。
(4)假设我们有一个非线性单元,将它一次应用于一个小批量的数据,这会导致什么样的问题?
这题也不会......