pytorch-transformers,pytorch transformerencoder
本文主要介绍从0开始用Pytorch实现变压器的实践。通过示例代码非常详细的介绍,对大家的学习或者工作都有一定的参考价值。有需要的朋友下面和边肖一起学习。
00-1010摘要1。构造数据1.1句子长度1.2生成句子1.3生成词典1.4获取矢量化句子2。位置代码2.1计算括号中的值2.2获取位置代码3。长关注3.1自我面膜
目录
随着时间序列预测的不断发展,类变压器模型凭借其强大的优势在CV和NLP领域逐渐取代了传统模型。其中,Informer在长期预测方面远优于传统的RNN模型,Swin Transformer在图像识别方面明显强于传统的CNN模型。深入掌握Transformer已经成为人工智能领域不可或缺的要求。本文将使用Pytorch框架实现Transformer中的位置编码、多头注意机制、自屏蔽、因果屏蔽等功能,从0构建一个Transformer网络。
随着时间序列预测的不断发展,类变压器模型以其强大的优势逐渐取代CV和NLP领域的传统模型。Informer在长期预测上远优于传统的RNN模型,Swin Transformer在图像识别上明显优于传统的CNN模型。对变形金刚的深度掌握已经成为人工智能领域的必然要求。本文将使用Pytorch框架实现Transformer中的位置编码、多头注意机制、自屏蔽、因果屏蔽等功能,从0构建一个Transformer网络。
摘要
一、构造数据
#对于单词嵌入,以序列建模为例。
#输入句子有两个,第一个是2,第二个是4。
src_len=torch.tensor([2,4])。至(torch.int32)
#有两个目标句。第一长度是4,第二长度是3。
tgt_len=torch.tensor([4,3])。至(torch.int32)
打印(src_len)
打印(tgt_len)
输入句子(src_len)有两个,第一个长度为2,第二个长度为4目标句子(tgt_len)有两个。第一个长度为4, 第二个长度为3
1.1 句子长度
用随机数生成句子,空格用零填充,所有句子长度保持一致。
src _ seq=torch . cat([torch . unsqueeze(f . pad(torch . randint(1,max_num_src_words,(L,)),(0,max(src_len)-L),0) for L in src_len])
TGT _ seq=torch . cat([torch . unsqueeze(
F.pad(torch.randint(1, max_num_tgt_words, (L, )), (0, max(tgt_len)-L)), 0) for L in tgt_len])
print(src_seq)
print(tgt_seq)
src_seq为输入的两个句子,tgt_seq为输出的两个句子。
为什么句子是数字?在做中英文翻译时,每个中文或英文对应的也是一个数字,只有这样才便于处理。
1.3 生成字典
在该字典中,总共有8个字(行),每个字对应8维向量(做了简化了的)。注意在实际应用中,应当有几十万个字,每个字可能有512个维度。
# 构造word embeddingsrc_embedding_table = nn.Embedding(9, model_dim)
tgt_embedding_table = nn.Embedding(9, model_dim)
# 输入单词的字典
print(src_embedding_table)
# 目标单词的字典
print(tgt_embedding_table)
字典中,需要留一个维度给class token,故是9行。
1.4 得到向量化的句子
通过字典取出1.2
中得到的句子
# 得到向量化的句子src_embedding = src_embedding_table(src_seq)
tgt_embedding = tgt_embedding_table(tgt_seq)
print(src_embedding)
print(tgt_embedding)
该阶段总程序
import torch# 句子长度
src_len = torch.tensor([2, 4]).to(torch.int32)
tgt_len = torch.tensor([4, 3]).to(torch.int32)
# 构造句子,用0填充空白处
src_seq = torch.cat([torch.unsqueeze(F.pad(torch.randint(1, 8, (L, )), (0, max(src_len)-L)), 0) for L in src_len])
tgt_seq = torch.cat([torch.unsqueeze(F.pad(torch.randint(1, 8, (L, )), (0, max(tgt_len)-L)), 0) for L in tgt_len])
# 构造字典
src_embedding_table = nn.Embedding(9, 8)
tgt_embedding_table = nn.Embedding(9, 8)
# 得到向量化的句子
src_embedding = src_embedding_table(src_seq)
tgt_embedding = tgt_embedding_table(tgt_seq)
print(src_embedding)
print(tgt_embedding)
二、位置编码
位置编码是transformer的一个重点,通过加入transformer位置编码,代替了传统RNN的时序信息,增强了模型的并发度。位置编码的公式如下:(其中pos代表行,i代表列)
2.1 计算括号内的值
# 得到分子pos的值pos_mat = torch.arange(4).reshape((-1, 1))
# 得到分母值
i_mat = torch.pow(10000, torch.arange(0, 8, 2).reshape((1, -1))/8)
print(pos_mat)
print(i_mat)
2.2 得到位置编码
# 初始化位置编码矩阵pe_embedding_table = torch.zeros(4, 8)
# 得到偶数行位置编码
pe_embedding_table[:, 0::2] =torch.sin(pos_mat / i_mat)
# 得到奇数行位置编码
pe_embedding_table[:, 1::2] =torch.cos(pos_mat / i_mat)
pe_embedding = nn.Embedding(4, 8)
# 设置位置编码不可更新参数
pe_embedding.weight = nn.Parameter(pe_embedding_table, requires_grad=False)
print(pe_embedding.weight)
三、多头注意力
3.1 self mask
有些位置是空白用0填充的,训练时不希望被这些位置所影响,那么就需要用到self mask。self mask的原理是令这些位置的值为无穷小,经过softmax后,这些值会变为0,不会再影响结果。
3.1.1 得到有效位置矩阵
# 得到有效位置矩阵vaild_encoder_pos = torch.unsqueeze(torch.cat([torch.unsqueeze(F.pad(torch.ones(L), (0, max(src_len) - L)), 0)for L in src_len]), 2)
valid_encoder_pos_matrix = torch.bmm(vaild_encoder_pos, vaild_encoder_pos.transpose(1, 2))
print(valid_encoder_pos_matrix)
3.1.2 得到无效位置矩阵
invalid_encoder_pos_matrix = 1-valid_encoder_pos_matrixmask_encoder_self_attention = invalid_encoder_pos_matrix.to(torch.bool)
print(mask_encoder_self_attention)
True
代表需要对该位置mask
3.1.3 得到mask矩阵
用极小数填充需要被mask的位置
# 初始化mask矩阵score = torch.randn(2, max(src_len), max(src_len))
# 用极小数填充
mask_score = score.masked_fill(mask_encoder_self_attention, -1e9)
print(mask_score)
算其softmat
mask_score_softmax = F.softmax(mask_score)print(mask_score_softmax)
可以看到,已经达到预期效果
到此这篇关于Pytorch从0实现Transformer的实践的文章就介绍到这了,更多相关Pytorch Transformer内容请搜索盛行IT软件开发工作室以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT软件开发工作室!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。