如果你想在翻譯任務上測試一個新的體系結構,例如在自訂資料集上訓練一個新的標記,那麼處理起來會很麻煩,所以在本文中,我將介紹新增標記的預處理步驟,並介紹如何進行模型微調。
因為Huggingface Hub有很多預先訓練過的模型,可以輕鬆找到預訓練標記器。但是我們要新增一個標記可能就會有些棘手,下面我們來完整的介紹如何實現它,首先載入和預處理資料集。
我們使用WMT16資料集及其羅馬尼亞語-英語子集。 load_dataset()函數將從Huggingface下載並載入任何可用的資料集。
import datasets dataset = datasets.load_dataset("stas/wmt16-en-ro-pre-processed", cache_dir="./wmt16-en_ro")
在上圖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」維度。
標記器提供了訓練標記器所需的所有工作。它由四個基本組成部分:(但這四個部分不是所有的都是必要的)
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")
現在可以使用新的標記器了。
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中文網其他相關文章!