首頁  >  文章  >  後端開發  >  Huggingface微調BART的程式碼範例:WMT16資料集訓練新的標記進行翻譯

Huggingface微調BART的程式碼範例:WMT16資料集訓練新的標記進行翻譯

王林
王林轉載
2023-04-10 14:41:061235瀏覽

如果你想在翻譯任務上測試一個新的體系結構,例如在自訂資料集上訓練一個新的標記,那麼處理起來會很麻煩,所以在本文中,我將介紹新增標記的預處理步驟,並介紹如何進行模型微調。

因為Huggingface Hub有很多預先訓練過的模型,可以輕鬆找到預訓練標記器。但是我們要新增一個標記可能就會有些棘手,下面我們來完整的介紹如何實現它,首先載入和預處理資料集。

載入資料集

我們使用WMT16資料集及其羅馬尼亞語-英語子集。 load_dataset()函數將從Huggingface下載並載入任何可用的資料集。

import datasets
 
 dataset = datasets.load_dataset("stas/wmt16-en-ro-pre-processed", cache_dir="./wmt16-en_ro")

Huggingface微調BART的程式碼範例:WMT16資料集訓練新的標記進行翻譯

在上圖1可以看到資料集內容。我們需要將其“壓平”,這樣可以更好的存取數據,讓後將其保存到硬碟中。

def flatten(batch):
 batch['en'] = batch['translation']['en']
 batch['ro'] = batch['translation']['ro']
 
 return batch
 
 # 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」維度。

Huggingface微調BART的程式碼範例:WMT16資料集訓練新的標記進行翻譯

標記器

標記器提供了訓練標記器所需的所有工作。它由四個基本組成部分:(但這四個部分不是所有的都是必要的)

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、特殊標記,如

3、初始詞彙量,這是每個模型啟動過程的預定義清單。

from tokenizers import normalizers, 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()。

def batch_iterator():
 batch_length = 1000
 for i in range(0, len(train), batch_length):
 yield train[i : i + batch_length]["ro"]
 
 bpe_tokenizer.train_from_iterator( batch_iterator(), length=len(train), trainer=trainer )
 
 bpe_tokenizer.save("./ro_tokenizer.json")

BART微調

現在可以使用新的標記器了。

from transformers import AutoTokenizer, 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
 
 def tokenize_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"]
 
 return input
 
 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行使用,標記器使用填充可以使所有輸入具有相同的大小。

下面就是訓練的過程:

from transformers import BartForConditionalGeneration
 from transformers import Seq2SeqTrainingArguments, 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://github.com/AlaFalaki/tutorial_notebooks/blob/main/translation/hf_bart_translation.ipynb

以上是Huggingface微調BART的程式碼範例:WMT16資料集訓練新的標記進行翻譯的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:51cto.com。如有侵權,請聯絡admin@php.cn刪除