如何在 MLM 和 NSP 的新领域从头开始训练 BERT?

How to train BERT from scratch on a new domain for both MLM and NSP?

我正在尝试使用我自己的数据集和 HuggingFace 库从头开始训练 BERT 模型。我想以具有原始 BERT 模型的确切架构的方式训练模型。

在原始论文中,它指出:“BERT 在两个任务上接受训练:预测随机屏蔽标记 (MLM) 和预测两个句子是否相互跟随 (NSP)。 SCIBERT 遵循与 BERT 相同的架构,但在科学文本上进行了预训练。”

我正在尝试了解如何在上述两个任务上训练模型。目前,我将模型初始化如下:

from transformers import BertForMaskedLM
model = BertForMaskedLM(config=config)

但是,它只适用于 MLM 而不是 NSP。我怎样才能用 NSP 初始化和训练模型,或者我原来的方法就可以了?

我的假设是

  1. BertForPreTraining 初始化(对于 MLM 和 NSP),或

  2. BertForMaskedLM完成训练后, 初始化相同的模型并再次训练 BertForNextSentencePrediction(但是这种方法的计算和 资源会花费两倍...)

我不确定哪一个是正确的方法。任何见解或建议将不胜感激。

我建议执行以下操作:

  1. 首先在 MLM objective 上预训练 BERT。 HuggingFace 提供了一个脚本,专门用于在您自己的数据上在 MLM objective 上训练 BERT。你可以找到它here。正如你在run_mlm.py脚本中看到的,他们使用AutoModelForMaskedLM,你可以指定任何你想要的架构。

  2. 其次,如果想训练下一句预测任务,可以定义一个BertForPretraining模型(MLM和NSP头都在上面),然后加载来自您在步骤 1 中训练的模型的权重,然后在下一个句子预测任务中进一步对其进行预训练。

更新:显然下一句预测任务确实有助于提高 BERT 在某些 GLUE 任务上的性能。参见 BERT 作者的this talk

您可以使用 BertForPretraining TextDatasetForNextSentencePrediction DataCollatorForLanguageModelingTrainer.

的组合在 MLM 和 NSP 任务上轻松地从头开始训练 BERT

我不建议您先训练模型 MLM,然后再训练 NSP,这可能会导致灾难性的遗忘。这基本上是忘记了你从以前的培训中学到的东西。

  1. 加载您预训练的分词器。
from transformers import BertTokenizer
bert_cased_tokenizer = BertTokenizer.from_pretrained("/path/to/pre-trained/tokenizer/for/new/domain", do_lower_case=False)
  1. 使用 BertForPretraining
  2. 初始化您的模型
from transformers import BertConfig, BertForPreTraining
config = BertConfig()
model = BertForPreTraining(config)
  1. 为 NSP 任务创建数据集。 TextDatasetForNextSentencePrediction 将标记化并为句子创建标签。您的数据集应在以下 format:(或者您可以修改现有代码)

(1) One sentence per line. These should ideally be actual sentences (2) Blank lines between documents

Sentence-1 From Document-1
Sentence-2 From Document-1
Sentence-3 From Document-1
...

Sentence-1 From Document-2
Sentence-2 From Document-2
Sentence-3 From Document-2
from transformers import TextDatasetForNextSentencePrediction
dataset = TextDatasetForNextSentencePrediction(
    tokenizer=bert_cased_tokenizer,
    file_path="/path/to/your/dataset",
    block_size = 256
)
  1. 使用 DataCollatorForLanguageModeling 来屏蔽和传递从 TextDatasetForNextSentencePrediction 生成的标签。 DataCollatorForNextSentencePrediction 一直是 removed,因为它与 DataCollatorForLanguageModeling
  2. 做同样的事情
from transformers import DataCollatorForLanguageModeling

data_collator = DataCollatorForLanguageModeling(
    tokenizer=bert_cased_tokenizer, 
    mlm=True,
    mlm_probability= 0.15
)
  1. 训练并保存

from transformers import Trainer, TrainingArguments

training_args = TrainingArguments(
    output_dir= "/path/to/output/dir/for/training/arguments"
    overwrite_output_dir=True,
    num_train_epochs=2,
    per_gpu_train_batch_size= 16,
    save_steps=10_000,
    save_total_limit=2,
    prediction_loss_only=True,
)

trainer = Trainer(
    model=model,
    args=training_args,
    data_collator=data_collator,
    train_dataset=dataset,
)

trainer.train()
trainer.save_model("path/to/your/model")