李沐《动手学深度学习》预备知识 张量操作及数据处理
李沐《动手学深度学习》预备知识 线性代数及微积分
李沐《动手学深度学习》线性神经网络 线性回归
李沐《动手学深度学习》线性神经网络 softmax回归
教材:李沐《动手学深度学习》
隐藏层的提出原因——线性模型可能会出错
线性意味着单调假设,但是现实生活中存在许多违反单调性的情况:
隐藏层的最简单方式:将许多全连接层堆叠在一起
多层感知机架构:将许多全连接层堆叠在一起,每一层都输出到上面的层,直到生成最后的输出。
多层感知机在输出层和输入层之间增加一个或多个全连接隐藏层,并通过激活函数转换隐藏层的输出。
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;输入为正时,导数为1。
y.backward(torch.ones_like(x), retain_graph=True)
d2l.plot(x.detach(), x.grad, 'x', 'grad of relu', figsize=(5, 2.5))
ReLU求导后:要么让参数消失,要么让参数通过。 这使得优化表现得更好,并且ReLU减轻了困扰以往神经网络的梯度消失问题。
sigmoid函数:
y = torch.sigmoid(x)
d2l.plot(x.detach(), y.detach(), 'x', 'sigmoid(x)', figsize=(5, 2.5))
sigmoid函数的导数:
d
d
x
s
i
g
m
o
i
d
(
x
)
=
e
x
p
(
?
x
)
(
1
+
e
x
p
(
?
x
)
)
2
=
s
i
g
m
o
i
d
(
x
)
(
1
?
s
i
g
m
o
i
d
(
x
)
)
\frac{d}{dx}sigmoid(x)=\frac{exp(-x)}{({{1+exp(-x)}})^2}=sigmoid(x)(1-sigmoid(x))
dxd?sigmoid(x)=(1+exp(?x))2exp(?x)?=sigmoid(x)(1?sigmoid(x))
当输入为0时,sigmoid函数的导数达到最大值0.25,输入在任一方向越远离0点时,导数越接近0。
# 清除以前的梯度
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函数:
y = torch.tanh(x)
d2l.plot(x.detach(), y.detach(), 'x', 'tanh(x)', figsize=(5, 2.5))
tanh函数的导数:
d
d
x
t
a
n
h
(
x
)
=
1
?
t
a
n
h
2
(
x
)
\frac{d}{dx}tanh(x)=1-tanh^2(x)
dxd?tanh(x)=1?tanh2(x)
当输入接近0时,tanh函数的导数接近最大值1,输入在任一方向越远离0点时,导数越接近0。
# 清除以前的梯度
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))
导入相关库,设置批量大小为256,调用load_data_fashion_mnist函数获取数据集
import torch
from torch import nn
from d2l import torch as d2l
batch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)
num_inputs, num_outputs, num_hiddens = 784, 10, 256
W1 = nn.Parameter(torch.randn(
num_inputs, num_hiddens, requires_grad=True) * 0.01)
b1 = nn.Parameter(torch.zeros(num_hiddens, requires_grad=True))
W2 = nn.Parameter(torch.randn(
num_hiddens, num_outputs, requires_grad=True) * 0.01)
b2 = nn.Parameter(torch.zeros(num_outputs, requires_grad=True))
params = [W1, b1, W2, b2]
def relu(X):
a = torch.zeros_like(X)
return torch.max(X, a)
隐藏层数目和隐藏单元数视为超参数,一般选择2的若干次幂为层的宽度, 因为内存在硬件中的分配和寻址方式,这么做往往可以在计算上更高效。
def net(X):
X = X.reshape((-1, num_inputs))
H = relu(X@W1 + b1) # 这里“@”代表矩阵乘法
return (H@W2 + b2)
在李沐《动手学深度学习》线性神经网络 softmax回归中实现了交叉熵损失函数,因此这里直接使用高级API中的内置函数计算softmax和交叉熵损失。
loss = nn.CrossEntropyLoss(reduction='none')
多层感知机的训练过程与softmax回归的训练过程完全相同。 可以直接调用d2l包的train_ch3函数, 将迭代周期数设置为10,并将学习率设置为0.1:
num_epochs, lr = 10, 0.1
updater = torch.optim.SGD(params, lr=lr)
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, updater)
为了对学习到的模型进行评估,在测试数据上应用这个模型:
import torch
from torch import nn
from d2l import torch as d2l
net = nn.Sequential(nn.Flatten(),
nn.Linear(784, 256),
nn.ReLU(),
nn.Linear(256, 10))
def init_weights(m):
if type(m) == nn.Linear:
nn.init.normal_(m.weight, std=0.01)
net.apply(init_weights);
batch_size, lr, num_epochs = 256, 0.1, 10
loss = nn.CrossEntropyLoss(reduction='none')
trainer = torch.optim.SGD(net.parameters(), lr=lr)
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, trainer)