0

我正在尝试使用 Huggingface Trainer API 微调 BERT 模型以进行情绪分析(将文本分类为正面/负面)。我的数据集有两列TextSentiment它看起来像这样。

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

这是我的代码:

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

dataset = load_dataset('csv', data_files='./train/test.csv', sep=';')
tokenizer = transformers.BertTokenizer.from_pretrained("TurkuNLP/bert-base-finnish-cased-v1")
model = transformers.BertForSequenceClassification.from_pretrained("TurkuNLP/bert-base-finnish-cased-v1", num_labels=1) 
def tokenize_function(examples):
    return tokenizer(examples["Text"], truncation=True, padding='max_length')

tokenized_datasets = dataset.map(tokenize_function, batched=True)
tokenized_datasets = tokenized_datasets.rename_column('Sentiment', 'label')
tokenized_datasets = tokenized_datasets.remove_columns('Text')
training_args = TrainingArguments("test_trainer")
trainer = Trainer(
    model=model, args=training_args, train_dataset=tokenized_datasets['train']
)
trainer.train()

运行此引发错误:

Variable._execution_engine.run_backward(
RuntimeError: Found dtype Long but expected Float

错误可能来自数据集本身,但我可以用我的代码以某种方式修复它吗?我搜索了互联网,这个错误似乎之前已经通过“将张量转换为浮点数”解决了,但是我将如何使用 Trainer API 来解决这个问题?任何建议都非常感谢。

一些参考:

https://discuss.pytorch.org/t/run-backward-expected-dtype-float-but-got-dtype-long/61650/10

4

2 回答 2

1

最有可能的是,问题在于损失函数。如果您正确设置模型,则可以解决此问题,主要是通过指定要使用的正确损失。请参阅此代码以查看确定正确损失的逻辑。

您的问题具有二进制标签,因此应该被视为单标签分类问题。因此,您共享的代码将被推断为回归问题,这解释了它期望浮动但发现目标标签的长类型的错误。

您需要传递正确的问题类型。

model = transformers.BertForSequenceClassification.from_pretrained(
    "TurkuNLP/bert-base-finnish-cased-v1", 
    num_labels=1, 
    problem_type = "single_label_classification"
) 

这将利用 BCE 损失。对于 BCE 损失,您需要目标浮动,因此您还必须将标签转换为浮动。我认为您可以使用数据集 API 做到这一点。看到这个

另一种方法是使用多类分类器或 CE 损失。为此,只需修复num_labels就可以了。

model = transformers.BertForSequenceClassification.from_pretrained(
    "TurkuNLP/bert-base-finnish-cased-v1", 
    num_labels=2,
) 
于 2021-12-30T22:53:39.263 回答
0

这里我假设你尝试做一个标签分类,即预测单个结果而不是预测多个结果。

但是您使用的损失函数(我不知道您在使用什么,但它可能是 BCE)需要您提供一个向量作为标签。

因此,您要么需要按照评论中的建议将标签转换为向量,要么可以将损失函数替换为交叉熵损失,并将标签参数的数量更改为 2(或其他)。两种解决方案都可以。

如果您想将模型训练为多标签分类器,您可以使用 sklearn.preprocessing 将标签转换为向量:

from sklearn.preprocessing import OneHotEncoder
import pandas as pd
import numpy as np

dataset = pd.read_csv("filename.csv", encoding="utf-8")
enc_labels = preprocessing.LabelEncoder()
int_encoded = enc_labels.fit_transform(np.array(dataset["Sentiment"].to_list()))

onehot_encoder = OneHotEncoder(sparse = False)
int_encoded = int_encoded.reshape(len(int_encoded),1)
onehot_encoded = onehot_encoder.fit_transform(int_encoded)
for index, cat in dataset.iterrows():
    dataset.at[index , 'Sentiment'] = onehot_encoded[index]
于 2021-12-31T12:04:31.160 回答