BART 模型是用来预训练 seq-to-seq 模型的降噪主动编码器(autoencoder)。它是一个序列到序列的模型,具备对损坏文本的双向编码器和一个从左到右的自回归解码器,所以它能够完满的执行翻译工作。
如果你想在翻译工作上测试一个新的体系结构,比方在自定义数据集上训练一个新的标记,那么解决起来会很麻烦,所以在本文中,我将介绍增加新标记的预处理步骤,并介绍如何进行模型微调。
因为 Huggingface Hub 有很多预训练过的模型,能够很容易地找到预训练标记器。然而咱们要增加一个标记可能就会有些辣手,上面咱们来残缺的介绍如何实现它,首先加载和预处理数据集。
加载数据集
咱们应用 WMT16 数据集及其罗马尼亚语 - 英语子集。load_dataset()函数将从 Huggingface 下载并加载任何可用的数据集。
importdatasets
dataset=datasets.load_dataset("stas/wmt16-en-ro-pre-processed", cache_dir="./wmt16-en_ro")
在上图 1 中能够看到数据集内容。咱们须要将其“压平”,这样能够更好的拜访数据,让后将其保留到硬盘中。
defflatten(batch):
batch['en'] =batch['translation']['en']
batch['ro'] =batch['translation']['ro']
returnbatch
# Map the 'flatten' function
train=dataset['train'].map(flatten)
test=dataset['test'].map(flatten)
validation=dataset['validation'].map(flatten)
# Save to disk
train.save_to_disk("./dataset/train")
test.save_to_disk("./dataset/test")
validation.save_to_disk("./dataset/validation")
下图 2 能够看到,曾经从数据集中删除了“translation”维度。
标记器
标记器提供了训练标记器所需的所有工作。它由四个根本组成部分:(但这四个局部不是所有的都是必要的)
Models: 标记器将如何合成每个单词。例如,给定单词“playing”:i) BPE 模型将其合成为“play”+“ing”两个标记,ii) WordLevel 将其视为一个标记。
Normalizers: 须要在文本上产生的一些转换。有一些过滤器能够更改 Unicode、小写字母或删除内容。
Pre-Tokenizers: 为操作文本提供更大灵活性解决的函数。例如,如何解决数字。数字 100 应该被认为是“100”还是“1”、“0”、“0”?
Post-Processors: 后处理具体情况取决于预训练模型的抉择。例如,将 [BOS](句首)或 [EOS](句尾)标记增加到 BERT 输出。
上面的代码应用 BPE 模型、小写 Normalizers 和空白 Pre-Tokenizers。而后用默认值初始化训练器对象,次要包含
1、词汇量大小应用 50265 以与 BART 的英语标记器统一
2、非凡标记,如 <s> 和 <pad>,
3、初始词汇量,这是每个模型启动过程的预约义列表。
fromtokenizersimportnormalizers, pre_tokenizers, Tokenizer, models, trainers
# Build a tokenizer
bpe_tokenizer=Tokenizer(models.BPE())
bpe_tokenizer.normalizer=normalizers.Lowercase()
bpe_tokenizer.pre_tokenizer=pre_tokenizers.Whitespace()
trainer=trainers.BpeTrainer(
vocab_size=50265,
special_tokens=["<s>", "<pad>", "</s>", "<unk>", "<mask>"],
initial_alphabet=pre_tokenizers.ByteLevel.alphabet(),)
应用 Huggingface 的最初一步是连贯 Trainer 和 BPE 模型,并传递数据集。依据数据的起源,能够应用不同的训练函数。咱们将应用 train_from_iterator()。
defbatch_iterator():
batch_length=1000
foriinrange(0, len(train), batch_length):
yieldtrain[i : i+batch_length]["ro"]
bpe_tokenizer.train_from_iterator(batch_iterator(), length=len(train), trainer=trainer )
bpe_tokenizer.save("./ro_tokenizer.json")
BART 微调
当初能够应用应用新的标记器了。
fromtransformersimportAutoTokenizer, PreTrainedTokenizerFast
en_tokenizer=AutoTokenizer.from_pretrained("facebook/bart-base");
ro_tokenizer=PreTrainedTokenizerFast.from_pretrained("./ro_tokenizer.json");
ro_tokenizer.pad_token=en_tokenizer.pad_token
deftokenize_dataset(sample):
input=en_tokenizer(sample['en'], padding='max_length', max_length=120, truncation=True)
label=ro_tokenizer(sample['ro'], padding='max_length', max_length=120, truncation=True)
input["decoder_input_ids"] =label["input_ids"]
input["decoder_attention_mask"] =label["attention_mask"]
input["labels"] =label["input_ids"]
returninput
train_tokenized=train.map(tokenize_dataset, batched=True)
test_tokenized=test.map(tokenize_dataset, batched=True)
validation_tokenized=validation.map(tokenize_dataset, batched=True)
下面代码的第 5 行,为罗马尼亚语的标记器设置填充标记是十分必要的。因为它将在第 9 行应用,标记器应用填充能够使所有输出都具备雷同的大小。
上面就是训练的过程:
fromtransformersimportBartForConditionalGeneration
fromtransformersimportSeq2SeqTrainingArguments, Seq2SeqTrainer
model=BartForConditionalGeneration.from_pretrained("facebook/bart-base")
training_args=Seq2SeqTrainingArguments(
output_dir="./",
evaluation_strategy="steps",
per_device_train_batch_size=2,
per_device_eval_batch_size=2,
predict_with_generate=True,
logging_steps=2, # set to 1000 for full training
save_steps=64, # set to 500 for full training
eval_steps=64, # set to 8000 for full training
warmup_steps=1, # set to 2000 for full training
max_steps=128, # delete for full training
overwrite_output_dir=True,
save_total_limit=3,
fp16=False, # True if GPU
)
trainer=Seq2SeqTrainer(
model=model,
args=training_args,
train_dataset=train_tokenized,
eval_dataset=validation_tokenized,
)
trainer.train()
过程也非常简单,加载 bart 根底模型(第 4 行),设置训练参数(第 6 行),应用 Trainer 对象绑定所有内容(第 22 行),并启动流程(第 29 行)。上述超参数都是测试目标,所以如果要失去最好的后果还须要进行超参数的设置,咱们应用这些参数是能够运行的。
推理
推理过程也很简略,加载通过微调的模型并应用 generate()办法进行转换就能够了,然而须要留神的是对源 (En) 和指标 (RO) 序列应用适当的分词器。
总结
尽管在应用自然语言解决 (NLP) 时,标记化仿佛是一个基本操作,但它是一个不应漠视的关键步骤。HuggingFace 的呈现能够不便的让咱们应用,这使得咱们很容易遗记标记化的基本原理,而仅仅依赖事后训练好的模型。然而当咱们心愿本人训练新模型时,理解标记化过程及其对上游工作的影响是必不可少的,所以相熟和把握这个根本的操作是十分有必要的。
本文代码:https://avoid.overfit.cn/post/6a533780b5d842a28245c81bf46fac63
作者:Ala Alam Falaki