隐藏层
- 可以通过在网络中加入一个或多个隐藏层来克服线性模型的限制, 使其能处理更普遍的函数关系类型。
- 多层感知机MLP: 将许多全连接层堆叠在一起。 每一层都输出到上面的层,直到生成最后的输出。 把前层看作表示,把最后一层看作线性预测器。 这种架构通常称为多层感知机(multilayer perceptron),通常缩写为MLP。
- 线性→非线性: 引入激活函数
常见的激活函数
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))
- 反向传播,求x的导数:
y.backward(torch.ones_like(x), retain_graph=True)
d2l.plot(x.detach(), x.grad, 'x', 'grad of relu', figsize=(5, 2.5))
- 变体:pReLU
参数化ReLU(pReLU),该变体为ReLU添加了一个线性项,因此即使参数是负的,某些信息仍然可以通过:
sigmoid函数
sigmoid函数将输入变换为**区间(0, 1)**上的输出。
绘制函数曲线:
- sigmoid在隐藏层中已经较少使用, 它在大部分时候被更简单、更容易训练的ReLU所取代。
- 导数:
绘制导数曲线:
tanh函数
与sigmoid函数类似,tanh(双曲正切)函数也能将其输入压缩转换到区间(-1, 1)上。
- 注意,当输入在0附近时,tanh函数接近线性变换。
- 函数的形状类似于sigmoid函数, 不同的是tanh函数关于坐标系原点中心对称。
- 导数:当输入接近0时,tanh函数的导数接近最大值1。
python/ pytorch语法分析
tensor.detach()和detach_():
- tensor.detach():
- 设置requires_grad = False, 得到的这个tensor永远不需要计算器梯度,不具有grad.
- 即使之后重新将它的requires_grad置为true,它也不会具有梯度grad. 后面进行反向传播时,到该调用detach()的tensor就会停止,不能再继续向前进行传播.
- ❗❗注意:使用detach返回的tensor和原始的tensor共用一个内存,即一个修改另一个也会跟着改变。
- tensor.detach():
两个的区别就是detach_()是对本身的更改,detach()则是生成了一个新的tensor,它本身的require_grad没有变! - 看看代码理解一下:
import torch
a = torch.tensor([1, 2, 3.], requires_grad=True)
print(a.grad)
out = a.sigmoid()
print(out)
print(id(out))
#添加detach(),c的requires_grad为False
out.detach()
print(out)
print(id(out))
#添加detach(),c的requires_grad为False
c = out.detach()
print(c)
print(id(c))
out.detach()对out本身没有起作用,out仍然是需要求导的;但是c = out.detach()之后,生成的这个新向量c则是没有grad_fn这一项的!
如果把out.detach()改成detach_()的话,那么out就跟c一样了,都不再含有grad_fn这一项,所以如果此时再使用out进行反向传播,就会报错
import torch
a = torch.tensor([1, 2, 3.], requires_grad=True)
print(a.grad)
out = a.sigmoid()
print(out)
print(id(out))
#添加detach(),c的requires_grad为False
out.detach_()
print(out)
print(id(out))
out.sum().backward()
print(a.grad)