有关于Transformer 的max_seq_length (max_source_length)

Transformer 的最大输入长度,即max_seq_length / max_source_length是一个非常值得注意的参数。

Transformer的encoder大多是Auto-encoder的结构,不同于Auto-regressive encode,由于auto-encoder缺乏时序序列的位置信息,因此其需要对输入的每个token的position进行编码。

而position的编码方式大致为两种:1).基于Embedding 2).非Embedding

1. Embedding编码

最常见的position编码方式自然就是绝对位置嵌入编码(i.e., absolute positional embeddings)。像BERT、Roberta、BART这种都是用的position embedding。也就是用每个token的index,去从embedding中取向量。

但是这也带来了一个问题,position embedding的长度是有限的,输入的tokens如果超出这个长度,就会有index error,这也是为什么会有max_seq_length这个参数,将过长的输入部分切掉。

所以,如果模型是用position embedding编码位置信息的,则必须传入正确的max_seq_length长度(可以利用tokenizer的truncation属性,指定模型config里面的max_seq_length)。

否则,一旦输入超出了这个最大长度,会报index error:
在这里插入图片描述

2. 非Embedding编码

而像XLNet、T5这种模型的位置编码,则不是利用这种传统的embedding式(XLNet用的shuffle,T5用的相对位置编码),因此就不会有输入长度的限制

尽管huggingface的接口都提供了max_source_length这个参数选项,其值默认设定为模型预训练时使用的max_seq_length,可如果实际传入长度大于该值的input,也并不会有任何报错

但是更大的输入长度,自然会带来更重的计算负担

在这里插入图片描述

更重要的是,更长的输入也并不一定能带来更好的性能(具体看做的任务),因为这与模型预训练时存在着差别(如下图所述):
在这里插入图片描述

笔者在使用T5-base的时候,也尝试过将默认的max_seq_length==512增大为1024,使用更长的input,但并未发现存在明显性能提升的现象,甚至还会略微损害性能(注:笔者使用的数据集存在大量的输入长度超过512的样本,因此排除max_seq_length不生效的情况)。

当然,这个结论是比较主观和局限的,可能某些任务使用更大的max_seq_length去进行fine-tune效果会更好。


参考

### 使用 PyTorch 实现 Transformer 模型 #### 创建 Transformer 类 为了构建一个完整的 Transformer 模型,需要定义多个组件并将其组合在一起。以下是基于给定信息的一个简化版本的 `Transformer` 类实现: ```python import torch import torch.nn as nn from torch import Tensor import math class PositionalEncoding(nn.Module): def __init__(self, d_model: int, dropout: float = 0.1, max_len: int = 5000): super().__init__() self.dropout = nn.Dropout(p=dropout) position = torch.arange(max_len).unsqueeze(1) div_term = torch.exp(torch.arange(0, d_model, 2) * (-math.log(10000.0) / d_model)) pe = torch.zeros(max_len, 1, d_model) pe[:, 0, 0::2] = torch.sin(position * div_term) pe[:, 0, 1::2] = torch.cos(position * div_term) self.register_buffer('pe', pe) def forward(self, x: Tensor) -> Tensor: """ Args: x: Tensor, shape [seq_len, batch_size, embedding_dim] """ x = x + self.pe[:x.size(0)] return self.dropout(x) class TransformerModel(nn.Module): def __init__(self, src_vocab_size: int, tgt_vocab_size: int, d_model: int, nhead: int, num_encoder_layers: int, num_decoder_layers: int, dim_feedforward: int, max_seq_length: int, dropout: float = 0.1): super().__init__() self.src_embedding = nn.Embedding(src_vocab_size, d_model)[^3] self.tgt_embedding = nn.Embedding(tgt_vocab_size, d_model) self.positional_encoding = PositionalEncoding(d_model=d_model, dropout=dropout, max_len=max_seq_length)[^3] encoder_layer = nn.TransformerEncoderLayer( d_model=d_model, nhead=nhead, dim_feedforward=dim_feedforward, dropout=dropout ) decoder_layer = nn.TransformerDecoderLayer( d_model=d_model, nhead=nhead, dim_feedforward=dim_feedforward, dropout=dropout ) self.transformer_encoder = nn.TransformerEncoder(encoder_layer, num_layers=num_encoder_layers)[^3] self.transformer_decoder = nn.TransformerDecoder(decoder_layer, num_layers=num_decoder_layers) self.fc_out = nn.Linear(d_model, tgt_vocab_size)[^3] def forward(self, src: Tensor, tgt: Tensor, src_mask: Tensor=None, tgt_mask: Tensor=None, memory_mask: Tensor=None, src_key_padding_mask: Tensor=None, tgt_key_padding_mask: Tensor=None, memory_key_padding_mask: Tensor=None) -> Tensor: src_emb = self.positional_encoding(self.src_embedding(src)) # Add positional encoding to source embeddings. tgt_emb = self.positional_encoding(self.tgt_embedding(tgt)) # Add positional encoding to target embeddings. encoded_src = self.transformer_encoder(src_emb, mask=src_mask, src_key_padding_mask=src_key_padding_mask) decoded_tgt = self.transformer_decoder(tgt=tgt_emb, memory=encoded_src, tgt_mask=tgt_mask, memory_mask=memory_mask, tgt_key_padding_mask=tgt_key_padding_mask, memory_key_padding_mask=memory_key_padding_mask) output = self.fc_out(decoded_tgt) return output ``` 此代码片段展示了如何利用 PyTorch 的内置模块来搭建一个基本的 Transformer 架构。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值