深度学习笔记(四):多层感知机

前言

本文将基于MINIST数据集,建立一个多层感知机完成图像分类任务。和本系列之前的博文一样,首先采用“造轮子”的方法从头开始实现,最后用pytorch的高级API封装实现。值得注意的是,训练过程和模型评价的函数由d2l包给出,d2l包并不具有普适性。本文采用的代码如下:

1
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs,trainer)

事实上,我们从该函数的参数可以窥见完成深度学习的基本要素:

深度学习的基本要素

  • 数据采集(train_iter, test_iter):获取和规范数据,划分为训练集、验证集和测试集。
  • 模型定义(net):包括模型的层数和每层进行的运算(激活函数),神经元和神经元之间的联系;最重要的是输入层和输出层的定义(一般使用nn.Sequential()进行连续定义)。
  • 损失函数(loss):描述输出层数据(或进一步变换)和真实数据的误差。
  • 优化方法(trainer, num_epochs):包括降低损失的手段(如梯度下降法)、需要优化的参数、以及参数变化幅度(学习率)。num_epochs则定义了重复训练的次数。
  • 多层感知机的从头实现

    导包

    我们使用torch实现多层感知机。从torch包中导入nn模块。

    1
    2
    3
    import torch
    from torch import nn
    from d2l import torch as d2l

    数据采集

    使用d2l已经封装好的数据采集函数,定义每个batch的大小为256。
    这里还需要记录一下:深度学习对训练集划分为不同的batch,batch的获得是随机的,初始化的参数经过batch优化后得到新的参数,继而进入下一个batch运算。通过所有batch运算完最后得到本轮epoch训练的参数。本轮epoch训练的参数继续进入下一个epoch。
    epoch 的概念是为了让模型在整个训练数据集上得到充分的学习,以便提高模型的性能和泛化能力。增加 epoch 的数量可以使模型更好地适应训练数据,但过多的 Epoch 可能会导致过拟合,即模型在训练数据上表现很好,但在新数据上表现不佳。

    1
    2
    batch_size = 256
    train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)

    定义待优化参数和初始化参数

    1
    2
    3
    4
    5
    6
    num_inputs, num_outputs, num_hiddens = 784, 10, 256
    W1 = 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]

    定义模型

    定义激活函数

    1
    2
    def relu(x):
    return torch.max(x,torch.zeros_like(x))

    定义学习模型

    1
    2
    3
    4
    def net(x):
    x = x.reshape(-1, num_inputs)
    h = relu(x@W1 + b1)
    return (h@W2 + b2)

    定义损失函数

    1
    loss = nn.CrossEntropyLoss(reduction = 'none')

    定义优化手段

    1
    2
    3
    4
    num_epochs = 10
    lr = 0.1
    updater = torch.optim.SGD(params, lr = lr)
    d2l.train_ch3(net, train_iter, test_iter,loss, num_epochs, updater)

    基于PyTorch高级API的简洁实现

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    import torch
    from torch import nn
    from d2l import torch as d2l

    # 定义神经网络模型
    net = nn.Sequential(
    nn.Flatten(), # 将输入的图像展平为向量
    nn.Linear(784, 256), # 全连接层,输入维度为784,输出维度为256
    nn.ReLU(), # 激活函数ReLU
    nn.Linear(256, 10) # 全连接层,输入维度为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 = 256 # 批量大小
    lr = 0.1 # 学习率
    num_epochs = 10 # 训练轮数

    # 定义损失函数
    loss = nn.CrossEntropyLoss(reduction="none") # 使用交叉熵损失函数

    # 定义优化器
    trainer = torch.optim.SGD(net.parameters(), lr=lr) # 使用随机梯度下降优化器

    # 调用d2l库中的训练函数进行模型训练
    d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, trainer)

    欢迎关注我的其它发布渠道