手把手教你微调GPT-3.5 Turbo[8.22新特性]

1. 引言

3天前,OpenAI公布了一个新特性,那就是宣布用户可以自定义微调GPT-3.5 Turbo了。这意味着什么呢?这就意味着很多任务都可以先拿GPT-3.5 Turbo进行一个微调作为基准系统了。但是,需要注意的是,这里能够微调GPT-3.5 Turbo应该和之前能够微调GPT-3使用的是相似的技术,也就是参数高效的微调,不然每个用户光保存模型大小,即使是传言中的10B左右的模型,也是很难做到的。

那么什么场景比较适合它呢?我个人看法是如果是用它进行对话微调,意义可能不是太大,因为现在的对话数据大部分也是蒸馏自它。因此,它更适合在一些特定任务上,使用少量的数据就可以微调出一个性能不错的模型。
在这里插入图片描述

2. 怎么操作?

这两天看到网上宣传这个事情的不少,但是真正动手做的还是比较少的。因此,特地亲自下场试验一下。上一个特性是Function Calling,错过了,这次可不能再错过了。下面看一下整个训练步骤吧,这次我们使用汉语语法纠错任务作为样例,进行一个完整的数据准备、上传文件、训练模型和测试结果流程。

2.1 准备文件

根据OpenAI官网的要求,微调GPT-3.5 Turbo的样例输入格式是和它原始的对话形式是一致的,例如:

{
    
    "messages": [{
    
    "role": "system", "content": "你是一个汉语语法纠错器。"}, {
    
    "role": "user", "content": "检测这个句子的语法错误:这件事对我们大家当时震动很大。"}, {
    
    "role": "assistant", "content": "这件事当时对我们大家震动很大。"}]}

如果原来的数据格式不是这样的,可以先写一个转换函数,使得其转换成上述的格式即可。

2.2 上传文件

上传文件的代码也非常容易,下面是一个上传文件的函数,openai.File的上传文件是异步操作,当你执行完create以后,它会先把文档传到云端,但是需要等待云端处理该数据,这里据OpenAI说,是包含了内容过滤的部分。

def upload_file(file_name):
    # if a train_file is 400KB, it will take about 1 min to upload the file.
    file_upload = openai.File.create(file=open(file_name, "rb"), purpose="fine-tune")
    print("Uploaded file id", file_upload.id)
    while True:
        print("Waiting for file to process...")
        file_handle = openai.File.retrieve(id=file_upload.id)
        if len(file_handle) and file_handle.status == "processed":
            print("File processed")
            break
        time.sleep(3)
    return file_upload

当文档处理成功后,我们就可以利用这个文件进行微调GPT-3.5了。

2.3 训练模型

训练模型的代码非常简单,只有一句:

job = openai.FineTuningJob.create(training_file=file_upload.id, model="gpt-3.5-turbo")
print(job.id)

这里同样是一个异步操作,需要注意的是,这里一定要记得file_upload.id,这样才能够让OpenAI知道我们要训哪个文件。
另外需要注意的是,也要记得job.id,因为需要用它来查询这个模型训练的进度的。如果忘记了这个id也没有关系,你可以用下面的代码查询已有的job。

result = openai.FineTuningJob.list(limit=10)
print(result)

模型的训练需要时间,当你查询到job的状态是下面所示时,才表明这个模型已经训练成功了:

"status": "succeeded"

当然OpenAI也会在模型训练完成后邮件通知你的。

2.4 测试模型

模型测试和使用原版的GPT-3.5 Turbo方式相同,只不过model里需要填写model id,而model id则可以通过上面的查询和通知邮件中获取。当你获取到model id后,只需要执行下面的代码就可以测试了:

def test_by_case(model_id, message):
    """
    Test the model with a given message.

    :param model_id: ID of the model to test.
    :param message: Message to test the model.
    :return: Response from the model.
    """
    completion = openai.ChatCompletion.create(
        model=model_id,
        messages=message
    )
    return completion.choices[0].message["content"]

整体上还是比较简单的。根据OpenAI的说法,一个账户一天可以训练12个模型,每次只能同时训练1个模型。

3. 实验结果

Model # Param. Data Word-level (P/R/F) Char-level(P/R/F)
S2S_BART 375M 1061 21.08/10.54/17.57 22.09/10.62/18.16
GrammarGPT 7B 1061 42.42/16.87/32.56 46.67/18.58/35.84
Fine-tuning GPT-3.5 Turbo - 1061 36.16/34.75/35.87 36.17/33.69/35.65

以上是我们在GrammarGPT的训练和测试集上进行的评估,可以看到模型的性能和7B全微调的性能差不多。

也不用担心上面的步骤看不懂,大家可以直接查看完整的代码:finetune_chatgpt

4. 训练的规模和成本

由于我们使用的是之前的GrammarGPT的任务作为样例,大部分关键指标如下所示。

训练样本1061条,转换后的文件大小为400KB左右,上传文件花费了大约1分多钟,训练轮数是默认值,最后是3轮,训练时间大概为1个多小时,推理速度为1秒1个样本左右。整体上训练40W左右token,测试500个样例,共计花费9刀左右。而对比训练GrammarGPT的7B大小,大概训练时间也就在8卡A100几十分钟的消耗,按照1个小时100块左右的消耗,两者似乎也差不太多。

5. 小结

从体验上来看,能够微调GPT-3.5 Turbo的门槛还是要低了很多,尽管有人吐槽说,这个成本是使用原版的4倍以上,但是对于大多数没有拥有8卡A100又需要大模型能力的同学来说,无外乎是一个福音。正如我之前所说的那样,以后的论文中,zero-shot的GPT-3.5 Turbo不是baseline了,而是微调后的GPT-3.5 Turbo才是一个strong baseline。

这是一个好事,也是一个坏事。

猜你喜欢

转载自blog.csdn.net/qq_35082030/article/details/132498748