携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第14天,点击查看活动详情
导语
T5模型是由Colin Raffel等谷歌科学家在论文 Exploring the Limits of Transfer Learning with a Unified Text-to-Text Transformer中提出的。该模型将几乎所有主流的NLP任务全部建模为Sequence2sequence的方式,并借助谷歌强大的算力支持,在众多NLP任务上取得了SOTA的表现。最近在学习T5预训练的一些内容,特此记录。
简介
T5是一个典型的Transformer架构的模型,由Encoder和Decoder两部分组成。由于T5将所有的任务全部统一成为了seq2seq的方式,所以其预训练也是通过将遮住的部分进行序列输出预测的方式进行。
举个例子,我们都知道BERT模型在预训练时使用一个特殊的token [MASK]用来遮住一部分的输入token,让模型在输出时预测这些被遮住的[MASK]具体是哪一个token。
在BERT时代,一个[MASK]就代表一个被遮住的token,需要预测。后来,许多工作如SpanBERT表名,不一定每次只遮住一个token,而是可以遮住连续的若干个token,让模型自己去猜到底遮住了几个token,并且要猜出到底是那几个token。这样一来,预训练的难度提升了,模型通过这种预训练所获得的能力也大大增加。
在T5中,不同于BERT中的这个[MASK],T5一共设置了最多100个专门用来遮盖的token,并给它们起了一个名字叫做”sentinel token”。它们在对应的T5Tokenizer中分别表示为:
<extra_id_0>, <extra_id_1>, ……, <extra_id_99>
T5同样使用遮盖一段token的方式。
代码示例
例如,以Huggingface Transformers文档上的代码作为示范,我们对句子”the cute dog walks in the park” 中掩盖”cute dog”和”the”应按如下方式处理:
from transformers import T5ForConditionalGeneration, T5Tokenizer
model = T5ForConditionalGeneration.from_pretrained("t5-small")
tokenizer = T5Tokenizer.from_pretrained("t5-small")
input_ids = tokenizer('The <extra_id_0> walks in <extra_id_1> park', return_tensors='pt').input_ids
labels = tokenizer('<extra_id_0> cute dog <extra_id_1> the <extra_id_2>', return_tensors='pt').input_ids
# the forward function automatically creates the correct decoder_input_ids
loss = model(input_ids=input_ids, labels=labels).loss
这里,<extra_id_0>对应于cute dog,即遮盖了2个token;<extra_id_1>对应于the,遮盖了1个token。在模型预测时,它的taget输出是刚好对应于input的对偶形式(即输入中的词组对应于输出里面的<extra_id>,输入中的<extra_id>对应于输出里面的被遮住的词(组))。
通过这种方式,可以将T5的预训练和训练流程全部统一,即无监督的预训练使用<extra_id>,有监督的训练则不会使用这些<extra_id>,也即sentinel token。
总结
本篇博客简要介绍了T5中的sentinel token以及其在无监督的预处理任务的中的使用示例。由于T5将所有任务全部统一到了Sequence2Sequence上,所以这些sentinel token就被用来区分是无监督的预训练任务还是有监督的下游任务。