当前位置: 首页 > article >正文

【NLP9-Transformer经典案例】

Transformer经典案例

1、语言模型

以一个符合语言规律的序列为输入,模型将利用序列间关系等特征,输出在一个在所有词汇上的概率分布,这样的模型称为语言模型。

2、语言模型能解决的问题

根据语言模型定义,可以在它的基础上完成机器翻译,文本生成等任务,因为我们通过最后输出的概率分布来预测下一个词汇是什么

语言模型可以判断输入的序列是否为一句完整的话,因为我们可以根据输出的概率分布查看最大概率是否落在句子结束符上,来判断完整性

语言模型本身的训练目标是预测下一个词,因为它的特征提取部分会抽象很多语言序列之间的关系,这些关系可能同样对其它语言类任务有效果。因此可以作为预训练模型进行迁移学习

3、模型实现步骤

1、导包

2、导入wikiText-2数据集并作基本处理

3、构建用于模型输入的批次化数据

4、构建训练和评估函数

5、进行训练和评估(包括验证以及测试)

4、数据准备

wikiText-2数据集体量中等,训练集共有600篇文章,共208万左右词汇,在33278个不重复词汇,OVV(有多少正常英文词汇不在该数据集中的占比)为2.6%。验证集和测试集均为60篇。

torchtext重要功能

对文本数据进行处理,比如文本语料加载,文本迭代器构建等。

包含很多经典文本语料的预加载方法。其中包括的语料有:用于情感分析的SST和IMDB,用于问题分类TREC,用于及其翻译的WMT14,IWSLT,以及用于语言模型任务wikiText-2

# 1、导包
import math
import torch
import torch.nn as nn
import torch.nn.functional as F
#英文文本数据集工具包
import torchtext

#导入英文分词工具
#from torchtext.legacy.data import Field

from torchtext.data.utils import get_tokenizer
#from torchtext.legacy.data import *
#导入已经构建完成的Transformer包

from pyitcast.transformer import TransformerModel

import torch
import torchtext
from torchtext.legacy.data import Field,TabularDataset,Iterator,BucketIterator


TEXT=torchtext.data.Field(tokenize=get_tokenizer("basic_english"),
                          init_token ='<sos>',
                          eos_token ='<eos>',
                          lower = True)
print(TEXT)
# 2、导入wikiText-2数据集并作基本处理
train_txt,val_txt,test_txt = torchtext.datasets.WikiText2.splits(TEXT)
print(test_txt.examples[0].text[:10])

#将训练集文本数据构建一个vocab对象,可以使用vocab对象的stoi方法统计文本共包含的不重复的词汇总数
TEXT.build_vocab(train_txt)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")


# 3、构建用于模型输入的批次化数据
def batchify(data,batch_size):
    #data,之前得到的文本数据
    # bsz,批次的样本量
    #第一步使用TEXT的numericalize方法将单词映射成对应的联系数字
    data = TEXT.numericalize([data.examples[0].text])
    #取得需要经过多少次的batch_size后能够遍历完所有的数据
    nbatch = data.size(0) // batch_size
    #利用narrow方法对数据进行切割
    #第一参数代表横轴切割还是纵轴切割,0 代表横轴,1代表纵轴
    #第二个参数,第三个参数分别代表切割的起始位置和终止位置
    data=data.narrow(0,0,nbatch * batch_size)
    #对data的形状进行转变
    data = data.view(batch_size,-1).t().contiguous()
    return data.to(device)

# x=torch.tensor([[1,2,3],[4,5,6],[7,8,9]])
# print(x.narrow(0,0,2))
# print(x.narrow(1,1,2))

#设置训练数据、验证数据、测试数据的批次大小
batch_size =20
eval_batch_size =10
train_data = batchify(train_txt,batch_size)
val_data = batchify(val_txt,eval_batch_size)
test_data = batchify(test_txt,eval_batch_size)

#设定句子的最大长度
bptt =35
def get_batch(source,i):
    seq_len = min(bptt,len(source) - 1 - i)
    data = source[i:i+seq_len]
    target = source[i+1:i+1+seq_len].view(-1)
    return data,target

# source = test_data
# i =1
# x,y = get_batch(source,i)
# print(x)
# print(y)


# 4、构建训练和评估函数
#通过TEXT.vocab.stoi方法获取不重复的词汇总数
ntokens = len(TEXT.vocab.stoi)
#设置词嵌入维度的值等于200
emsize =200
#设置前馈全连接层的节点数等于200
nhid =200
#设置编码层层数等于2
nlayers=2
#设置多头注意力中的头数等于2
nhead =2
#设置置零比率
dropout =0.2
#将参数传入TransformerModel 中实例化模型
model = TransformerModel(ntokens,emsize,nhead,nhid,nlayers,dropout).to(device)

#设定损失函数,采用交叉熵损失函数
criterion= nn.CrossEntropyLoss()

#设置学习率
lr =5.0

#设置优化器
optimizer = torch.optim.SGD(model.parameters(),lr=lr)

criterion = nn.CrossEntropyLoss()
lr =5.0
optimizer = torch.optim.SGD(model.parameters(),lr=lr)
#定义学习率调整器,使用torch自带的lr_scheduler,将优化器传入
scheduler = torch.optim.lr_scheduler.StepLR(optimizer,1.0,gamma=0.95)


# 5、进行训练和评估(包括验证以及测试)

#训练函数
import time
def train():
    #首先开启训练模式
    model.train()
    #定义初始损失值
    total_loss =0

    start_time = time.time()
    #遍历训练数据进行模型的训练
    for batch,i in enumerate(range(0,train_data.size(0) -1 ,bptt)):
        #通过前面的get_batch函数获取源数据和目标数据
        data,targets = get_batch(train_data,i)
        #设置梯度归零
        optimizer.zero_grad()
        #通过模型预测输出
        output = model(data)
        #计算损失值
        loss = criterion(output.view(-1,ntokens),targets)
        #进行反向传播
        loss.backward()
        #进行梯度规范化,防止出现梯度爆炸或者梯度消失
        torch.nn.utils.clip_grad_norm(model.parameters(),0.5)
        #进行参数更新
        optimizer.step()
        #将损失值进行累加
        total_loss +=loss.item()
        # 获取当前开始时间
        log_interval =200
        #打印日志信息
        if batch % log_interval ==0 and batch>0:
            #计算平均损失
            cur_loss = total_loss/log_interval
            #计算训练到目前的耗时
            elapsed = time.time() - start_time
            #打印日志信息
            print('| epoch {:3d} | {:5d}/{:5d} batches | '
                  'lr {:02.2f} | ms/batch {:5.2f} | '
                  'loss {:5.2f} | ppl {:8.2f}'.format(
                   epoch, batch, len(train_data) // bptt, scheduler.get_lr()[0],
                   elapsed * 1000 / log_interval,
                   cur_loss, math.exp(cur_loss)))
            #每个打印批次借结束后,将总损失值清零
            total_loss =0
            start_time= time.time()

#评估函数
def evaluate(eval_model,data_source):
    #eval_model,代表每轮训练后产生的模型
    # data_source,代表验证集数据或者测试集数据
    #首先开启评估模式
    eval_model.eval()
    #初始化总损失值
    total_loss =0
    #模型开启评估模式,不进行反向传播求梯度
    with torch.no_grad():
        #遍历验证数据
        for i in range(0,data_source.size(0)-1,bptt):
            #首先通过get_batch函数获取源数据和目标数据
            data,targets = get_batch(data_source,i)
            #将源数据放入评估模型中,进行预测
            output = eval_model(data)
            #对输出张量进行变形
            output_flat = output.view(-1,ntokens)
            #累加损失值
            total_loss +=criterion(output_flat,targets).item()
        #返回评估的总损失值
        return total_loss

best_val_loss = float("inf")

epochs =3
best_model =None

for epoch in range(1,epochs +1):
    epoch_start_time = time.time()
    train()
    val_loss = evaluate(model,val_data)
    print('-'*50)
    print('| end of epoch {:3d} | time: {:5.2f}s | valid loss {:5.2f} | '
          'valid ppl {:8.2f}'.format(epoch, (time.time() - epoch_start_time),
                                     val_loss, math.exp(val_loss)))
    print('-'*50)
    #通过比较当前轮次的损失值,获取最佳模型
    if val_loss<best_val_loss:
        best_val_loss=val_loss
        best_model=model
    #每个轮次后调整优化器的学习率
    scheduler.step()

#添加测试的流程代码
test_loss = evaluate(best_model,test_data)
print('-'*90)
print('|End of training |test loss {:5,2f}'.format(test_loss))
print('-'*50)


没有运行成功


http://www.kler.cn/a/273431.html

相关文章:

  • 提高文本处理效率:精通awk命令中的$NF
  • 【系统架构设计师】2022年真题论文: 论湖仓—体架构及其应用(包括解题思路和素材)
  • 十四届蓝桥杯STEMA考试Python真题试卷第二套第五题
  • SpringBoot新闻稿件管理系统:架构与实现
  • SpringBoot+VUE2完成WebSocket聊天(数据入库)
  • Django ORM详解:外键使用(外键逻辑关联)与查询优化
  • 放慢音频速度的三个方法 享受慢音乐
  • 【数据挖掘】实验3:常用的数据管理
  • 【Docker】常用命令 docker build
  • 还原wps纯粹的编辑功能
  • VSCode下使用github初步
  • java的成员变量和局部变量
  • 前端面试拼图-实践经验
  • 基础:TCP三次握手做了什么,为什么要握手?
  • 【DataWhale学习笔记-蝴蝶书共读】大语言模型背后
  • CTF题型 Http请求走私总结Burp靶场例题
  • EI Scopus检索 | 第二届大数据、物联网与云计算国际会议(ICBICC 2024) |
  • 苍穹外卖-day09:用户端历史订单模块(理解业务逻辑),商家端订单管理模块(理解业务逻辑),校验收货地址是否超出配送范围(相关API)
  • springboot280基于WEB的旅游推荐系统设计与实现
  • 环境变量和Bash内置命令
  • android 顺滑滑动嵌套布局
  • Mac玩《幻兽帕鲁》为什么打不开D3DMetal?d3d错误怎么办 d3dxl error
  • 基于YOLOv8深度学习的橙子病害智能诊断与防治系统【python源码+Pyqt5界面+数据集+训练代码】深度学习实战、目标分类
  • mac清除dns缓存指令 mac清除缓存怎么清理
  • 复制word文档,合并word文档
  • 【vscode】vscode重命名变量后多了很多空白行