FinNLP - 使用LoRA来训练自己的FinGPT - 2. 模型训练

FinNLP - 使用LoRA来训练自己的FinGPT - 2. 模型训练

一、前言

前一篇文章介绍了我们使用的训练数据以及如何利用市场来制作我们的训练数据标签,这期文章我们将探讨如何训练我们的自己的FinGPT,前一篇文章的链接详见如下地址:

Hugging Face 是当今训练和微调大语言模型非常好用的库,能够节约我们大量的代码编写与调试时间。近期Hugging Face旗下的 peft 库也支持了包括LoRA在内的大模型微调功能,可以使用这些库在有限的计算资源中训练大语言模型。本文的模型训练也将基于相关的库展开,完整代码详见:

二、模型选择

预训练模型的选择直接决定了最终的训练质量与效果,而在本项目中,由于新闻的文本大多是中文的,因此选择了由清华大学发布的 ChatGLM-6B 模型。该模型是开源的、支持中英双语的对话语言模型,同时支持轻量化推理和部署,因此非常适合本次的训练任务。

三、模型训练

为了能够使用hugging face相关的dataset训练模型,我们需要对数据的格式进行一系列的转化,包括文本向量化同时生成对应的dataset文件等。在转换完了之后我们还需要给出data_collator来使得训练器能够获取对应的训练数据,相关的代码如下:

def data_collator(features: list) -> dict:
    len_ids = [len(feature["input_ids"]) for feature in features]
    longest = max(len_ids)
    input_ids = []
    labels_list = []
    for ids_l, feature in sorted(zip(len_ids, features), key=lambda x: -x[0]): # 按照文本长短重新排序
        ids = feature["input_ids"]
        # seq_len = feature["seq_len"]
        seq_len = len(ids)
        labels = (
            [-100] * (seq_len - 1) + ids[(seq_len - 1) :] + [-100] * (longest - ids_l)
        ids = ids + [tokenizer.pad_token_id] * (longest - ids_l)           # 补齐文本长度
        _ids = torch.LongTensor(ids)
        labels_list.append(torch.LongTensor(labels))
        input_ids.append(_ids)
    input_ids = torch.stack(input_ids)
    labels = torch.stack(labels_list)
    return {
        "input_ids": input_ids,
        "labels": labels,
    }

同时我们也需要对训练器做如下所以的修改来使其适用于ChatGLM的模型:

class ModifiedTrainer(Trainer):
    def compute_loss(self, model, inputs, return_outputs=False):
        return model(
            input_ids=inputs["input_ids"],
            labels=inputs["labels"],
        ).loss
    def prediction_step(self, model: nn.Module, inputs, prediction_loss_only: bool, ignore_keys = None):