输入为什么有512这个长度限制?
原文:To speed up pretraing in our experiments, we pre-train the model with sequence length of 128 for 90% of the steps. Then, we train the rest 10% of the steps of sequence of 512 to learn the positional embeddings. 学习了512长度的positional embeddings,如果长于512则不存在位置信息,出错。BERT中的Positional Embedding和Transformer中的Positional Embedding实现方式并不一样。 BERT中的Positional Embedding本质上是一个可学习的参数,也就是说每个位置所对应的位置向量就类似于Token Embedding中每个词对应的词向量。如下代码所示为Positional Embedding部分的代码实现,可以发现其本质上也就是一个普通的可学习的Embedding层。
class PositionalEmbedding(nn.Module):
def __init__(self, hidden_size, max_position_embeddings=512, initializer_range=0.02):
super(PositionalEmbedding, self).__init__()
self.embedding = nn.Embedding(max_position_embeddings, hidden_size)
def forward(self, position_ids):
return self.embedding(position_ids).transpose(0, 1)
因此,除非是你自己从零开始训练一个模型,否则如果你使用的是谷歌开源的预训练模型,那么这个词表的大小将会被限制在512。 当然,我们依旧可以突破这个限制,那就是重新初始化Positional Embedding中的向量,并将前512个向量用已有的进行替换,超出部分就使用随机初始化的权重在语料上进行微调或训练。代码实现:
1 @classmethod
2 def from_pretrained(cls, config, pretrained_model_dir=None):
3 model = cls(config)
4 pretrained_model_path = os.path.join(pretrained_model_dir, "pytorch_model.bin")
5 if not os.path.exists(pretrained_model_path):
6 raise ValueError(f"<路径:{pretrained_model_path} 中的模型不存在,请仔细检查!>")
7 loaded_paras = torch.load(pretrained_model_path)
8 state_dict = deepcopy(model.state_dict())
9 loaded_paras_names = list(loaded_paras.keys())[:-8]
10 model_paras_names = list(state_dict.keys())[1:]
11 for i in range(len(loaded_paras_names)):
12 state_dict[model_paras_names[i]] = loaded_paras[loaded_paras_names[i]]
13 logging.debug(f"## 成功将参数:{loaded_paras_names[i]}赋值给{model_paras_names[i]},"
14 f"参数形状为:{state_dict[model_paras_names[i]].size()}")
15 model.load_state_dict(state_dict)
16 return model
在上述代码中,第3-10行用来载入本地的模型参数;第11-15行则是用来将载入的模型参数赋值到现有的模型。 进一步,我们只需要判断在第12行之前判断当前参数是否为positional embeding层,如果是进行替换即可,代码如下:
1 def replace_512_position(init_embedding, loaded_embedding, config):
2 logging.info(f"模型参数max_positional_embedding > 512,采用替换处理!")
3 init_embedding[:512, :] = loaded_embedding[:512, :]
4 return init_embedding
5
6 @classmethod
7 def from_pretrained(cls, config, pretrained_model_dir=None):
8
9 for i in range(len(loaded_paras_names)):
10 if "position_embeddings" in model_paras_names[i]:
11
12 if config.max_position_embeddings > 512:
13 new_embedding = replace_512_position(state_dict[model_paras_names[i]],
14 loaded_paras[loaded_paras_names[i]],
15 config)
16 state_dict[model_paras_names[i]] = new_embedding
17 else:
18 state_dict[model_paras_names[i]] = loaded_paras[loaded_paras_names[i]]
19 logging.debug(f"## 成功将参数:{loaded_paras_names[i]}赋值给{model_paras_names[i]},"
20 f"参数形状为:{state_dict[model_paras_names[i]].size()}")
21 model.load_state_dict(state_dict)
22 return model
通过上述代码,我们在载入预训练模型的同时就成功将随机初始化positional embedding中的前512个向量替换为了预训练模型中positional embedding中的参数。在这之后,剩余部分的参数可以通过下游任务来进行微调,也可以在一些语料上根据NSP和MLM任务进行训练。 Transformer中的Positional Embedding是通过公式得到的
参考
https://zhuanlan.zhihu.com/p/493424507
|