nn.TransformerEncoderLayer

这个类是transformer encoder的组成部分,代表encoder的一个层,而encoder就是将transformerEncoderLayer重复几层。

Args:
d_model: the number of expected features in the input (required).
nhead: the number of heads in the multiheadattention models (required).
dim_feedforward: the dimension of the feedforward network model (default=2048).
dropout: the dropout value (default=0.1).
activation: the activation function of intermediate layer, relu or gelu (default=relu).

Examples::
encoder_layer = nn.TransformerEncoderLayer(d_model=512, nhead=8)
src = torch.rand(10, 32, 512)
out = encoder_layer(src)

需要注意的是transformer 只能输入 seqlenth x batch x dim 形式的数据。

nn.TransformerEncoder

这里是transformer的encoder部分,即将上述的encoder-layer作为参数输入初始话以后可以获得TransformerEncoder

Args
encoder_layer: an instance of the TransformerEncoderLayer() class (required).
num_layers: the number of sub-encoder-layers in the encoder (required).
norm: the layer normalization component (optional).

Examples::
encoder_layer = nn.TransformerEncoderLayer(d_model=512,nhead=8) transformer_encoder=nn.TransformerEncoder(encoder_layer,num_layers=6)
src = torch.rand(10, 32, 512)
out =transformer_encoder(src)

PostionEncoder

这里的数学原理就不再详细叙述了,因为我也没搞特别明白反正就是获得位置信息,与embedding加起来就行了。

class PositionalEncoding(nn.Module):def __init__(self, d_model, dropout=0.1, max_len=5000):super(PositionalEncoding, self).__init__()self.dropout = nn.Dropout(p=dropout)pe = torch.zeros(max_len, d_model)position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1)div_term = torch.exp(torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model))pe[:, 0::2] = torch.sin(position * div_term)pe[:, 1::2] = torch.cos(position * div_term)pe = pe.unsqueeze(0).transpose(0, 1)self.register_buffer('pe', pe)def forward(self, x):x = x + self.pe[:x.size(0), :]return self.dropout(x)

TransformerModel

这里将参考pytorch tutorial中的内容

class First_TransformerModel(nn.Module):def __init__(self, ninp=300, nhead=4, nhid=128, nlayers=6, dropout=0.5):super(First_TransformerModel, self).__init__()from torch.nn import TransformerEncoder, TransformerEncoderLayerself.model_type = 'Transformer'self.src_mask = Noneself.pos_encoder = PositionalEncoding(ninp, dropout)encoder_layers = TransformerEncoderLayer(ninp, nhead, nhid, dropout)self.transformer_encoder = TransformerEncoder(encoder_layers, nlayers)self.ninp = ninpdef _generate_square_subsequent_mask(self, src, lenths):'''padding_masksrc:max_lenth,num,300lenths:[lenth1,lenth2...]'''# mask num_of_sens x max_lenthmask = torch.ones(src.size(1), src.size(0)) == 1for i in range(len(lenths)):lenth = lenths[i]for j in range(lenth):mask[i][j] = Falsereturn maskdef forward(self, src, mask):'''src:num_of_all_sens,max_lenth,300'''self.src_mask = masksrc = src * math.sqrt(self.ninp)src = self.pos_encoder(src)output = self.transformer_encoder(src, src_key_padding_mask=self.src_mask)output = output[0,:,:]return outputclass PositionalEncoding(nn.Module):def __init__(self, d_model, dropout=0.1, max_len=5000):super(PositionalEncoding, self).__init__()self.dropout = nn.Dropout(p=dropout)pe = torch.zeros(max_len, d_model)position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1)div_term = torch.exp(torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model))pe[:, 0::2] = torch.sin(position * div_term)pe[:, 1::2] = torch.cos(position * div_term)pe = pe.unsqueeze(0).transpose(0, 1)self.register_buffer('pe', pe)def forward(self, x):x = x + self.pe[:x.size(0), :]return self.dropout(x)

在这里我们只需将输入的src (seqlenth x batch x ninp)进行下面的操作即可,先乘上根号下的ninp,经过positionencoder,再经过encoder即可。

    src = src * math.sqrt(self.ninp)src = self.pos_encoder(src)output = self.transformer_encoder(src, src_key_padding_mask=self.src_mask)
  • 这里还需要提一下mask

mask 是什么呢?
mask主要可以分为两种mask,一种是src_mask,一种是src_key_padding_mask, 这里我们主要解释src_key_padding_mask。
nn.Transformer中,提到了src_key_padding_mask的size,必须是 NxS ,即 batch x seqlenths
通过这个mask,就可以将padding的部分忽略掉,让attention注意力机制不再参与这一部分的运算。

  • 需要注意的是,src_key_padding_mask 是一个二值化的tensor,在需要被忽略地方应该是True,在需要保留原值的情况下,是False

这里附上我定义的双层transformer代码
第一层

class First_TransformerModel(nn.Module):def __init__(self, ninp=300, nhead=4, nhid=128, nlayers=6, dropout=0.5):super(First_TransformerModel, self).__init__()from torch.nn import TransformerEncoder, TransformerEncoderLayerself.model_type = 'Transformer'self.src_mask = Noneself.pos_encoder = PositionalEncoding(ninp, dropout)encoder_layers = TransformerEncoderLayer(ninp, nhead, nhid, dropout)self.transformer_encoder = TransformerEncoder(encoder_layers, nlayers)# self.encoder = nn.Embedding(ntoken, ninp)self.ninp = ninp# self.decoder = nn.Linear(ninp, ntoken)def _generate_square_subsequent_mask(self, src, lenths):'''padding_masksrc:max_lenth,num,300lenths:[lenth1,lenth2...]'''# mask num_of_sens x max_lenthmask = torch.ones(src.size(1), src.size(0)) == 1for i in range(len(lenths)):lenth = lenths[i]for j in range(lenth):mask[i][j] = False# mask = (torch.triu(torch.ones(sz, sz)) == 1).transpose(0, 1)#mask = mask.float().masked_fill(mask == 0, float('-inf')).masked_fill(mask == 1, float(0.0))return maskdef forward(self, src, mask):'''src:num_of_all_sens,max_lenth,300'''self.src_mask = masksrc = src * math.sqrt(self.ninp)src = self.pos_encoder(src)output = self.transformer_encoder(src, src_key_padding_mask=self.src_mask)output = output[0,:,:]#output = self.decoder(output)return outputclass PositionalEncoding(nn.Module):def __init__(self, d_model, dropout=0.1, max_len=5000):super(PositionalEncoding, self).__init__()self.dropout = nn.Dropout(p=dropout)pe = torch.zeros(max_len, d_model)position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1)div_term = torch.exp(torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model))pe[:, 0::2] = torch.sin(position * div_term)pe[:, 1::2] = torch.cos(position * div_term)pe = pe.unsqueeze(0).transpose(0, 1)self.register_buffer('pe', pe)def forward(self, x):x = x + self.pe[:x.size(0), :]return self.dropout(x)

第二层

#second levelclass Second_TransformerModel(nn.Module):def __init__(self, ninp=300, nhead=4, nhid=128, nlayers=6, dropout=0.5):super(Second_TransformerModel, self).__init__()from torch.nn import TransformerEncoder, TransformerEncoderLayerself.src_mask = Noneself.pos_encoder = PositionalEncoding(ninp, dropout)encoder_layers = TransformerEncoderLayer(ninp, nhead, nhid, dropout)self.transformer_encoder = TransformerEncoder(encoder_layers, nlayers)self.ninp = ninpdef _generate_square_subsequent_mask(self, src, lenths):'''padding_masksrc:num_of_sentence x batch(文章数) x 300lenths:[lenth1,lenth2...]'''# mask num_of_sens x max_lenthmask = torch.ones(src.size(1), src.size(0)) == 1for i in range(len(lenths)):lenth = lenths[i]for j in range(lenth):mask[i][j] = Falsereturn maskdef forward(self, src, mask):'''src:max_sentence_num x batch(文章数) x 300'''self.src_mask = masksrc = src * math.sqrt(self.ninp)src = self.pos_encoder(src)output = self.transformer_encoder(src, src_key_padding_mask=self.src_mask)#output = self.decoder(output)return output

最终代码

class segmentmodel(nn.Module):def __init__(self, ninp=300, nhead=4, nhid=128, nlayers=6, dropout=0.5):super(segmentmodel, self).__init__()self.first_layer = First_TransformerModel(ninp,nhead,nhid,nlayers,dropout)self.second_layer = Second_TransformerModel(ninp,nhead,nhid,nlayers,dropout)self.linear = nn.Linear(ninp,2)  def pad(self, s, max_length):s_length = s.size()[0]v = torch.tensor(s.unsqueeze(0).unsqueeze(0))padded = F.pad(v, (0, 0, 0, max_length - s_length))  # (1, 1, max_length, 300)shape = padded.size()return padded.view(shape[2], 1, shape[3])  # (max_length, 1, 300)def pad_document(self, d, max_document_length):d_length = d.size()[0]v = d.unsqueeze(0).unsqueeze(0)padded = F.pad(v, (0, 0,0, max_document_length - d_length ))  # (1, 1, max_length, 300)shape = padded.size()return padded.view(shape[2], 1, shape[3])  # (max_length, 1, 300)def forward(self, batch):batch_size = len(batch)sentences_per_doc = []all_batch_sentences = []for document in batch:all_batch_sentences.extend(document)sentences_per_doc.append(len(document))lengths = [s.size()[0] for s in all_batch_sentences]max_length = max(lengths)#logger.debug('Num sentences: %s, max sentence length: %s',# sum(sentences_per_doc), max_length)padded_sentences = [self.pad(s, max_length) for s in all_batch_sentences]big_tensor = torch.cat(padded_sentences, 1)  # (max_length, batch size, 300)mask = self.first_layer._generate_square_subsequent_mask(big_tensor,lengths).cuda()firstlayer_out = self.first_layer(src = big_tensor,mask = mask)# 句子数 x 300#padded_output  batch x 300# 将各个文章中的句子分别取出来encoded_documents =[]index = 0for sentences_count in sentences_per_doc:end_index = index + sentences_countencoded_documents.append(firstlayer_out[index : end_index, :])index = end_index#docuemnt_paddingdoc_sizes = [doc.size()[0] for doc in encoded_documents]max_doc_size = np.max(doc_sizes)padded_docs = [self.pad_document(d, max_doc_size) for d in encoded_documents]docs_tensor = torch.cat(padded_docs, 1)#docs_tensor max_doc_size x batch x 300mask = self.second_layer._generate_square_subsequent_mask(docs_tensor,doc_sizes).cuda()second_layer_out = self.second_layer(src = docs_tensor,mask = mask)#去除最后一个句子doc_outputs = []for i, doc_len in enumerate(doc_sizes):doc_outputs.append(second_layer_out[0:doc_len - 1, i, :])  # -1 to remove last predicsentence_outputs = torch.cat(doc_outputs, 0)# 句子数 x 300out = self.linear(sentence_outputs)return out

值得注意的是,这里的第一层提取的句子信息,是采用的第一层的输出的一个向量来表示的,即从 seqlenth x N x 300 中选出 seqlenth维度的第一个作为句子表示,得到Nx300的tensor。

torch.nn.Transformer解读与应用相关推荐

  1. 【PyTorch】torch.nn.Transformer解读与应用

    nn.TransformerEncoderLayer 这个类是transformer encoder的组成部分,代表encoder的一个层,而encoder就是将transformerEncoderL ...

  2. torch.nn、(二)

    参考 torch.nn.(二) - 云+社区 - 腾讯云 目录 Recurrent layers RNN LSTM GRU RNNCell LSTMCell GRUCell Transformer l ...

  3. Pytorch中 nn.Transformer的使用详解与Transformer的黑盒讲解

    文章目录 本文内容 将Transformer看成黑盒 Transformer的推理过程 Transformer的训练过程 Pytorch中的nn.Transformer nn.Transformer简 ...

  4. torch.nn.Embedding()中的padding_idx参数解读

    torch.nn.Embedding() Word Embedding 词嵌入,就是把一个词典,随机初始化映射为一个向量矩阵. 列如:有一组词典,有两个词"hello"和" ...

  5. torch.nn.functional.unfold 用法解读

    torch.nn.Unfold(kernel_size, dilation=1, padding=0, stride=1) 参数 kernel_size,滑动窗口的大小 dilation,和空洞卷积中 ...

  6. 【torch.nn.init】初始化参数方法解读

    文章目录 torch.nn.init 均匀分布 正态分布 常数分布 全1分布 全0分布 对角分布 dirac 分布 xavier_uniform 分布 xavier_normal 分布 kaiming ...

  7. PyTorch中的torch.nn.Parameter() 详解

    PyTorch中的torch.nn.Parameter() 详解 今天来聊一下PyTorch中的torch.nn.Parameter()这个函数,笔者第一次见的时候也是大概能理解函数的用途,但是具体实 ...

  8. Pytorch入门实战(5):基于nn.Transformer实现机器翻译(英译汉)

    使用Google Colab运行(open In Colab) 源码地址 文章目录 本文涉及知识点 本文内容 环境配置 数据预处理 文本分词与构造词典 Dataset and Dataloader 模 ...

  9. Transformer解读和实战

    Transformer解读和实战 背景 循环神经网络(RNN),LSTM,GRU等循环结构的神经网络已经在NLP应用任务中取得了卓越的表现,循环模型通常沿输入和输出序列的符号位置考虑计算,产生对应位置 ...

最新文章

  1. 【NLP】如何系统性的学习NLP,有三AI-NLP知识星球等你来
  2. 博士申请 | 香港浸会大学万人杰教授招收计算机视觉全奖博士生/研究助理
  3. 友盟分享快速集成--学习记录
  4. crntos7启动php命令_CentOS7设置php-fpm开机自启动
  5. java服务器崩溃的原因_请求大神帮忙分析一下服务器崩溃原因
  6. Ubuntu18.04取消VIM自动备份文件
  7. 【渝粤教育】国家开放大学2018年春季 3922T汽车运用基础 参考试题
  8. NULL 与 nullptr区别与联系
  9. Exchange2010安装配置
  10. ckplayer php,CKplayer 站外调用示例
  11. 发明专利授权:顺源科技模拟信号隔离放大及转换技术
  12. 银行不良资产收益权转让 模式大起底
  13. android 反编译 jadx,jadx gui下载 jadx(Android反编译gui工具) v0.6.1 官方版 下载-脚本之家...
  14. 每日一练(三) pointSprite(点精灵)
  15. 在Win32程序中创建OpenGL渲染环境
  16. 【Maxent】最大熵的数学原理及其在推断问题中的应用
  17. 我对测试工作的一些认识(资深测试人员总结)
  18. Wind数据个性化定制抓取
  19. 本地安全策略命令行secedit设置本地账户安全策略
  20. Ubuntu18.04安装wps office

热门文章

  1. 【王卓】数据结构与算法图(九)
  2. 电子工程师标配十款经典RF射频器件
  3. 使用jquery.fly插件实现添加购物车抛物动画
  4. Kafka完美解决:Error while executing topic command:Replication factor: 1 larger than available brokers:0
  5. Consumer HDU - 3449【dp-有依赖的背包问题】
  6. altera FPGA介紹
  7. 锐界机器人_钱江机器人/海峰机器人/锐界科技彰显“装配”技术实力
  8. [洛谷P3758][TJOI2017]可乐
  9. JS学习手册十五 事件处理
  10. 关于ros提到的那只turtle