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