文章目录

  • 多层感知机的从零开始实现
  • 直观理解图
  • 推导公式
  • 动手实现多层感知机
  • 初始化模型参数
  • 激活函数
  • 模型
  • 损失函数
  • 训练
  • 预测结果
  • 小结


多层感知机的从零开始实现

多层感知机,通过向输入层和输出层中间添加多个隐藏层(Hidden),使其能处理更普遍的函数关系类型,预测可信度更高。

直观理解图

原理图如下:

多层感知器神经网络实现目标识别python代码 多层感知机算法_多层感知机

注意,这个多层感知机有4个输入,3个输出,其隐藏层包含5个隐藏单元

输入层不涉及任何计算,因此使用此网络产生输出只需要实现隐藏层和输出层的计算。 因此,这个多层感知机中的层数为2。 注意,这两个层都是全连接的。 每个输入都会影响隐藏层中的每个神经元, 而隐藏层中的每个神经元又会影响输出层中的每个神经元。

推导公式

我们都知道,之前学习的softmax回归模型或者线性模型仅包含输入输出,是直接通过仿射函数完成的,如下公式。

多层感知器神经网络实现目标识别python代码 多层感知机算法_迭代器_02

其中,X为样本向量,每个标量即为一个特征。W为特征权重向量,每个标量对应特征的权重b为偏置量。

通过该式子计算便可以得到一个预测值概率分布

那么现在,我们已经向输入层和输出层增加了隐藏层(Hidden),则现在预测公式即为

多层感知器神经网络实现目标识别python代码 多层感知机算法_多层感知机_03
多层感知器神经网络实现目标识别python代码 多层感知机算法_迭代器_04

这是一个具有单隐层的多层感知机的实现公式(多层感知器套用多个 多层感知器神经网络实现目标识别python代码 多层感知机算法_多层感知机_05 即可),其中 多层感知器神经网络实现目标识别python代码 多层感知机算法_多层感知机_05 即为隐层, 多层感知器神经网络实现目标识别python代码 多层感知机算法_多层感知机_07输入层到隐层的权重和偏置, 多层感知器神经网络实现目标识别python代码 多层感知机算法_多层感知机_08隐层到输出层的权重和偏置,经过多层运算,即可得到最终结果。

动手实现多层感知机

若对下面的某些函数实现感到困惑,请看图像分类数据集和从零开始实现softmax回归着两篇文章,均包含函数算法详细实现过程。

现在让我们尝试自己实现一个多层感知机。 为了与之前softmax回归获得的结果进行比较, 我们将继续使用Fashion-MNIST图像分类数据集

import torch                                          #引入torch包
from torch import nn                                  #引入神经网络
from d2l import torch as d2l

batch_size = 256                                       #小批量样本大小为256

#获取训练集迭代器和测试集迭代器
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)                     #该方法在《图像分类数据集》中实现
初始化模型参数

回想一下,Fashion-MNIST中的每个图像由 多层感知器神经网络实现目标识别python代码 多层感知机算法_迭代器_09

我们用几个张量来表示我们的参数。 注意,对于每一层我们都要记录一个权重矩阵和一个偏置向量。 跟以前一样,我们要为损失关于这些参数的梯度分配内存。

num_imputs = 784                                       #输入特征个数
num_outputs = 10                                       #输出类别个数
num_hiddens = 256                                      #隐层的宽度,即隐单元的个数,256个


W1 = nn.Parameter(torch.randn(
    num_imputs, num_hiddens, requires_grad=True)*0.1)                        #定义输入层与隐层之间的权重矩阵, 即(784, 256)
b1 = nn.Parameter(torch.zeros(num_hiddens, requires_grad=True))              #定义输入层与隐层之间的偏置量,长度为256

W2 = nn.Parameter(torch.randn(
    num_hiddens, num_outputs, requires_grad=True)*0.1)                       #定义隐层与输出层之间的权重矩阵,即(256, 10)
b2 = nn.Parameter(torch.zeros(num_outputs, requires_grad=True))              #定义隐层与输出层之间的偏置量,长度为10

params = [W1, b1, W2, b2]                                                     #均作为网络模型的参数
激活函数

为了确保我们对模型的细节了如指掌, 我们将实现ReLU激活函数(即舍弃负数), 而不是直接调用内置的relu函数。

def relu(X):
    a = torch.zeros_like(X)                            #同X形状一致的全0矩阵
    return torch.max(X, a)                            #通过max()函数实现X矩阵去除负数的效果
模型

因为我们忽略了空间结构, 所以我们使用reshape将每个二维图像转换为一个长度为num_inputs的向量。 只需几行代码就可以实现我们的模型。

def net(X):
    X = X.reshape((-1, num_imputs))                   #对X进行形状重塑,使其符合矩阵相乘
    H = relu(X@W1 + b1 )                              #首先计算输入层到隐层的结果,记得一定要使用激活函数预处理数据
    return H@W2 + b2                                 #再计算隐层到输出层的结果
损失函数

由于我们已经从零实现过softmax函数, 因此在这里我们直接使用高级API中的内置函数来计算softmax和交叉熵损失

loss = nn.CrossEntropyLoss(reduction='none')         #定义内置的交叉熵损失函数,保持数据稳定性,torch.nn内部API算法
训练

幸运的是,多层感知机的训练过程与softmax回归的训练过程完全相同。 可以直接调用d2l包的train_ch3函数(不懂可以看这里,从零实现softmax回归), 将迭代周期数设置为10,并将学习率设置为0.1.

num_epochs = 10                                     #迭代次数选择为10
lr = 0.1                                            #学习率为0.1
updater = torch.optim.SGD(params, lr)               #定义优化函数,更新神经网络内的参数,即[W1,b1,W2,b2],torch内梯度下降算法


#开始训练模型,参数分别为神经网络、训练集迭代器、测试集迭代器、损失函数、迭代次数、优化函数
#《从零开始实现softmax回归模型》文章中有详细实现过程
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, updater)

多层感知器神经网络实现目标识别python代码 多层感知机算法_迭代器_10

预测结果

为了对学习到的模型进行评估,我们将在一些测试数据上应用这个模型。

# 预测6个图片的标签
#《从零开始实现softmax回归模型》文章中有该函数详细实现过程
d2l.predict_ch3(net, test_iter)

多层感知器神经网络实现目标识别python代码 多层感知机算法_多层感知机_11

小结

手动实现一个简单的多层感知机是很容易的。然而如果有大量的层,从零开始实现多层感知机会变得很麻烦(例如,要命名和记录模型的参数)。

另外,多层感知机(MLP) 是深度学习流行模型的简单思想概括,深刻理解该模型将非常有助于其它深度学习模型的学习。