自然语言处理 基于预训练模型的方法 代码解读 [ section 4.1.6, page 77 ]
自定义神经网络模型的例子:一个简单的多层感知器模型MLP
文件名为 mlp.py
# Defined in Section 4.1.6
# Page 77
# 自定义神经网络模型的第一个例子(The first example of custom neural network model)# 导入torch和torch.nn
# pytorch将常用的神经网络模型封装到了torch.nn包内,从而可以方便灵活地加以调用
# Sigmoid, Softmax, ReLU, tanh等各种激活函数包含在torch.nn.functional中
# activation function 可以实现对输入按元素(每个值value)进行非线性运算(即pointwise,elementwise逐点的计算)import torch
from torch import nn
from torch.nn import functional as F# The class of Multi-Layer Perceptron 多层感知机的类
# 从torch.nn中的Module类继承/派生/扩展/extend 一个子类 sub-class
# 并实现构造函数和forward前向传播函数
class MLP(nn.Module):def __init__(self, input_dim, hidden_dim, num_class):"""constructor构造函数定义了模型所需的成员对象(属性)比如构成该模型的各层,并对其中的参数进行初始化 initializeself 指的是用构造器创建的实例对象本身:param input_dim: 输入的每个序列的元素个数(输入层的神经元个数):param hidden_dim: 隐藏层的神经元个数:param num_class: 输出层的神经元个数"""# 继承父类super(MLP, self).__init__()# 模型三个层的初始化# 线性变换:输入层->隐含层self.linear1 = nn.Linear(input_dim, hidden_dim)# 使用ReLU激活函数self.activate = F.relu# 线性变换:隐含层->输出层 (用来分类)self.linear2 = nn.Linear(hidden_dim, num_class)# 前向传播函数,直接通过实例名调用前向函数,返回nn模型的输出# 参数是inputs输入的数据def forward(self, inputs):# 模型的前向过程# 对输入进行逐层的处理# 从而得到最终的输出结果# 线性变换:输入层->隐含层hidden = self.linear1(inputs)# 使用ReLU激活函数对隐含层进行激活# 让所有的数值都变为非负实数,维数dim保持hidden_dim不会变activation = self.activate(hidden)# 将经过整流线性单元Rectification Linear Unit后的数值activation放到隐含层到输出层的线性映射层outputs = self.linear2(activation)# 对第二维(dim=1)中的element进行softmax的操作# softmax可以让每一个元素的实数数值归一化到 (0,1)# 并且当前维度的每个元素之和等于1# 原来的值越大,则概率越大(函数是单调递增的)# 获得每个输入属于某一类别的概率(num_class是输出张量的元素数目,也即分类的类别数量)probs = F.softmax(outputs, dim=1)# probs是由F.softmax创建的张量,因此该张量的grad_fn求导函数/求梯度函数是<SoftmaxBackward>return probs, hidden, activationdef separator():print("------")# MLP类的构造函数创建一个MLP对象,输入特征的数目input_dim为4,隐藏层维数是5,输出的分类维度是2,即二分类。
mlp = MLP(input_dim=4, hidden_dim=5, num_class=2)# 输入inputs形状为(3, 4)的张量,其中3表示有3个输入(批次大小 batch_size=3, 一次性输入3个样例),4表示每个输入的维度
# i.e. 3*4的矩阵
# 随机赋值每个元素element
inputs = torch.rand(3, 4)
print("输入的张量inputs:")
print(inputs.shape)
print(inputs)
separator()# 通过对象实例直接自动调用forward函数
# 就是用实例的名字,后面小括号的参数放输入inputs
# 得到二分类的概率输出 ( mlp的输出 )
probs, hidden, activation = mlp(inputs)print("隐藏层的张量hidden:")
print(hidden.shape)
print(hidden)
separator()print("隐藏层激活后的张量activation:")
print(activation.shape)
print(activation)
separator()print("输出的张量probs:")
print(probs.shape)# 打印3个输入对应输出的分类概率
print(probs)