本文章来源于对李沐动手深度学习
代码以及原理的理解,并且由于李沐老师的代码能力很强,以及视频中讲解代码的部分较少,所以这里将代码进行尽量逐行详细解释
并且由于pytorch的语法有些小伙伴可能并不熟悉,所以我们会采用逐行解释+小实验的方式来给大家解释代码
大家可能对多层感知机这个名字还比较陌生,但是它还有一个让我们比较熟悉的名字全连接神经网络,我们后面还会讲解其他形式的神经网络,如卷积神经网络、循环神经网络等等
导入模块以及数据集
import torch
from torch import nn
from d2l import torch as d2lbatch_size = 256
train_iter,test_iter = d2l.load_data_fashion_mnist(batch_size)
在这里我们仍然fashion_mnist
数据集来进行本次的demo
随机初始化参数
# 由于输入的是图片,图片计算机读取的时候是按照像素读取而不是张数
# 所以inputs和outputs和hiddens都会比较大,因为它们是以像素作为基本单元的
# 模型的训练和预测的速率也会比较慢
num_inputs = 784
num_outputs = 10
num_hiddens = 256W1 = nn.Parameter(torch.randn(num_inputs,num_hiddens,requires_grad = True))
b1 = nn.Parameter(torch.zeros(num_hiddens,requires_grad=True))
W2 = nn.Parameter(torch.randn(num_hiddens,num_outputs,requires_grad = True))
b2 = nn.Parameter(torch.zeros(num_outputs,requires_grad=True))
params = [W1,b1,W2,b2]
这里的随机初始化参数在我们前面已经讲解过了,但是我们需要的是注意这些参数的维度,我们可以根据李沐老师的课程,得到多层感知机的一个很重要的讲解图片
小实验/参数的维度
我们就随便用上面初始化的一个参数举例子,我们这里就拿W1进行举例
W1 = nn.Parameter(torch.randn(num_inputs,num_hiddens,requires_grad = True))
W1的维度为(num_inputs × num_hiddens)
的一个张量,所以针对于这样初始化维度的一个矩阵,我们后面如果要进行线形层运算的话,根据矩阵运算的性质,我们应该将W1左乘输入X矩阵才可以,即
Y = X W + B Y=XW+B Y=XW+B
激活函数
为了让整个模型不是完全线性的模型,我们要引入一个非线性的激活函数,比如Sigmoid函数,但是我们这里采用另一种函数,名字叫做ReLU函数,函数的图像如下:
这个激活函数可以让我们在模型的训练过程中收敛速度加快
tips:其实每个激活函数的作用都相差不大,我们没有很大的必要把它当一个重要的超参数去看待
模型的实现
# 实现模型
def net(X):X = X.reshape((-1,num_inputs))H = relu(X @ W1 + b1)return (H @ W2 + b2)loss = nn.CrossEntropyLoss(reduction='none')
在这个代码里面,我们采用逐行讲解的方式来进行
逐行讲解
X = X.reshape((-1,num_inputs))
首先,为了完成矩阵的乘法,我们需要先把输入的X给reshape为一个二维的矩阵,并且我们一定需要指定的是这个矩阵的第二个维度的参数,因为我们需要把它和一个(num_inputs × num_hiddens)
维度的矩阵右乘
H = relu(X @ W1 + b1)
对于初学者而言,可能这一句话有一点难理解,这里我们是将矩阵的结果进行了一次relu函数,这个过程和我们多层感知机的运作过程相关,多层感知机的运作过程李沐老师的课里面有提到过,我这里可以用两个公式来进行概括
H = X W + B Y = R e L U ( H ) H = XW+B\\ Y = ReLU(H) H=XW+BY=ReLU(H)
利用这两个公式,我们可以看出先利用输入和权重算出X,再利用我们的激活函数来算出输出(也就是下一层的输入)
优化器
num_epochs = 10
lr = 0.1
updater = torch.optim.SGD(params,lr=lr)
在这个代码里面,我们采用了训练轮数为10轮,学习率为0.1,然后优化器我们还是采用前面的随机梯度下降的方法
模型的训练
train_ch3(net,train_iter,test_iter,loss,num_epochs,trainer)