实战案例:用OpenAI打造定制化的微调模型

2024/12/6 21:04:06

本文主要是介绍实战案例:用OpenAI打造定制化的微调模型,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

什么是调整?什么是调整?(通常指在现有基础上进行细微修改的过程。)

微调是基于预训练的机器学习模型,进一步使用较小且特定的数据集进行训练。这能让模型更好地理解特定的主题或任务,从而使模型在理解和回答相关问题时更加出色。微调利用模型现有的知识,避免从头开始训练,这样不仅节省时间和资源,还能提高其在特定任务上的表现。

主要好处

微调(Fine-tuning)的几个关键好处如下:

  • 更省时省钱:微调相较于从头训练模型更加经济且更快。
  • 提高性能:利用模型已有的知识,它可以帮助模型在特定任务上表现更好。
  • 需要较少的数据:你只需用较少的任务特定数据就能取得不错的效果。
  • 更容易的自定义:微调使你能够根据独特需求轻松定制强大的模型。
真实世界的调整案例

哈维公司是一家专注于法律技术的AI公司。他们使用法律数据和律师事务所特定信息对大型语言模型进行优化,以创建定制化的AI助手供法律专业人士使用。哈维的模型训练有素,能够处理复杂的法律任务,能够应对如下的查询:

“总结这份合同的关键点,并识别任何潜在的风险点。”
“加州在类似知识产权纠纷中有哪些相关先例?”

这种定制的方法让哈维能更好地回答法律问题,提供更准确和相关的答案。

使用 OpenAI 进行精调的高级操作步骤

最关键的部分是准备数据集。完成之后,剩下的步骤就都变得简单多了。

  • 准备训练数据集:将数据整理成JSONL文件格式,并确保数据质量高且多样化。数据应包含提示-响应对。
  • 开始进行微调:登录OpenAI,进入“微调”部分,点击“新建”,选择一个模型,上传您的JSONL文件,并监控进度直至完成。
  • 使用微调模型:在沙盒中选择您的模型,试用提示测试它,并在您的应用中使用它。
准备数据

在准备数据以微调OpenAI模型时,训练数据的格式非常重要。这里有几个关于数据格式的关键点:

  • 训练数据必须采用 JSONL(JSON Lines)格式。
  • 文件中的每一行都必须是一个有效的 JSON 对象。
  • 每个 JSON 对象不能跨行。
  • 文件扩展名应该是 .jsonl。
  • 确保您的示例高质量且多样化,充分代表您的任务。
  • 至少包含 10 个示例,更多的示例通常能提高性能。
聊天模型的数据结构设计

对于像GPT-4这样的聊天模型来说,一般情况下,结构应该是这样的。

    {"messages": [{"role": "system", "content": "系统信息"},   
                  {"role": "user", "content": "用户输入"},   
                  {"role": "assistant", "content": "助手回复"}]}
  • 每个示例都是一段完整的对话。
  • “messages”数组就是对话的全部内容。
  • 这些角色可以是系统、用户或助手。
用于精调的数据集

在这个例子中,我使用了一个癌症数据集来展示整个流程。目标是根据电子健康记录(EHR)分类患者的文档,以确定患者目前是否有癌症,过去是否有癌症,是否未患癌症,或者亲属是否患有癌症。这里提供了一个简化的数据集用于说明。你可以按照这些步骤来调整你自己的数据集。

数据集中包含文本示例,每个条目根据所描述的癌症状态进行分类。类别有等:

  1. Cancer_present :描述正在经历的癌症治疗的文本。例如:“她目前正在接受乳腺癌化疗。”
  2. Cancer_past :指过去的癌症已被确认的文本。例如:“他收到了确认前列腺癌的阳性检测结果。”
  3. Cancer_relative :与他人癌症经历相关的文本。例如:“我妈妈与乳腺癌斗争了两年,现在病情有所好转。”
  4. No_Cancer :与患者没有癌症相关的文本。例如:“她的结肠癌检测结果是阴性。”

这里是一条数据。

    {"messages": [{"role": "system", "content": "你的任务是将一段文本分类到以下类别标签中:['当前存在癌症', '曾经患有癌症', '亲属曾患癌症', '无癌症']"},   
    {"role": "user", "content": "她上个月被诊断出患有三期结肠直肠癌。"},   
    {"role": "assistant", "content": "当前存在癌症"}]}

高质量的数据样本非常重要。调整时至少需要10条数据记录。这里是用于训练模型进行分类的10条标记数据。

这里是 JSONL 格式的数据,即每行一个 JSON 对象的序列。下面这个就是用 JSONL 格式表示的数据。

    {"messages": [{"role": "system", "content": "你的任务是将一段文本分类到以下类别标签之一:[\"Cancer_present\", \"Cancer_past\", \"Cancer_relative\", \"No_Cancer\"]."}, {"role": "user", "content": "她上个月被诊断出患有三期结肠癌。"}, {"role": "assistant", "content": "Cancer_present"}]}  
    {"messages": [{"role": "system", "content": "你的任务是将一段文本分类到以下类别标签之一:[\"Cancer_present\", \"Cancer_past\", \"Cancer_relative\", \"No_Cancer\"]."}, {"role": "user", "content": "肿瘤科医生确认他的症状与癌症相关。"}, {"role": "assistant", "content": "Cancer_present"}]}  
    {"messages": [{"role": "system", "content": "你的任务是将一段文本分类到以下类别标签之一:[\"Cancer_present\", \"Cancer_past\", \"Cancer_relative\", \"No_Cancer\"]."}, {"role": "user", "content": "她的最近扫描显示肺部有恶性肿瘤。"}, {"role": "assistant", "content": "Cancer_present"}]}  
    {"messages": [{"role": "system", "content": "你的任务是将一段文本分类到以下类别标签之一:[\"Cancer_present\", \"Cancer_past\", \"Cancer_relative\", \"No_Cancer\"]."}, {"role": "user", "content": "她目前正在接受乳腺癌的化疗。"}, {"role": "assistant", "content": "Cancer_present"}]}  
    {"messages": [{"role": "system", "content": "你的任务是将一段文本分类到以下类别标签之一:[\"Cancer_present\", \"Cancer_past\", \"Cancer_relative\", \"No_Cancer\"]."}, {"role": "user", "content": "他收到了一个阳性测试结果,确认患有前列腺癌。"}, {"role": "assistant", "content": "Cancer_present"}]}  
    {"messages": [{"role": "system", "content": "你的任务是将一段文本分类到以下类别标签之一:[\"Cancer_present\", \"Cancer_past\", \"Cancer_relative\", \"No_Cancer\"]."}, {"role": "user", "content": "她在十几岁时患过癌症,但从那时起就一直在缓解中。"}, {"role": "assistant", "content": "Cancer_past"}]}  
    {"messages": [{"role": "system", "content": "你的任务是将一段文本分类到以下类别标签之一:[\"Cancer_present\", \"Cancer_past\", \"Cancer_relative\", \"No_Cancer\"]."}, {"role": "user", "content": "经过五年无癌的生活,他仍然定期进行检查。"}, {"role": "assistant", "content": "Cancer_past"}]}  
    {"messages": [{"role": "system", "content": "你的任务是将一段文本分类到以下类别标签之一:[\"Cancer_present\", \"Cancer_past\", \"Cancer_relative\", \"No_Cancer\"]."}, {"role": "user", "content": "她战胜了宫颈癌,之后一直很健康。"}, {"role": "assistant", "content": "Cancer_past"}]}  
    {"messages": [{"role": "system", "content": "你的任务是将一段文本分类到以下类别标签之一:[\"Cancer_present\", \"Cancer_past\", \"Cancer_relative\", \"No_Cancer\"]."}, {"role": "user", "content": "他的测试结果证实他已经完全从皮肤癌中恢复。"}, {"role": "assistant", "content": "Cancer_past"}]}  
    {"messages": [{"role": "system", "content": "你的任务是将一段文本分类到以下类别标签之一:[\"Cancer_present\", \"Cancer_past\", \"Cancer_relative\", \"No_Cancer\"]."}, {"role": "user", "content": "我妈妈与乳腺癌斗争了两年,现在处于缓解。"}, {"role": "assistant", "content": "Cancer_relative"}}

用一组较小的样本来测试模型的性能。这有助于通过反馈来调整超参数并选择最佳模型,确保模型能泛化到未见的数据上。

这是我的验证数据集。

    {"messages": [{"role": "system", "content": "你的任务是将一段文本分类到以下类别标签中:[\"癌症存在\", \"癌症过去\", \"家族癌症\", \"无癌症\"]."}, {"role": "user", "content": "他的父亲因肺癌去世,这让他担心自己的患病风险。"}, {"role": "assistant", "content": "家族癌症"}]}  
    {"messages": [{"role": "system", "content": "你的任务是将一段文本分类到以下类别标签中:[\"癌症存在\", \"癌症过去\", \"家族癌症\", \"无癌症\"]."}, {"role": "user", "content": "她的堂妹最近被诊断出早期宫颈癌。"}, {"role": "assistant", "content": "家族癌症"}]}  
    {"messages": [{"role": "system", "content": "你的任务是将一段文本分类到以下类别标签中:[\"癌症存在\", \"癌症过去\", \"家族癌症\", \"无癌症\"]."}, {"role": "user", "content": "她因此担心,因为去年她的姐姐被诊断出乳腺癌。"}, {"role": "assistant", "content": "家族癌症"}]}  
    {"messages": [{"role": "system", "content": "你的任务是将一段文本分类到以下类别标签中:[\"癌症存在\", \"癌症过去\", \"家族癌症\", \"无癌症\"]."}, {"role": "user", "content": "他的母亲目前正在与结肠癌抗争,所以他决定去做检查。"}, {"role": "assistant", "content": "家族癌症"}]}  
    {"messages": [{"role": "system", "content": "你的任务是将一段文本分类到以下类别标签中:[\"癌症存在\", \"癌症过去\", \"家族癌症\", \"无癌症\"]."}, {"role": "user", "content": "她父亲的前列腺癌病史让她更加小心地关注自己的健康。"}, {"role": "assistant", "content": "家族癌症"}]}

现在我们可以开始调优了。这可以通过代码或界面来完成。

您也可以通过代码来触发调整。

    from openai import OpenAI  
    client = OpenAI()  

    # 开始一个微调任务:  
    client.fine_tuning.jobs.create(  
      training_file="file-abc123",   
      model="gpt-4o-mini"  
    )  

    # 查看微调任务的状态  
    client.fine_tuning.jobs.retrieve("ftjob-abc123")  

    # 取消这个任务  
    client.fine_tuning.jobs.cancel("ftjob-abc123")  

    # 列出这10个微调任务的事件  
    client.fine_tuning.jobs.list_events(fine_tuning_job_id="ftjob-abc123", limit=10)

接下来,我将带你通过仪表板进行调整的过程,这可能是初学者的最佳入门方式。

使用openAI界面进行模型的精调
1. 访问细调界面:
  • 登录到 OpenAI 然后进入“Fine-tuning”部分

去微调部分

2. 开始微调

选择一个基础模型,上传你的JSONL格式的文件,并给它取个名字。

选择一个模型并上传数据

请选择你想要微调的模型。(4o-mini)我用的是4o-mini。

请上传您的训练和验证数据集

设置超参数值。在进行微调时,仔细调整学习率、批量大小和训练周期。从推荐的默认设置开始,通过实验找到最适合您任务的最优设置。

第3步:调整超参数

以下是在OpenAI训练中使用的三个主要超参数。

  1. 学习率:
    这控制模型学习的速度。较高的学习率意味着更快的学习,但可能忽略重要的细节。较低的学习率则学习更加细致,但需要更多的时间。
  2. 批量大小:
    这是模型在更新它所知的内容之前查看的示例数量。较大的批量有助于学习更复杂的模式,但需要更多的内存。
  3. 训练轮数:
    这是模型遍历所有训练数据的次数。更多的轮数意味着更多的训练机会,但轮数过多会导致模型记住数据而不是真正学习。范围:通常为1到10。我使用了10。
4, 监控进度情况

在仪表板上查看微调过程,直到完成为止。

我的第一次尝试失败了,因为我训练数据有问题。我解决了那个问题。

我的JSONL文件有误,因为每个JSON对象没有放在一行里。我得把这个问题解决一下。

我把那个弄好了,重新上传数据,之后一切都好了。

损失度量,比如损失值

这是我选定的超参数值。

使用的超参数有

这里是一些关键损失指标,例如随着训练进展需要跟踪的变化,如损失值。

监控训练和验证损失,确保微调过程顺利。损失减少表示模型学得不错。如果验证损失增加而训练损失减少,则需要注意是否出现过拟合。

花了15分钟完成了微调工作

5. 试试这个模型。

现在让我们在实验平台上使用微调过的模型。

你也可以用代码查询

from openai import OpenAI  
client = OpenAI()  

completion = client.chat.completions.create(  
  model="Enter_the_fine_tuned_model_IDhere",  
  messages=[  
    {"role": "system", "content": "你的任务是将一段文本分类为以下类别:[\"现患癌症\", \"既往癌症\", \"家族癌症史\", \"无癌症\"]。"},  
    {"role": "user", "content": "她结肠癌的检测结果是阴性!"}  
  ]  
)  
print(completion.choices[0].message)

现在这个模型已经准备好了。

微调经济学

虽然初始训练数据是免费的,但考虑整体成本很重要。

GPT-4O (原文)

- 训练(每百万个token 25元),
- 推理(每百万个token 3.75元),
- 输出(每百万个token 15元),

GPT-4O-min

- 训练:$3每百万标记,
- 推理:$0.3每百万标记,
- 输出:$1.25每百万标记,

结束.

对OpenAI模型进行微调是让AI更好地适应特定任务的一个好方法。通过准备好高质量的训练数据、挑选合适的模型并进行充分的训练,企业可以创建量身定制的AI解决方案,这些解决方案的表现通常会比通用模型更好。虽然这样做需要时间和资源,但它能带来更好的效果,同时还能节省资金。

不过,微调并不是每次都需要。适当调整提示就可以得到很好的效果,而无需额外的训练步骤。在决定是否进行微调之前,你需要考虑您的具体需求和数据。只要操作得当,可以为有效利用AI打开新的可能性。



这篇关于实战案例:用OpenAI打造定制化的微调模型的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程