HuggingFace | huggingface中遇到的坑

发布时间 2023-07-07 12:19:16作者: 张Zong在修行

一、不要尝试使用huggingface的Trainer函数加载自定义模型

理论上说,Hugging Face的Trainer函数可以加载自定义模型,只要您的模型是基于PyTorch或TensorFlow实现的,并且实现了必要的方法(如forward方法和from_pretrained方法)。

要将您的自定义模型与Hugging Face的Trainer函数一起使用,您需要使用Transformers库中的Trainer类,该类提供了训练、评估和预测模型的方法,以及与PyTorch和TensorFlow模型集成的功能。

代码示例:

import torch
from torch.utils.data import Dataset
from transformers import Trainer, TrainingArguments

class MyDataset(Dataset):
    def __init__(self, data):
        self.data = data
    
    def __len__(self):
        return len(self.data)
    
    def __getitem__(self, idx):
        # 假设数据是一个 tuple,第一个元素是输入,第二个元素是标签
        input_ids = self.data[idx][0]
        labels = self.data[idx][1]
        return {"input_ids": input_ids, "labels": labels}

# 假设您有一个包含 100 个样例的数据集,每个样例是一个 tuple,包含一个长度为 10 的输入和一个标签
data = [([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 0) for i in range(100)]

# 创建 train_dataset 和 eval_dataset,这里使用前 80 个样例作为训练集,后 20 个样例作为评估集
train_dataset = MyDataset(data[:80])
eval_dataset = MyDataset(data[80:])

class MyModel(torch.nn.Module):
    def __init__(self):
        super(MyModel, self).__init__()
        self.linear = torch.nn.Linear(10, 1)
    
    def forward(self, input_ids, labels=None):
        logits = self.linear(input_ids)
        if labels is not None:
            labels = labels.to(torch.float)
            labels = labels.view(-1)
            loss_fn = torch.nn.CrossEntropyLoss(ignore_index=-1)
            loss = loss_fn(logits.view(-1, 1), labels)
            return loss
        else:
            return logits
    
    @classmethod
    def from_pretrained(cls, pretrained_model_name_or_path, *model_args, **kwargs):
        model = cls(*model_args, **kwargs)
        state_dict = torch.load(pretrained_model_name_or_path)
        model.load_state_dict(state_dict)
        return model

model = MyModel()
training_args = TrainingArguments(
    output_dir='./results',          # 训练输出目录
    num_train_epochs=3,              # 训练轮数
    per_device_train_batch_size=16,  # 训练批次大小
    per_device_eval_batch_size=64,   # 评估批次大小
    warmup_steps=500,                # 预热步数
    weight_decay=0.01,               # 权重衰减
    logging_dir='./logs',            # 日志目录
    logging_steps=10,                # 日志步数
)

trainer = Trainer(
    model=model,                         # 自定义模型实例
    args=training_args,                  # 训练参数
    train_dataset=train_dataset,         # 训练数据集
    eval_dataset=eval_dataset            # 评估数据集
)

trainer.train()  # 开始训练

我们上面都可以运行,但是到了trainer.train()函数中,就有各种错误,比如:

RuntimeError: expected scalar type Float but found Long

这个错误通常是由于张量数据类型不匹配引起的。在 PyTorch 中,张量数据类型非常重要,因为它们指定了张量中存储的数值的精度和类型。如果您在模型的前向传递中使用了错误的数据类型,就会出现这个错误。

但是代码中我们找不到这个错误就说执行在trainer.train()函数这里,报了错。这样对debug代码不友好,而且这个错误解决了,可能还有更多错误。

使用Trainer函数的正确用法

想要使用Trainer函数进行训练模型,那么模型应该使用huggingface中的可以查到的模型。我们可以使用这些预训练模型进行微调。

比如,我们使用多语言预训练模型进行翻译的下游任务,而且我们可以训练领域的数据的embedding,然后可以进行领域的翻译训练,然后我们可以通过我们训练好的预训练模型进行使用。

在比如,我们可以进行数据的处理,把单语数据进行翻译。(待定)

问题继续发现。。。。。。