Init
Browse files- prepare.py +63 -0
- preprocess.py +73 -0
- run_cat.py +52 -0
- run_mlm_local.py +130 -0
prepare.py
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
#
|
| 3 |
+
# 1. [Prepare the dataset](#1-prepare-the-dataset)
|
| 4 |
+
# 2. [Train a Tokenizer](#2-train-a-tokenizer)
|
| 5 |
+
# 3. [Preprocess the dataset](#3-preprocess-the-dataset)
|
| 6 |
+
# 4. [Pre-train BERT on Habana Gaudi](#4-pre-train-bert-on-habana-gaudi)
|
| 7 |
+
#
|
| 8 |
+
# _Note: Step 1 to 3 can/should be run on a different instance size those are CPU intensive tasks._
|
| 9 |
+
|
| 10 |
+
# %%
|
| 11 |
+
# ## 1. Prepare the dataset
|
| 12 |
+
# Log into the [Hugging Face Hub](https://huggingface.co/models) to push our dataset, tokenizer, model artifacts, logs and metrics during training and afterwards to the hub.
|
| 13 |
+
|
| 14 |
+
from huggingface_hub import HfApi
|
| 15 |
+
|
| 16 |
+
user_id = HfApi().whoami()["name"]
|
| 17 |
+
print(f"user id '{user_id}' will be used during the example")
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
from datasets import concatenate_datasets, load_dataset
|
| 21 |
+
# The [original BERT](https://arxiv.org/abs/1810.04805) was pretrained on [Wikipedia](https://huggingface.co/datasets/wikipedia) and [BookCorpus](https://huggingface.co/datasets/bookcorpus) dataset. Both datasets are available on the [Hugging Face Hub](https://huggingface.co/datasets) and can be loaded with `datasets`.
|
| 22 |
+
#
|
| 23 |
+
# _Note: For wikipedia we will use the `20220301`, which is different to the original split._
|
| 24 |
+
#
|
| 25 |
+
# As a first step are we loading the dataset and merging them together to create on big dataset.
|
| 26 |
+
bookcorpus = load_dataset("bookcorpus", split="train")
|
| 27 |
+
wiki = load_dataset("wikipedia", "20220301.en", split="train")
|
| 28 |
+
wiki = wiki.remove_columns([col for col in wiki.column_names if col != "text"]) # only keep the 'text' column
|
| 29 |
+
|
| 30 |
+
assert bookcorpus.features.type == wiki.features.type
|
| 31 |
+
raw_datasets = concatenate_datasets([bookcorpus, wiki])
|
| 32 |
+
print(raw_datasets)
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
# %% [markdown]
|
| 36 |
+
# > We are not going to do some advanced dataset preparation, like de-duplication, filtering or any other pre-processing. If you are planning to apply this notebook to train your own BERT model from scratch I highly recommend to including those data preparation steps into your workflow. This will help you improve your Language Model.
|
| 37 |
+
|
| 38 |
+
# ## 2. Train a Tokenizer
|
| 39 |
+
#
|
| 40 |
+
# To be able to train our model we need to convert our text into a tokenized format. Most Transformer models are coming with a pre-trained tokenizer, but since we are pre-training our model from scratch we also need to train a Tokenizer on our data. We can train a tokenizer on our data with `transformers` and the `BertTokenizerFast` class.
|
| 41 |
+
#
|
| 42 |
+
# More information about training a new tokenizer can be found in our [Hugging Face Course](https://huggingface.co/course/chapter6/2?fw=pt).
|
| 43 |
+
from tqdm import tqdm
|
| 44 |
+
from transformers import BertTokenizerFast
|
| 45 |
+
|
| 46 |
+
# repositor id for saving the tokenizer
|
| 47 |
+
tokenizer_id="chaoyan/bert-base-uncased-cat"
|
| 48 |
+
|
| 49 |
+
# create a python generator to dynamically load the data
|
| 50 |
+
def batch_iterator(batch_size=10000):
|
| 51 |
+
for i in tqdm(range(0, len(raw_datasets), batch_size)):
|
| 52 |
+
yield raw_datasets[i : i + batch_size]["text"]
|
| 53 |
+
|
| 54 |
+
tokenizer = BertTokenizerFast.from_pretrained("bert-base-uncased")
|
| 55 |
+
bert_tokenizer = tokenizer.train_new_from_iterator(text_iterator=batch_iterator(), vocab_size=32_000)
|
| 56 |
+
|
| 57 |
+
print(tokenizer)
|
| 58 |
+
|
| 59 |
+
bert_tokenizer.save_pretrained("cat_tokenizer")
|
| 60 |
+
|
| 61 |
+
# We push the tokenizer to [Hugging Face Hub](https://huggingface.co/models) for later training our model.
|
| 62 |
+
bert_tokenizer.push_to_hub(tokenizer_id)
|
| 63 |
+
|
preprocess.py
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from datasets import concatenate_datasets, load_dataset
|
| 2 |
+
# The [original BERT](https://arxiv.org/abs/1810.04805) was pretrained on [Wikipedia](https://huggingface.co/datasets/wikipedia) and [BookCorpus](https://huggingface.co/datasets/bookcorpus) dataset. Both datasets are available on the [Hugging Face Hub](https://huggingface.co/datasets) and can be loaded with `datasets`.
|
| 3 |
+
#
|
| 4 |
+
# _Note: For wikipedia we will use the `20220301`, which is different to the original split._
|
| 5 |
+
#
|
| 6 |
+
# As a first step are we loading the dataset and merging them together to create on big dataset.
|
| 7 |
+
bookcorpus = load_dataset("bookcorpus", split="train")
|
| 8 |
+
wiki = load_dataset("wikipedia", "20220301.en", split="train")
|
| 9 |
+
wiki = wiki.remove_columns([col for col in wiki.column_names if col != "text"]) # only keep the 'text' column
|
| 10 |
+
|
| 11 |
+
assert bookcorpus.features.type == wiki.features.type
|
| 12 |
+
raw_datasets = concatenate_datasets([bookcorpus, wiki])
|
| 13 |
+
print(raw_datasets)
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
# %%
|
| 17 |
+
# ## 3. Preprocess the dataset
|
| 18 |
+
#
|
| 19 |
+
# Before we can get started with training our model, the last step is to pre-process/tokenize our dataset. We will use our trained tokenizer to tokenize our dataset and then push it to hub to load it easily later in our training. The tokenization process is also kept pretty simple, if documents are longer than `512` tokens those are truncated and not split into several documents.
|
| 20 |
+
|
| 21 |
+
from transformers import AutoTokenizer
|
| 22 |
+
import multiprocessing
|
| 23 |
+
|
| 24 |
+
# load tokenizer (from local or remote hub)
|
| 25 |
+
# tokenizer = AutoTokenizer.from_pretrained(f"{user_id}/{tokenizer_id}")
|
| 26 |
+
tokenizer = AutoTokenizer.from_pretrained("cat_tokenizer")
|
| 27 |
+
num_proc = min(multiprocessing.cpu_count(), 8)
|
| 28 |
+
print(f"The max length for the tokenizer is: {tokenizer.model_max_length}")
|
| 29 |
+
|
| 30 |
+
def group_texts(examples):
|
| 31 |
+
tokenized_inputs = tokenizer(
|
| 32 |
+
examples["text"], return_special_tokens_mask=True, truncation=True, max_length=tokenizer.model_max_length
|
| 33 |
+
)
|
| 34 |
+
return tokenized_inputs
|
| 35 |
+
|
| 36 |
+
# preprocess dataset
|
| 37 |
+
tokenized_datasets = raw_datasets.map(group_texts, batched=True, remove_columns=["text"], num_proc=num_proc)
|
| 38 |
+
print(tokenized_datasets.features)
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
# As data processing function will we concatenate all texts from our dataset and generate chunks of `tokenizer.model_max_length` (512).
|
| 42 |
+
from itertools import chain
|
| 43 |
+
|
| 44 |
+
# Main data processing function that will concatenate all texts from our dataset and generate chunks of
|
| 45 |
+
# max_seq_length.
|
| 46 |
+
def group_texts(examples):
|
| 47 |
+
# Concatenate all texts.
|
| 48 |
+
concatenated_examples = {k: list(chain(*examples[k])) for k in examples.keys()}
|
| 49 |
+
total_length = len(concatenated_examples[list(examples.keys())[0]])
|
| 50 |
+
# We drop the small remainder, we could add padding if the model supported it instead of this drop, you can
|
| 51 |
+
# customize this part to your needs.
|
| 52 |
+
if total_length >= tokenizer.model_max_length:
|
| 53 |
+
total_length = (total_length // tokenizer.model_max_length) * tokenizer.model_max_length
|
| 54 |
+
# Split by chunks of max_len.
|
| 55 |
+
result = {
|
| 56 |
+
k: [t[i : i + tokenizer.model_max_length] for i in range(0, total_length, tokenizer.model_max_length)]
|
| 57 |
+
for k, t in concatenated_examples.items()
|
| 58 |
+
}
|
| 59 |
+
return result
|
| 60 |
+
|
| 61 |
+
tokenized_datasets = tokenized_datasets.map(group_texts, batched=True, num_proc=num_proc)
|
| 62 |
+
# shuffle dataset
|
| 63 |
+
tokenized_datasets = tokenized_datasets.shuffle(seed=34)
|
| 64 |
+
|
| 65 |
+
print(tokenized_datasets)
|
| 66 |
+
print(f"the dataset contains in total {len(tokenized_datasets)*tokenizer.model_max_length} tokens")
|
| 67 |
+
# the dataset contains in total 3417216000 tokens
|
| 68 |
+
# tokenized_datasets.to_csv('processed_bert_dataset.csv')
|
| 69 |
+
|
| 70 |
+
user_id = 'chaoyan'
|
| 71 |
+
# push dataset to hugging face
|
| 72 |
+
dataset_id=f"{user_id}/processed_bert_dataset"
|
| 73 |
+
tokenized_datasets.push_to_hub(dataset_id)
|
run_cat.py
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
# %%
|
| 3 |
+
# ## 4. Pre-train BERT on processed dataset
|
| 4 |
+
|
| 5 |
+
import os
|
| 6 |
+
from huggingface_hub import HfFolder
|
| 7 |
+
|
| 8 |
+
# hyperparameters
|
| 9 |
+
hyperparameters = {
|
| 10 |
+
"model_config_id": "bert-base-uncased",
|
| 11 |
+
"dataset_id": "chaoyan/processed_bert_dataset",
|
| 12 |
+
"tokenizer_id": "cat_tokenizer",
|
| 13 |
+
"repository_id": "bert-base-uncased-cat",
|
| 14 |
+
"hf_hub_token": HfFolder.get_token(), # need to be login in with `huggingface-cli login`
|
| 15 |
+
"max_steps": 100_000,
|
| 16 |
+
"per_device_train_batch_size": 16,
|
| 17 |
+
"learning_rate": 5e-5,
|
| 18 |
+
}
|
| 19 |
+
hyperparameters_string = " ".join(f"--{key} {value}" for key, value in hyperparameters.items())
|
| 20 |
+
|
| 21 |
+
cmd_str = f"python3 run_mlm_local.py {hyperparameters_string}"
|
| 22 |
+
os.system(cmd_str)
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
# %% [markdown]
|
| 26 |
+
# 
|
| 27 |
+
# _This [experiment](https://huggingface.co/philschmid/bert-base-uncased-2022-habana-test-6) ran for 60k steps_
|
| 28 |
+
#
|
| 29 |
+
# In our `hyperparameters` we defined a `max_steps` property, which limited the pre-training to only `100_000` steps. The `100_000` steps with a global batch size of `256` took around 12,5 hour.
|
| 30 |
+
#
|
| 31 |
+
# BERT was originial pre-trained on [1 Million Steps](https://arxiv.org/pdf/1810.04805.pdf) with a global batch size of `256`:
|
| 32 |
+
# > We train with batch size of 256 sequences (256 sequences * 512 tokens = 128,000 tokens/batch) for 1,000,000 steps, which is approximately 40 epochs over the 3.3 billion word corpus.
|
| 33 |
+
#
|
| 34 |
+
# Meaning if we want to do a full pre-training it would take around 125h hours (12,5 hour * 10) and would cost us around ~$1,650 using Habana Gaudi on AWS, which is extermely cheap.
|
| 35 |
+
#
|
| 36 |
+
# For comparison the DeepSpeed Team, who holds the record for the [fastest BERT-pretraining](https://www.deepspeed.ai/tutorials/bert-pretraining/) [reported](https://www.deepspeed.ai/tutorials/bert-pretraining/) that pre-training BERT on 1 [DGX-2](https://www.nvidia.com/en-us/data-center/dgx-2/) (powered by 16 NVIDIA V100 GPUs with 32GB of memory each) takes around 33,25 hours.
|
| 37 |
+
#
|
| 38 |
+
# To be able to compare the cost we can use the [p3dn.24xlarge](https://aws.amazon.com/de/ec2/instance-types/p3/) as reference, which comes with 8x NVIDIA V100 32GB GPUs and costs ~31,22$/h. We would need two of these instances to have the same "setup" as the one DeepSpeed reported, for now we are ignoring any overhead created to the multi-node setup (I/O, Network etc.).
|
| 39 |
+
# This would bring the cost of the DeepSpeed GPU based training on AWS to around ~$2,075, which is 25% more than what Habana Gaudi currently delivers.
|
| 40 |
+
# _Something to note here is that using [DeepSpeed](https://www.deepspeed.ai/tutorials/bert-pretraining/#deepspeed-single-gpu-throughput-results) in general improves the performance by a factor of ~2._
|
| 41 |
+
#
|
| 42 |
+
# We are looking forward on re-doing the experiment once the [Gaudi DeepSpeed integration](https://docs.habana.ai/en/latest/PyTorch/DeepSpeed/DeepSpeed_User_Guide.html#deepspeed-configs) is more widely available.
|
| 43 |
+
#
|
| 44 |
+
#
|
| 45 |
+
# ## Conlusion
|
| 46 |
+
#
|
| 47 |
+
# That's it for this tutorial. Now you know the basics on how to pre-train BERT from scratch using Hugging Face Transformers and Habana Gaudi. You also saw how easy it is to migrate from the `Trainer` to the `GaudiTrainer`.
|
| 48 |
+
#
|
| 49 |
+
# We compared our implementation with the [fastest BERT-pretraining](https://www.deepspeed.ai/tutorials/bert-pretraining/) results and saw that Habana Gaudi still delivers a 25% cost reduction and allows us to pre-train BERT for ~$1,650.
|
| 50 |
+
#
|
| 51 |
+
# Those results are incredible, since it will allow companies to adapt their pre-trained models to their language and domain to [improve accuracy up to 10%](https://huggingface.co/pile-of-law/legalbert-large-1.7M-1#evaluation-results) compared to the general BERT models.
|
| 52 |
+
#
|
run_mlm_local.py
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import logging
|
| 3 |
+
import sys
|
| 4 |
+
from dataclasses import dataclass, field
|
| 5 |
+
from typing import Optional
|
| 6 |
+
|
| 7 |
+
from transformers import (
|
| 8 |
+
HfArgumentParser,
|
| 9 |
+
AutoModelForMaskedLM,
|
| 10 |
+
AutoTokenizer,
|
| 11 |
+
set_seed,
|
| 12 |
+
AutoConfig,
|
| 13 |
+
DataCollatorForLanguageModeling,
|
| 14 |
+
)
|
| 15 |
+
|
| 16 |
+
from transformers import Trainer, TrainingArguments
|
| 17 |
+
from datasets import load_dataset
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
logging.basicConfig(
|
| 21 |
+
format="%(asctime)s - %(levelname)s - %(name)s - %(message)s",
|
| 22 |
+
datefmt="%m/%d/%Y %H:%M:%S",
|
| 23 |
+
handlers=[logging.StreamHandler(sys.stdout)],
|
| 24 |
+
level=logging.INFO,
|
| 25 |
+
)
|
| 26 |
+
logger = logging.getLogger(__name__)
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
@dataclass
|
| 30 |
+
class ScriptArguments:
|
| 31 |
+
"""
|
| 32 |
+
Arguments which aren't included in the TrainingArguments
|
| 33 |
+
"""
|
| 34 |
+
|
| 35 |
+
dataset_id: str = field(
|
| 36 |
+
default=None, metadata={"help": "The repository id of the dataset to use (via the datasets library)."}
|
| 37 |
+
)
|
| 38 |
+
tokenizer_id: str = field(
|
| 39 |
+
default=None, metadata={"help": "The repository id of the tokenizer to use (via AutoTokenizer)."}
|
| 40 |
+
)
|
| 41 |
+
repository_id: str = field(
|
| 42 |
+
default=None,
|
| 43 |
+
metadata={"help": "The repository id where the model will be saved or loaded from for futher pre-training."},
|
| 44 |
+
)
|
| 45 |
+
hf_hub_token: str = field(
|
| 46 |
+
default=False,
|
| 47 |
+
metadata={"help": "The Token used to push models, metrics and logs to the Hub."},
|
| 48 |
+
)
|
| 49 |
+
model_config_id: Optional[str] = field(
|
| 50 |
+
default="bert-base-uncased", metadata={"help": "Pretrained config name or path if not the same as model_name"}
|
| 51 |
+
)
|
| 52 |
+
per_device_train_batch_size: Optional[int] = field(
|
| 53 |
+
default=16,
|
| 54 |
+
metadata={"help": "The Batch Size per HPU used during training"},
|
| 55 |
+
)
|
| 56 |
+
max_steps: Optional[int] = field(
|
| 57 |
+
default=1_000_000,
|
| 58 |
+
metadata={"help": "The Number of Training steps to perform."},
|
| 59 |
+
)
|
| 60 |
+
learning_rate: Optional[float] = field(default=1e-4, metadata={"help": "Learning Rate for the training"})
|
| 61 |
+
mlm_probability: Optional[float] = field(
|
| 62 |
+
default=0.15, metadata={"help": "Ratio of tokens to mask for masked language modeling loss"}
|
| 63 |
+
)
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
def run_mlm():
|
| 67 |
+
# Parse arguments
|
| 68 |
+
parser = HfArgumentParser(ScriptArguments)
|
| 69 |
+
script_args = parser.parse_args_into_dataclasses()[0]
|
| 70 |
+
logger.info(f"Script parameters {script_args}")
|
| 71 |
+
|
| 72 |
+
# set seed for reproducibility
|
| 73 |
+
seed = 34
|
| 74 |
+
set_seed(seed)
|
| 75 |
+
|
| 76 |
+
# load processed dataset
|
| 77 |
+
train_dataset = load_dataset(script_args.dataset_id, split="train")
|
| 78 |
+
# load trained tokenizer
|
| 79 |
+
tokenizer = AutoTokenizer.from_pretrained(script_args.tokenizer_id, use_auth_token=script_args.hf_hub_token)
|
| 80 |
+
|
| 81 |
+
# load model from config (for training from scratch)
|
| 82 |
+
logger.info("Training new model from scratch")
|
| 83 |
+
config = AutoConfig.from_pretrained(script_args.model_config_id)
|
| 84 |
+
model = AutoModelForMaskedLM.from_config(config)
|
| 85 |
+
|
| 86 |
+
logger.info(f"Resizing token embedding to {len(tokenizer)}")
|
| 87 |
+
model.resize_token_embeddings(len(tokenizer))
|
| 88 |
+
|
| 89 |
+
# This one will take care of randomly masking the tokens.
|
| 90 |
+
data_collator = DataCollatorForLanguageModeling(
|
| 91 |
+
tokenizer=tokenizer, mlm_probability=script_args.mlm_probability, pad_to_multiple_of=8
|
| 92 |
+
)
|
| 93 |
+
|
| 94 |
+
# define our hyperparameters
|
| 95 |
+
training_args = TrainingArguments(
|
| 96 |
+
output_dir=script_args.repository_id,
|
| 97 |
+
per_device_train_batch_size=script_args.per_device_train_batch_size,
|
| 98 |
+
learning_rate=script_args.learning_rate,
|
| 99 |
+
seed=seed,
|
| 100 |
+
max_steps=script_args.max_steps,
|
| 101 |
+
# logging & evaluation strategies
|
| 102 |
+
logging_dir=f"{script_args.repository_id}/logs",
|
| 103 |
+
logging_strategy="steps",
|
| 104 |
+
logging_steps=100,
|
| 105 |
+
save_strategy="steps",
|
| 106 |
+
save_steps=5_000,
|
| 107 |
+
save_total_limit=2,
|
| 108 |
+
report_to="tensorboard",
|
| 109 |
+
# push to hub parameters
|
| 110 |
+
# hub_strategy="every_save",
|
| 111 |
+
# hub_model_id=script_args.repository_id,
|
| 112 |
+
# pretraining
|
| 113 |
+
ddp_find_unused_parameters=True,
|
| 114 |
+
# throughput_warmup_steps=2, # !!! ?
|
| 115 |
+
)
|
| 116 |
+
|
| 117 |
+
# Initialize our Trainer
|
| 118 |
+
trainer = Trainer(
|
| 119 |
+
args=training_args,
|
| 120 |
+
model=model,
|
| 121 |
+
train_dataset=train_dataset,
|
| 122 |
+
tokenizer=tokenizer,
|
| 123 |
+
data_collator=data_collator,
|
| 124 |
+
)
|
| 125 |
+
# train the model
|
| 126 |
+
trainer.train()
|
| 127 |
+
|
| 128 |
+
|
| 129 |
+
if __name__ == "__main__":
|
| 130 |
+
run_mlm()
|