【Transformer从零开始代码实现 pytoch版】(六)模型基本测试运行

模型基本测试及运行

【Transformer从零开始代码实现 pytoch版】(六)模型基本测试运行_第1张图片

(1)构建数据生成器

def data_generator(V, batch, num_batch):
    """ 用于随机生成copy任务的数据

    :param V: 随机生成数字的最大值+1
    :param batch: 每次输送给模型更新一次参数的数据量
    :param num_batch: 输送多少次完成一轮
    :return:
    """
    # 遍历nbatches
    for i in range(num_batch):
        # 在循环中使用np的random.randint方法随机生成[1, v)的整数
        # 每批次10个样本,分布在(batch, 10)形状的矩阵中,然后再把numpy形式转换成torch中的tensor
        data = torch.from_numpy(np.random.randint(1, V, size=(batch, 10)))

		# 生成起始标志,使数据矩阵中的第一列数字都为1,这一列也就成为了起始标志列
        # 当解码器进行第一次解码的时候,会使用起始标志列作为输入
        data[:, 0] = 1

        # 因为是copy任务,所有source与target是完全相同的,且数据样本作用变量不需要求梯度
        # 因此requires_grad设置为False
        with torch.no_grad():
            target = source = data

        # 使用Batch对source和target进行对应批次的掩码张量生成,最后使用yield返回
        yield Batch(source, target)

示例

V = 11                  # 将生成0-10的整数
batch = 20              # 每次喂给模型20个数据进行参数更新
num_batch = 30          # 连续喂30次完成全部数据的遍历

res = data_generator(V, batch, num_batch)
print(f"res {res}")


res <generator object data_generator at 0x000001BD670E4D60>

(2) 获得Transformer模型及其优化器和损失函数

# 获得Transformer模型机及其优化器和损失函数
from pyitcast.transformer_utils import get_std_opt          # 导入优化器工具包,用于获得标准的针对Transformer模型的优化器
from pyitcast.transformer_utils import LabelSmoothing       # 导入标签平滑工具包,用于标签平滑(小幅度的改变原有标签值的值域)
from pyitcast.transformer_utils import SimpleLossCompute    # 导入损失计算工具包,能够使标签平滑后的结果进行损失计算

# 使用make_mode获得model
model = make_model(V, V, N=2)
# 使用get_std_opt获得模拟优化器
model_optimizer = get_std_opt(model)
# 使用LabelSmoothing获得平滑对象
criterion = LabelSmoothing(size=V, padding_idx=0, smoothing=0.0)     # 输入目标词汇的总数
# 使用SimpleLossCompute获得利用标签平滑结果的损失计算方法
loss = SimpleLossCompute(model.generator, criterion, model_optimizer)

  • from pyitcast.transformer_utils import get_std_opt :该标准优化器基于Adam优化器,使其对序列到序列的任务更有效
  • from pyitcast.transformer_utils import LabelSmoothing:因为在理论上人工标注的数据可能并非完全正确,会受一些外界隐私影响而产涩会给你一些微笑的偏差,因此使用标签平滑来弥补这种偏差,减少模型对某一条规律的绝对认知,以防过拟合。
  • from pyitcast.transformer_utils import SimpleLossCompute:损失的计算方法可以认为使交叉熵损失函数。

【Transformer从零开始代码实现 pytoch版】(六)模型基本测试运行_第2张图片
【Transformer从零开始代码实现 pytoch版】(六)模型基本测试运行_第3张图片

(3)运行模型进行训练和评估

# 导入模型单轮训练工具包run_epoch,该工具将对模型使用给定的损失函数计算方法进行单轮参数更新,同时,打印每轮参数更新的损失结果
from pyitcast.transformer_utils import run_epoch

def run(model, loss, epochs=10):
    """ 模型训练函数

    :param model: 要进行训练的模型
    :param loss: 使用的损失计算方法
    :param epochs: 模型的训练轮数
    :return:
    """
    for epoch in range(epochs):
        # 使用训练模式,进行反向传播,所有参数将被更新
        model.train()
        run_epoch(data_generator(V, 8, 20), model, loss)        # batch_size = 20

        # 使用评估模型,不进行反向传播,所有参数不会被更新
        model.eval()
        run_epoch(data_generator(V, 8, 5), model, loss)        # batch_size = 5

示例

run(model, loss)

(4)使用模型进行贪婪解码

# 贪婪解码
from pyitcast.transformer_utils import greedy_decode        # 导入贪婪解码工具包greedy_decode,每次预测都是选择概率最大的结果作为输出

def greedy_run(model, loss, epochs=10):
    for epoch in range(epochs):
        model.train()
        run_epoch(data_generator(V, 8, 20), model, loss)

        model.eval()
        run_epoch(data_generator(V, 8, 5), model, loss)

    # 模型训练结束,进入评估模式
    model.eval()

    # 初始化一个输入张量
    source = torch.LongTensor([[1,3,2,5,4,6,7,8,9,10]])

    # 定义源数据掩码张量,因为元素都是1,这里1代表不遮掩,因此相当于对数据源没有遮掩
    source_mask = torch.ones(1, 1, 10)

    # 起始标志默认为1
    result = greedy_decode(model, source, source_mask, max_len=10, start_symbol=1)
    print(result)

示例

greedy_run(model, loss)

(5)小结

【Transformer从零开始代码实现 pytoch版】(六)模型基本测试运行_第4张图片
【Transformer从零开始代码实现 pytoch版】(六)模型基本测试运行_第5张图片

整体架构构建合集

【Transformer从零开始代码实现 pytoch版】(一)输入部件:embedding+positionalEncoding

【Transformer从零开始代码实现 pytoch版】(二)Encoder编码器组件:mask + attention + feed forward + add&norm

【Transformer从零开始代码实现 pytoch版】(三)Decoder编码器组件:多头自注意力+多头注意力+全连接层+规范化层

【Transformer从零开始代码实现 pytoch版】(四)输出部件:Linear+softmax

【Transformer从零开始代码实现 pytoch版】(五)总架构类的实现

【Transformer从零开始代码实现 pytoch版】(六)模型基本测试运行

你可能感兴趣的:(#,预训练模型,transformer,深度学习,人工智能)