OpenAI API 指南:4.微调

了解如何为应用程序自定义模型。

介绍

通过微调,您可以通过提供以下内容从通过 API 提供的模型中获得更多收益:

  1. 比提示设计更高质量的结果
  2. 能够训练比提示所能容纳的更多示例
  3. 由于提示时间较短,可以节省代币
  4. 更低的延迟请求

原文链接:Fine-tuning – OpenAI API

GPT-3 已经对来自开放互联网的大量文本进行了预训练。当给出一个只有几个例子的提示时,它通常可以直观地判断你正在尝试执行什么任务并生成一个合理的完成。这通常被称为“少镜头学习”。

微调通过训练比提示所能容纳的更多的示例来改进少数镜头学习,让您在大量任务上获得更好的结果。对模型进行微调后,无需再在提示中提供示例。这样可以节省成本并实现更低的延迟请求。

概括地说,微调涉及以下步骤:

  1. 准备和上传训练数据
  2. 训练新的微调模型
  3. 使用微调模型

请访问我们的定价页面,详细了解如何对微调的模型训练和使用计费。

哪些模型可以微调?

微调目前仅适用于以下基本型号:davincicuriebabbageada 。这些是原始模型,在训练后没有任何说明(例如text-davinci-003)。您还可以继续微调微调模型以添加其他数据,而无需从头开始。text-davinci-003

安装

我们建议使用我们的 OpenAI 命令行界面 (CLI)。要安装它,请运行

(以下说明适用于版本 0.9.4 及更高版本。此外,OpenAI CLI 需要 python 3。

通过在 shell 初始化脚本(例如 .bashrc、zshrc 等)中添加以下行或在微调命令之前的命令行中运行它来设置环境变量:OPENAI_API_KEY

准备训练数据

训练数据是你教 GPT-3 你想说什么的方式。

您的数据必须是 JSONL 文档,其中每行都是对应于训练示例的提示完成对。您可以使用我们的 CLI 数据准备工具轻松地将数据转换为此文件格式。

设计用于微调的提示和完成与设计用于我们基本模型(Davinci、Curie、Babbage、Ada )的提示不同。特别是,虽然基础模型的提示通常由多个示例组成(“少数镜头学习”),但为了微调,每个训练示例通常由单个输入示例及其关联的输出组成,而无需给出详细说明或在同一提示中包含多个示例。

有关如何为各种任务准备训练数据的更详细指导,请参阅我们准备数据集最佳实践。

您拥有的培训示例越多越好。我们建议至少有几百个示例。通常,我们发现数据集大小每增加一倍,模型质量就会线性提高。

CLI 数据准备工具

我们开发了一个工具来验证、提供建议和重新格式化您的数据:

此工具接受不同的格式,唯一要求它们包含提示和完成列/键。您可以传递 CSV、TSV、XLSX、JSON 或 JSONL 文件,它会在指导您完成建议的更改过程后,将输出保存到 JSONL 文件中,以便进行微调。

创建微调模型

以下假设你已按照上述说明准备了训练数据。

使用 OpenAI CLI 启动微调作业:

您从哪里开始的基本模型的名称(ada、babbage、居里或达芬奇)。您可以使用后缀参数自定义微调模型的名称。BASE_MODEL

运行上述命令会执行以下几项操作:

  1. 使用文件 API 上传文件(或使用已上传的文件)
  2. 创建微调作业
  3. 流式传输事件,直到作业完成(这通常需要几分钟,但如果队列中有许多作业或数据集很大,则可能需要数小时)

每个微调作业都从默认为居里的基本模型开始。模型的选择会影响模型的性能和运行微调模型的成本。您的模型可以是以下之一:adababbagecurie, 或 davinci。请访问我们的定价页面,了解有关微调费率的详细信息。

开始微调作业后,可能需要一些时间才能完成。你的作业可能排在我们系统上的其他作业后面,训练我们的模型可能需要几分钟或几小时,具体取决于模型和数据集大小。如果事件流因任何原因中断,您可以通过运行以下命令来恢复它:

作业完成后,它应显示微调模型的名称。

除了创建微调作业之外,您还可以列出现有作业、检索作业状态或取消作业。

使用微调模型

作业成功后,fine_tuned_model将使用模型名称填充该字段。您现在可以将此模型指定为我们的完成 API 的参数,并使用 Playground 向其发出请求。

作业首次完成后,模型可能需要几分钟才能准备好处理请求。如果对模型的完成请求超时,则可能是因为模型仍在加载中。如果发生这种情况,请在几分钟后重试。

您可以通过将模型名称model作为完成请求的参数传递来开始发出请求:

OpenAI CLI:

cURL

Python

Node.js:

您可以继续在这些请求中使用所有其他完成参数,temperaturefrequency_penaltypresence_penalty等,以微调模型。

删除微调的模型

若要删除微调的模型,必须在组织内指定“所有者”。

OpenAI CLI:

cURL

Python

准备数据集

微调是一种强大的技术,用于创建特定于您的用例的新模型。在微调模型之前,我们强烈建议您阅读下面针对您的使用案例的这些最佳实践和特定指南

数据格式

要微调模型,您需要一组训练示例,每个示例都由单个输入(“prompt”)及其关联的输出(“completion”)组成。这与使用我们的基本模型明显不同,在基本模型中,您可以在单个提示中输入详细说明或多个示例。

  • 每个提示都应以固定的分隔符结尾,以便在提示结束和完成开始时通知模型。通常运行良好的简单分隔符是 。分隔符不应出现在任何提示中的其他位置。\n\n###\n\n
  • 由于我们的标记化,每个完成都应该以空格开头,这会用前面的空格标记大多数单词。
  • 每次完成都应以固定的停止序列结束,以便在完成结束时通知模型。停止序列可以是 、 或任何其他未出现在任何完成中的标记。\n###
  • 对于推理,应采用与创建训练数据集时相同的方式设置提示的格式,包括相同的分隔符。还要指定相同的停止序列以正确截断完成。

一般最佳做法

使用更多高质量示例,微调效果更好。要微调性能优于使用高质量提示的模型,您应该提供至少数百个高质量的示例,最好由人类专家审查。从那里开始,性能往往会随着示例数量的每增加一倍而线性增加。增加示例数量通常是提高性能的最佳和最可靠的方法。

分类器是最容易入门的模型。对于分类问题,我们建议使用ada,一旦微调,它通常只会比功能更强大的模型表现得稍微差一点,同时速度更快,更便宜。

如果要对预先存在的数据集进行微调,而不是从头开始编写提示,请确保尽可能手动查看数据中是否有令人反感或不准确的内容,或者如果数据集很大,则尽可能多地查看数据集的随机样本。

具体准则

微调可以解决各种问题,使用它的最佳方式可能取决于您的特定用例。下面,我们列出了最常见的微调用例和相应的指南。

分类

在分类问题中,提示中的每个输入都应分类到预定义的类之一。对于此类问题,我们建议:

  • 在提示符末尾使用分隔符,例如 \n\n###\n\n.请记住,当您最终向模型发出请求时,还要附加此分隔符。
  • 选择映射到单个token的类。在推理时,请指定,因为您只需要第一个标记进行分类。max_tokens=1
  • 确保提示 + 完成不超过 2048 个标记,包括分隔符
  • 目标是每节课至少~100个示例
  • 要获取类日志概率,您可以在使用模型时指定(对于 5 个类)logprobs=5
  • 确保用于微调的数据集在结构和任务类型上与模型将用于的任务非常相似

案例研究:模型是否做出了不真实的陈述?

假设您想确保网站上的广告文字提及正确的产品和公司。换句话说,你要确保模型不是编造的。您可能需要微调分类器,以过滤掉不正确的广告。

数据集可能如下所示:

在上面的示例中,我们使用了包含公司名称、产品和关联广告的结构化输入。作为分隔符,我们使用它清楚地将提示与完成分开。有了足够数量的示例,只要分隔符没有出现在提示或完成中,它就不会产生太大差异(通常小于 0.4%)。\nSupported:

对于此用例,我们对 ada 模型进行了微调,因为它更快、更便宜,并且性能将与更大的模型相当,因为它是一项分类任务。

现在,我们可以通过发出完成请求来查询模型。

这将返回 yes 或 no . 

案例研究:情绪分析

假设你想获得特定推文是正面还是负面的程度。数据集可能如下所示:

微调模型后,可以通过设置完成请求来获取第一个完成令牌的日志概率。正类的概率越高,相对情绪越高。logprobs=2

现在,我们可以通过发出完成请求来查询模型。

这将返回:

案例研究:电子邮件会审的分类

假设您要将传入的电子邮件分类为大量预定义类别之一。要分类为大量类别,我们建议您将这些类别转换为数字,这将适用于 ~500 个类别。我们观察到,由于标记化,在数字之前添加空格有时会稍微提高性能。您可能希望按如下方式构建训练数据:

例如:

在上面的示例中,我们使用以 2043 个令牌为上限的传入电子邮件作为输入。(这允许 4 个令牌分隔符和一个令牌完成,总计到 2048 个。作为分隔符,我们使用并删除了电子邮件中出现的任何内容。\n\n###\n\n###

条件生成

条件生成是一个问题,其中需要生成给定某种输入的内容。这包括释义、总结、实体提取、产品描述编写给定规范、聊天机器人等等。对于此类问题,我们建议:

  • 在提示符末尾使用分隔符,例如 \n\n###\n\n .请记住,当您最终向模型发出请求时,还要附加此分隔符。
  • 在完成结束时使用结束标记,例如 END
  • 请记住在推理过程中添加结束标记作为停止序列,例如stop=[" END"]
  • 目标至少 ~500 个示例
  • 确保提示 + 完成不超过 2048 个标记,包括分隔符
  • 确保示例具有高质量并遵循相同的所需格式
  • 确保用于微调的数据集在结构和任务类型上与模型将用于的任务非常相似
  • 使用较低的学习率和只有 1-2 个 epoch 往往更适合这些用例

案例研究:根据维基百科文章撰写引人入胜的广告

这是一个生成用例,因此您需要确保您提供的示例具有最高质量,因为微调模型将尝试模仿给定示例的样式(和错误)。一个好的起点是大约 500 个示例。示例数据集可能如下所示:

例如:

在这里,我们使用了多行分隔符,因为维基百科文章包含多个段落和标题。我们还使用了一个简单的结束标记,以确保模型知道何时应该完成。

案例研究:实体提取

这类似于语言转换任务。为了提高性能,最好按字母顺序或按原始文本中显示的顺序对不同的提取实体进行排序。这将有助于模型跟踪需要按顺序生成的所有实体。数据集可能如下所示:

例如:

多行分隔符效果最好,因为文本可能包含多行。理想情况下,输入提示的类型(新闻文章、维基百科页面、推文、法律文档)将具有高度多样性,这些提示反映了提取实体时可能遇到的文本。

案例研究:客户支持聊天机器人

聊天机器人通常会包含有关对话的相关上下文(订单详细信息)、到目前为止的对话摘要以及最新消息。对于此用例,过去的相同对话可以在数据集中生成多行,每次的上下文略有不同,每次代理生成都作为完成。此用例将需要几千个示例,因为它可能会处理不同类型的请求和客户问题。为了确保性能高质量,我们建议审查对话示例以确保代理消息的质量。可以使用单独的文本转换微调模型生成摘要。数据集可能如下所示:

在这里,我们有意分离不同类型的输入信息,但在提示和完成之间保持相同格式的客户代理对话框。所有的完成应该只由代理完成,我们可以在进行推理时用作停止序列。\n

案例研究:基于技术属性列表的产品描述

在这里,将输入数据转换为自然语言非常重要,这可能会带来卓越的性能。例如,以下格式:

不会像:

为了获得高性能,请确保完成基于提供的描述。如果经常查阅外部内容,则以自动方式添加此类内容将提高性能。如果描述基于图像,则使用算法提取图像的文本描述可能会有所帮助。由于补全只有一个句子长,我们可以在推理过程中用作停止序列。.

高级用法

自定义模型名称

您可以使用后参数向微调的模型名称添加最多 40 个字符的后缀。

OpenAI CLI:

生成的名称将是:

分析微调模型

完成后,我们会将结果文件附加到每个作业。检索微调时以及查看微调事件时,将列出此结果文件 ID。您可以下载以下文件:

OpenAI CLI:

卷曲:

_results.csv文件包含每个训练步骤的一行,其中步骤是指对一批数据进行一次向前和向后传递。除了步骤编号外,每行还包含与该步骤对应的以下字段:

  • elapsed_tokens:模型到目前为止看到的代币数量(包括重复)
  • elapsed_examples:到目前为止模型看到的示例数(包括重复),其中一个示例是批处理中的一个元素。例如,如果batch_size = 4 ,则elapsed_examples每步将增加 4。
  • training_loss:训练批次的损失
  • training_sequence_accuracy:训练批次中模型的预测令牌与真实完成令牌完全匹配的完成百分比。例如,如果 batch_size 为 3,则您的数据包含完成 [[1, 2]、[0, 5]、[4, 2]] 和模型预测 [[1, 1]、[0, 5]、[4, 2]],则此精度将为 2/3 = 0.67
  • training_token_accuracy:训练批次中模型正确预测的令牌的百分比。例如,如果 batch_size 为 3,则您的数据包含完成 [[1, 2]、[0, 5]、[4, 2]] 和预测模型 [[1, 1]、[0, 5]、[4, 2]],则此精度将为 5/6 = 0.83

分类特定指标

我们还提供了在结果文件中生成其他特定于分类的指标的选项,例如准确性和加权 F1 分数。这些指标会根据完整的验证集定期计算,并在微调结束时计算。您将在结果文件中看到它们作为附加列。

要启用此功能,请设置参数 --compute_classification_metrics 。此外,还必须提供验证文件,并为多类分类设置参数 classification_n_classes,或为二元分类设置参数classification_positive_class

OpenAI CLI:

如果设置以下指标,则结果文件中将显示以下指标:--compute_classification_metrics

对于多类分类
  • classification/accuracy:准确性
  • classification/weighted_f1_score:加权 F-1 分数
对于二元分类

以下指标基于 0.5 的分类阈值(即,当概率> 0.5 时,示例被归类为属于正类。

  • classification/accuracy
  • classification/precision
  • classification/recall
  • classification/f{beta}
  • classification/auroc – AUROC
  • classification/auprc – AUPRC

请注意,这些评估假定您正在对标记为单个标记的类使用文本标签,如上所述。如果这些条件不成立,你得到的数字可能是错误的。

验证

您可以保留一些数据进行验证。验证文件的格式与训练文件的格式完全相同,并且训练数据和验证数据应互斥。

如果在创建微调作业时包含验证文件,则生成的结果文件将包括对微调模型在训练期间定期针对验证数据的性能的评估。

OpenAI CLI:

如果您提供了验证文件,我们会在训练期间定期计算批量验证数据的指标。您将在结果文件中看到以下其他指标:

  • validation_loss:验证批次丢失
  • validation_sequence_accuracy:验证批处理中模型的预测令牌与真实完成令牌完全匹配的完成百分比。例如,如果 batch_size为 3,则数据包含完成 [[1, 2]、[0, 5]、[4, 2]] 和模型预测 [[1, 1]、[0, 5]、[4, 2]],则此精度将为 2/3 = 0.67b
  • validation_token_accuracy:验证批处理中模型正确预测的令牌的百分比。例如,如果 batch_size 为 3,则您的数据包含完成 [[1, 2], [0, 5], [4, 2]] 和预测模型 [[1, 1], [0, 5], [4, 2]],则此精度将为 5/6 = 0.83

超参数

我们选择了在各种用例中运行良好的默认超参数。唯一必需的参数是训练文件。

也就是说,调整用于微调的超参数通常可以产生更高质量的输出。特别是,您可能需要配置以下内容:

  • model:要微调的基本模型的名称。您可以选择“ada”、“babbage”、“居里”或“davinci”之一。若要了解有关这些模型的详细信息,请参阅模型文档。
  • n_epochs– 默认为 4。要为其训练模型的纪元数。纪元是指通过训练数据集的一个完整周期。
  • batch_size– 默认为训练集中样本数的 ~0.2%,上限为 256。批量大小是用于训练单个正向和后向传递的训练示例数。通常,我们发现较大的批量大小往往更适合较大的数据集。
  • learning_rate_multiplier– 默认为 0.05、0.1 或 0.2,具体取决于最终 batch_size.微调学习率是用于预训练的原始学习率乘以该乘数。我们建议尝试 0.02 到 0.2 范围内的值,以查看产生最佳结果的值。根据经验,我们发现较大的学习率通常表现得更好,批量越大。
  • compute_classification_metrics– 默认为 False。如果为 True,则为了微调分类任务,在每个纪元结束时对验证集计算特定于分类的指标(准确性、F-1 分数等)。

要配置这些额外的超参数,请通过 OpenAI CLI 上的命令行标志传递它们,例如:

从微调的模型继续微调

如果您已经为您的任务微调了模型,并且现在有想要合并的其他训练数据,则可以继续从模型进行微调。这将创建一个从所有训练数据中学习的模型,而无需从头开始重新训练。

为此,请在创建新的微调作业时传入微调的模型名称(例如 -m curie:ft-<org>-<date>)。其他训练参数不必更改,但是,如果新的训练数据比以前的训练数据小得多,您可能会发现earning_rate_multiplier减少 2 到 4 倍很有用。l

权重和偏差

您可以将微调与权重和偏差同步,以跟踪实验、模型数据集。

要开始使用,您需要一个权重和偏见帐户和一个付费的OpenAI计划。要确保您使用的是 openaiwandb 的最新版本,请运行:

要将微调与权重和偏差同步,请运行:

您可以阅读权重和偏差文档,了解有关此集成的更多信息。

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部