目的:使模型(e.g., MLP)不会退化成线性模型
ReLu
修正线性单元(Rectified linear unit,ReLu)
实现:
%matplotlib inline
import torch
from d2l import torch as d2l
# ReLu函数图
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))
当输入为负时,ReLU函数的导数为0,而当输入为正时,ReLU函数的导数为1。 注意,当输入值精确等于0时,ReLU函数不可导。 在此时,我们默认使用左侧的导数,即当输入为0时导数为0。 我们可以忽略这种情况,因为输入可能永远都不会是0。
y.backward(torch.ones_like(x), retain_graph = True) #返回一个用1填充的张量,其大小与输入相同。
# 进行一次backward之后,各个节点的值会清除,这样进行第二次backward会报错,如果加上retain_graph==True后,计算节点中间值不会被释放,可以再来一次backward。
d2l.plot(x.detach(), x.grad, 'x','grad of relu', figsize=(5,2.5))
PReLU
y = torch.prelu(x, torch.tensor([0.25]))
d2l.plot(x.detach(), y.detach(), 'x', 'prelu(x)', figsize = (5, 2.5))
PReLU函数梯度图
x.grad.data.zero_()
y.backward(torch.ones_like(x), retain_graph=True)
d2l.plot(x.detach(), x.grad, 'x', 'grad of prelu', figsize = (5, 2.5))
sigmoid
y = torch.sigmoid(x)
d2l.plot(x.detach(), y.detach(), 'x', 'sigmoid(x)', figsize = (5, 2.5))
sigmoid函数的导数
# 清除以前的梯度
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函数
注意,当输入在0附近时,tanh函数接近线性变换。 函数的形状类似于sigmoid函数, 不同的是tanh函数关于坐标系原点中心对称。
y = torch.tanh(x)
d2l.plot(x.detach(), y.detach(), 'x', 'tanh(x)', figsize = (5, 2.5))
tanh函数的导数:
# 清楚以前的梯度
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))