使用 Trainer API 预训练 BERT 模型时出现 ValueError

Posted

技术标签:

【中文标题】使用 Trainer API 预训练 BERT 模型时出现 ValueError【英文标题】:ValueError when pre-training BERT model using Trainer API 【发布时间】:2022-01-12 17:03:08 【问题描述】:

我正在尝试使用 transformers 库中的 Trainer API 微调/预训练现有的 BERT 模型以进行情绪分析。我的训练数据集如下所示:

Text                             Sentiment
This was good place                  1
This was bad place                   0

我的目标是能够将情绪分类为正面/负面。这是我的代码:

from datasets import load_dataset
from datasets import load_dataset_builder
import datasets
import transformers
from transformers import TrainingArguments
from transformers import Trainer

dataset = load_dataset('csv', data_files='my_data.csv', sep=';')
tokenizer = transformers.BertTokenizer.from_pretrained("bert-base-cased")
model = transformers.BertForMaskedLM.from_pretrained("bert-base-cased") 
print(dataset)
def tokenize_function(examples):
    return tokenizer(examples["Text"], examples["Sentiment"], truncation=True)

tokenized_datasets = dataset.map(tokenize_function, batched=True)
training_args = TrainingArguments("test_trainer")
trainer = Trainer(
    model=model, args=training_args, train_dataset=tokenized_datasets
)
trainer.train()

这会引发错误消息:

ValueError: text input must of type `str` (single example), `List[str]` (batch or single pretokenized example) or `List[List[str]]` (batch of pretokenized examples).

我做错了什么?非常感谢任何建议。

【问题讨论】:

我更新了我的答案,请看一下,如果有帮助请告诉我。 【参考方案1】:

您需要注意以下几点才能使您的代码正常工作。

首先,您正在处理序列分类任务,特别是二进制分类,因此您需要相应地实例化您的模型:

# replace this:
# model = transformers.BertForMaskedLM.from_pretrained("bert-base-cased")
# by this:
model = transformers.BertForSequenceClassification.from_pretrained("bert-base-cased", num_labels=2)

您不应将标签 (examples["Sentiment"]) 提供给分词器,因为它们不需要被分词:

# use only the text as input 
# use padding to standardize sequence length
return tokenizer(examples["Text"], truncation=True, padding='max_length')

谈到标签,您的培训师会期望它们位于名为“标签”的列中,因此您必须相应地重命名您的“情绪”。请注意,此方法不会像您预期的那样在原地运行,它会返回一个您必须捕获的新数据集。

# for example, after you tokenized the dataset:
tokenized_datasets = tokenized_datasets.rename_column('Sentiment', 'label')

最后,您需要指定实际要用于训练的数据集的拆分。在这里,由于您没有拆分数据集,它应该只包含一个:'train'

trainer = Trainer(
    model=model, 
    args=training_args, 
    train_dataset=tokenized_datasets['train'] # here
)

这应该会让你的代码工作,但并不意味着你会得到任何有趣的结果。由于您对使用变形金刚感兴趣,我强烈建议您查看series of notebooks by huggingface。

【讨论】:

谢谢,这解决了 OP 中的错误,但我可能需要为下一个问题提出新问题。现在它说:The following columns in the training set don't have a corresponding argument in BertForMaskedLM.forward and have been ignored: Text, Sentiment. 这给出了错误“训练集中的以下列在 BertForSequenceClassification.forward 中没有相应的参数并且已被忽略:Text.” 后跟“ValueError: Target size (torch.Size ([8])) 必须与输入大小相同 (torch.Size([8, 2]))´ 第一条消息只是一个警告,它不会阻止您的代码运行。您可以通过在训练之前删除“文本”列来摆脱它,例如tokenized_datasets = tokenized_datasets.remove_columns('Text')。很难猜测是什么触发了第二条消息。它可能来自数据集本身。你能分享文件,或从中摘录吗? 这是 CSV 文件:github.com/JereRajala00/training-data。您知道该错误消息的一般含义吗?

以上是关于使用 Trainer API 预训练 BERT 模型时出现 ValueError的主要内容,如果未能解决你的问题,请参考以下文章

BERT:深度双向预训练语言模型

在特定领域继续训练预训练的 BERT 模型的最简单方法是啥?

预训练语言模型整理(ELMo/GPT/BERT...)

预训练模型-从BERT原理到BERT调包和微调

BERT模型Hugging face的慢速训练

使用 BERT 等预训练模型进行文档分类