微调open in new window

了解如何为你的应用定制一个模型。

介绍

微调让你通过提供API获得更多可用的模型:

  1. 比提示设计更高质量的结果
  2. 能够在更多的例子上进行训练,而不是在提示中进行训练
  3. 由于较短的提示,可以节省token
  4. 更低的延迟请求

GPT-3已经对来自开放互联网的大量文本进行了预训练。当给它一个只有几个例子的提示时,它往往能直觉到你要执行什么任务,并产生一个合理的完成。这通常被称为 "少量学习"。

微调通过对比提示中所包含的更多的例子进行训练,改进了少数几次的学习,让你在大量的任务中取得更好的结果。一旦一个模型被微调,你就不需要再在提示中提供例子。 这节省了成本,并实现了更低的延迟请求。

在一个较高的水平上,微调包括以下步骤:

  1. 准备并上传训练数据
  2. 训练一个新的微调过的模型
  3. 使用你的微调后的模型

访问我们的定价页面open in new window,了解更多关于微调模型训练和使用的计费方式。

哪些模型可以进行微调?

微调目前只适用于以下基础模型:davinci, curie, babbageada。这些是原始模型,在训练后没有任何指令(例如像text-davinci-003那样)。你也能够从微调的模型中继续进行微调,增加额外的数据,而不必从头开始。

安装

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

pip install --upgrade openai
1

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

设置OPENAI_API_KEY环境变量的方法是:在shell初始化脚本(如.bashrc、zshrc等)中加入以下一行,或在微调命令前的命令行中运行:

export OPENAI_API_KEY="<OPENAI_API_KEY>"
1

准备训练数据

训练数据是你如何教GPT-3你想让它说什么。

你的数据必须是一个JSONLopen in new window文件,其中每一行都是对应于一个训练实例的提示-完成对。你可以使用我们的CLI数据准备工具来轻松地将你的数据转换成这种文件格式。

{"提示": "<提示 text>", "完成": "<ideal generated text>"}
{"提示": "<提示 text>", "完成": "<ideal generated text>"}
{"提示": "<提示 text>", "完成": "<ideal generated text>"}
...
1
2
3
4

为微调设计提示语和完成语与为我们的基础模型(Davinci, Curie, Babbage, Ada)设计提示语不同。特别是,基础模型的提示通常由多个例子组成("少量学习"),而对于微调,每个训练例子通常由一个输入例子和其相关的输出组成,不需要给出详细的说明或在同一提示中包括多个例子。

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

你拥有的训练实例越多,就越好。我们建议至少要有几百个例子。一般来说,我们发现数据集的规模每增加一倍,模型的质量就会直线上升。

CLI数据准备工具

我们开发了一个工具,可以验证、提供建议并重新格式化你的数据:

openai tools fine_tunes.prepare_data -f <LOCAL_FILE>
1

这个工具接受不同的格式,唯一的要求是它们包含一个提示和一个完成列/键。你可以传递一个CSVTSVXLSXJSONJSONL 文件,在指导你完成建议的修改过程后,它将把输出保存到JSONL文件中,准备进行微调。

创建一个微调的模型

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

使用OpenAI CLI开始你的微调工作:

openai api fine_tunes.create -t <TRAIN_FILE_ID_OR_PATH> -m <BASE_MODEL>
1

其中BASE_MODEL是你的基础模型的名称(ada、babbage、curie或davinci)。你可以使用后缀参数来定制你的微调模型的名称。

运行上述命令可以做几件事:

  1. 使用文件APIopen in new window上传文件(或使用已经上传的文件)。
  2. 创建一个微调作业
  3. 流动事件,直到作业完成(这通常需要几分钟,但如果队列中有许多作业或你的数据集很大,可能需要几个小时)。

每个微调工作都从一个基本模型开始,默认为Curie。模型的选择影响着模型的性能和运行微调模型的成本。你的模型可以是:AdaBabbageCurieDavinci之一。请访问我们的定价页面open in new window,了解微调费用的细节。

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

openai api fine_tunes.follow -i <YOUR_FINE_TUNE_JOB_ID>
1

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

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

# List all created fine-tunes
openai api fine_tunes.list

# Retrieve the state of a fine-tune. The resulting object includes
# job status (which can be one of pending, running, succeeded, or failed)
# and other information
openai api fine_tunes.get -i <YOUR_FINE_TUNE_JOB_ID>

# Cancel a job
openai api fine_tunes.cancel -i <YOUR_FINE_TUNE_JOB_ID>
1
2
3
4
5
6
7
8
9
10

使用一个微调的模型

当一个作业成功后,fine_tuned_model字段将被填充为模型的名称。你现在可以指定这个模型作为我们的完成s APIopen in new window的参数,并使用Playgroundopen in new window向它发出请求。

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

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

OpenAI CLI:

openai api 完成s.create -m <FINE_TUNED_MODEL> -p <YOUR_提示>
1

cURL:

curl https://api.openai.com/v1/完成s \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"提示": YOUR_提示, "model": FINE_TUNED_MODEL}'
1
2
3
4

Python:

import openai
openai.完成.create(
    model=FINE_TUNED_MODEL,
    提示=YOUR_提示)
1
2
3
4

Node.js:

const response = await openai.create完成({
  model: FINE_TUNED_MODEL
  提示: YOUR_提示,
});
1
2
3
4

你可以继续在这些请求上使用所有其他的完成度open in new window参数,如temperaturefrequency_penaltypresence_penalty等,以微调模型。

删除一个微调的模型

要删除一个微调模型,你必须在你的组织内被指定为 "owner"。

OpenAI CLI:

openai api models.delete -i <FINE_TUNED_MODEL>
1

cURL:

curl -X "DELETE" https://api.openai.com/v1/models/<FINE_TUNED_MODEL> \
  -H "Authorization: Bearer $OPENAI_API_KEY"
1
2

Python:

import openai
openai.Model.delete(FINE_TUNED_MODEL)
1
2

准备你的数据集

微调是一种强大的技术,可以创建一个针对你的用例的新模型。在微调你的模型之前,我们强烈建议你阅读下面这些最佳实践和针对你的用例的具体准则

数据格式化

为了微调一个模型,你需要一组训练实例,每个实例由一个输入("提示")和其相关的输出("完成")组成。这与使用我们的基础模型明显不同,在那里你可能会在一个提示中输入详细的指令或多个例子。

  • 每个提示应该以一个固定的分隔符结束,以告知模型提示何时结束,完成何时开始。一般来说,一个简单的分隔符效果很好,就是\n\n###\n\n。分隔符不应该出现在任何提示中的其他地方。

  • 由于我们的标记化open in new window,每个完成都应该以一个空格开始,因为我们的标记化是以前面的空格来标记大多数的单词。

  • 每个完成都应该以一个固定的停止序列结束,以告知模型完成何时结束。停止序列可以是 \n, ###, 或任何其他不出现在任何完成中的token。

  • 对于推理,你应该以创建训练数据集时的相同方式格式化你的提示,包括相同的分隔符。同时指定相同的停止序列以正确截断完成。

一般的最佳做法

微调在更多高质量的例子中表现得更好。为了微调一个模型,比使用高质量的提示与我们的基础模型表现更好,你应该提供至少几百个高质量的例子,最好是由人类专家审核的。从这里开始,性能往往随着例子数量的每增加一倍而线性增加。增加例子的数量通常是提高性能的最好和最可靠的方法。

分类器是最容易上手的模型。对于分类问题,我们建议使用ada,一旦经过微调,它的性能通常只比能力更强的模型差一点,同时速度明显更快,成本也更低。

如果你是在一个预先存在的数据集上进行微调,而不是从头开始写提示,如果可能的话,一定要手动审查你的数据是否有攻击性或不准确的内容,如果数据集很大,则要尽可能多地审查随机样本。

具体准则

微调可以解决各种问题,而使用微调的最佳方式可能取决于你的具体用例。下面,我们列出了微调的最常见的使用情况和相应的准则。

分类

在分类问题中,提示中的每个输入都应该被归入预定义的类别之一。对于这种类型的问题,我们建议:

  • 在提示的最后使用一个分隔符,例如:\n\n###\n\n。当你最终向你的模型提出请求时,记得也要附加上这个分隔符。
  • 选择能映射到单个tokenopen in new window的类。在推理时,指定max_tokens=1,因为你只需要第一个token进行分类。
  • 确保 提示+完成 不超过2048个token,包括分隔符。
  • 争取每个类别至少有~100个例子
  • 为了得到类的对数概率,你可以在使用你的模型时指定logprobs=5(用于5个类别)。
  • 确保用于微调的数据集在结构和任务类型上与模型将被使用的非常相似。
案例研究:该模型是否做出了不真实的陈述?

比方说,你想确保你网站上的广告文字提到正确的产品和公司。换句话说,你想确保模型不会胡编乱造。你可能想微调一个分类器,过滤掉不正确的广告。

该数据集可能看起来像下面的东西:

{"提示":"Company: BHFF insurance\nProduct: allround insurance\nAd:One stop shop for all your insurance needs!\nSupported:", "完成":" yes"}
{"提示":"Company: Loft conversion specialists\nProduct: -\nAd:Straight teeth in weeks!\nSupported:", "完成":" no"}
1
2

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

对于这个用例,我们微调了一个ada模型,因为它将更快、更便宜,而且性能将与较大的模型相媲美,因为它是一个分类任务。

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

curl https://api.openai.com/v1/完成s \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -d '{
    "提示": "Company: Reliable accountants Ltd\nProduct: Personal Tax help\nAd:Best advice in town!\nSupported:",
    "max_tokens": 1,
    "model": "YOUR_FINE_TUNED_MODEL_NAME"
  }'
1
2
3
4
5
6
7
8

这将返回yesno

案例研究:感情分析

比方说,你想得到某条推特的积极或消极程度。该数据集可能看起来像下面这样:

{"提示":"Overjoyed with the new iPhone! ->", "完成":" positive"}
{"提示":"@lakers disappoint for a third straight night https://t.co/38EFe43 ->", "完成":" negative"}
1
2

一旦模型被微调,你可以通过在完成请求中设置logprobs=2来获得第一个完成token的对数概率。正类的概率越高,相对情绪越高。

现在我们可以通过提出一个完成请求来查询我们的模型。

curl https://api.openai.com/v1/完成s \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -d '{
    "提示": "https://t.co/f93xEd2 Excited to share my latest blog post! ->",
    "max_tokens": 1,
    "model": "YOUR_FINE_TUNED_MODEL_NAME"
  }'
1
2
3
4
5
6
7
8

它将返回:

{
  "id": "cmpl-完成_ID",
  "object": "text_完成",
  "created": 1589498378,
  "model": "YOUR_FINE_TUNED_MODEL_NAME",
  "choices": [
    {
      "logprobs": {
        "text_offset": [
          19
        ],
        "token_logprobs": [
          -0.03597255
        ],
        "tokens": [
          " positive"
        ],
        "top_logprobs": [
          {
            " negative": -4.9785037,
            " positive": -0.03597255
          }
        ]
      },

      "text": " positive",
      "index": 0,
      "finish_reason": "length"
    }
  ]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
案例研究:邮件分流的分类

比方说,你想把收到的邮件归入大量预定义的类别中。对于分类到大量的类别,我们建议你将这些类别转换成数字,这将很好地工作到~500个类别。我们观察到,由于标记化的原因,在数字前添加一个空格有时会对性能略有帮助。你可能想把你的训练数据结构化,如下:

{"提示":"Subject: <email_subject>\nFrom:<customer_name>\nDate:<date>\nContent:<email_body>\n\n###\n\n", "完成":" <numerical_category>"}
1

比如说:

{"提示":"Subject: Update my address\nFrom:Joe Doe\nTo:support@ourcompany.com\nDate:2021-06-03\nContent:Hi,\nI would like to update my billing address to match my delivery address.\n\nPlease let me know once done.\n\nThanks,\nJoe\n\n###\n\n", "完成":" 4"}
1

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

有条件的生成

条件性生成是一个需要在给定某种输入的情况下生成内容的问题。这包括转述、总结、实体提取、给定规格的产品描述写作、聊天机器人和许多其他问题。对于这种类型的问题,我们建议:

  • 在提示的最后使用一个分隔符,例如:\n\n###\n\n。当你最终向你的模型提出请求时,记得也要追加这个分隔符。
  • 在完成度的末尾使用一个结束符,例如:END
  • 在推理过程中,记得将结束token作为一个停止序列加入,例如stop=[" END"]
  • 争取至少有~500个例子
  • 确保提示+完成语不超过2048个token,包括分隔符
  • 确保实例具有较高的质量并遵循相同的预期格式
  • 确保用于微调的数据集在结构和任务类型上与模型将被使用的非常相似。
  • 对于这些用例,使用较低的学习率和仅1-2个历时往往效果更好。
案例研究:根据维基百科上的文章写一个吸引人的广告

这是一个生成性用例,所以你要确保你提供的样本是最高质量的,因为微调后的模型将试图模仿所给的例子的风格(和错误)。一个好的起点是500个左右的例子。一个样本数据集可能看起来像这样:

{"提示":"<Product Name>\n<Wikipedia description>\n\n###\n\n", "完成":" <engaging ad> END"}
1

例子:

{"提示":"Samsung Galaxy Feel\nThe Samsung Galaxy Feel is an Android smartphone developed by Samsung Electronics exclusively for the Japanese market. The phone was released in June 2017 and was sold by NTT Docomo. It runs on Android 7.0 (Nougat), has a 4.7 inch display, and a 3000 mAh battery.\nSoftware\nSamsung Galaxy Feel runs on Android 7.0 (Nougat), but can be later updated to Android 8.0 (Oreo).\nHardware\nSamsung Galaxy Feel has a 4.7 inch Super AMOLED HD display, 16 MP back facing and 5 MP front facing cameras. It has a 3000 mAh battery, a 1.6 GHz Octa-Core ARM Cortex-A53 CPU, and an ARM Mali-T830 MP1 700 MHz GPU. It comes with 32GB of internal storage, expandable to 256GB via microSD. Aside from its software and hardware specifications, Samsung also introduced a unique a hole in the phone's shell to accommodate the Japanese perceived penchant for personalizing their mobile phones. The Galaxy Feel's battery was also touted as a major selling point since the market favors handsets with longer battery life. The device is also waterproof and supports 1seg digital broadcasts using an antenna that is sold separately.\n\n###\n\n", "完成":"Looking for a smartphone that can do it all? Look no further than Samsung Galaxy Feel! With a slim and sleek design, our latest smartphone features high-quality picture and video capabilities, as well as an award winning battery life. END"}
1

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

案例研究:实体提取

这类似于一个语言转换任务。为了提高性能,最好是将不同的提取的实体按字母顺序或按它们在原文中出现的顺序进行排序。这将有助于模型按顺序跟踪所有需要生成的实体。该数据集可以如下:

{"提示":"<any text, for example news article>\n\n###\n\n", "完成":" <list of entities, separated by a newline> END"}
1

例子:

{"提示":"Portugal will be removed from the UK's green travel list from Tuesday, amid rising coronavirus cases and concern over a \"Nepal mutation of the so-called Indian variant\". It will join the amber list, meaning holidaymakers should not visit and returnees must isolate for 10 days...\n\n###\n\n", "完成":" Portugal\nUK\nNepal mutation\nIndian variant END"}
1

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

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

聊天机器人通常会包含关于对话的相关背景(订单细节),到目前为止的对话摘要以及最近的信息。对于这个用例,同一个过去的对话可以在数据集中产生多行,每次都有稍微不同的上下文,对于每个代理的生成都是一种完成。这个用例需要几千个例子,因为它可能会处理不同类型的请求,以及客户问题。为了确保性能的高质量,我们建议对对话样本进行审核,以确保代理信息的质量。摘要可以用一个单独的文本转换微调模型来生成。数据集可以看起来如下:

{"提示":"Summary: <summary of the interaction so far>\n\nSpecific information:<for example order details in natural language>\n\n###\n\nCustomer: <message1>\nAgent: <response1>\nCustomer: <message2>\nAgent:", "完成":" <response2>\n"}
{"提示":"Summary: <summary of the interaction so far>\n\nSpecific information:<for example order details in natural language>\n\n###\n\nCustomer: <message1>\nAgent: <response1>\nCustomer: <message2>\nAgent: <response2>\nCustomer: <message3>\nAgent:", "完成":" <response3>\n"}
1
2

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

案例研究:基于技术特性清单的产品描述

在这里,重要的是将输入的数据转换为自然语言,这将可能导致卓越的性能。例如,下面的格式:

{"提示":"Item=handbag, Color=army_green, price=$99, size=S->", "完成":" This stylish small green handbag will add a unique touch to your look, without costing you a fortune."}
1

不会有好的效果:

{"提示":"Item is a handbag. Colour is army green. Price is midrange. Size is small.->", "完成":" This stylish small green handbag will add a unique touch to your look, without costing you a fortune."}
1

为了获得较高的性能,确保完成的内容是基于所提供的描述。如果经常查阅外部内容,那么以自动的方式添加这些内容会提高性能。如果描述是基于图片的,那么使用一种算法来提取图片的文字描述可能会有帮助。由于完成只有一句话长,我们可以在推理过程中使用.作为停止序列。

高级用法

定制你的模型名称

你可以使用后缀open in new window参数为你的微调模型名称添加一个最多 40 个字符的后缀。

OpenAI CLI:

openai api fine_tunes.create -t test.jsonl -m ada --suffix "custom model name"
1

由此产生的名称将是:

ada:ft-your-org:custom-model-name-2022-02-15-04-21-04
1

分析你的微调模型

每项工作完成后,我们都会给它附加一个结果文件。当你检索微调时,这个结果文件的ID将被列出,当你查看微调的事件时也是如此。你可以下载这些文件:

OpenAI CLI:

openai api fine_tunes.results -i <YOUR_FINE_TUNE_JOB_ID>
1

CURL:

curl https://api.openai.com/v1/files/$RESULTS_FILE_ID/content \
  -H "Authorization: Bearer $OPENAI_API_KEY" > results.csv
1
2

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

  • elapsed_tokens: 到目前为止,该模型已经看到的token的数量(包括重复)。
  • elapsed_examples: 模型到目前为止看到的例子的数量(包括重复),其中一个例子是你的批次中的一个元素。例如,如果 batch_size = 4,每一步都会使 elapsed_examples 增加 4。
  • training_loss: 训练批次的损失。
  • training_sequence_accuracy: 在训练批中,模型预测的token与真实完成的token完全匹配的完成度百分比。例如,在 batch_size 为 3 的情况下,如果你的数据包含完成度 [[1, 2], [0, 5], [4, 2]] 而模型预测 [[1, 1], [0, 5], [4, 2]] ,这个准确性将是 2/3 = 0.67
  • training_token_accuracy: 训练批中被模型正确预测的token的百分比。例如,在 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:

# For multiclass classification
openai api fine_tunes.create \
  -t <TRAIN_FILE_ID_OR_PATH> \
  -v <VALIDATION_FILE_OR_PATH> \
  -m <MODEL> \
  --compute_classification_metrics \
  --classification_n_classes <N_CLASSES>

# For binary classification
openai api fine_tunes.create \
  -t <TRAIN_FILE_ID_OR_PATH> \
  -v <VALIDATION_FILE_OR_PATH> \
  -m <MODEL> \
  --compute_classification_metrics \
  --classification_n_classes 2 \
  --classification_positive_class <POSITIVE_CLASS_FROM_DATASET>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

如果你设置了 --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

请注意,这些评估假设你使用的是文本标签,如上文所述,这些标签被token为一个单一的token。如果这些条件不成立,你得到的数字就可能是错误的。

验证

你可以保留一些数据用于验证。验证文件的格式与训练文件完全相同,你的训练和验证数据应该是相互排斥的。

如果你在创建微调作业时包含一个验证文件,那么生成的结果文件将包括对微调模型在训练期间定期对验证数据的表现的评估。

OpenAI CLI:

openai api fine_tunes.create -t <TRAIN_FILE_ID_OR_PATH> \
  -v <VALIDATION_FILE_ID_OR_PATH> \
  -m <MODEL>
1
2
3

如果你提供了一个验证文件,我们会在训练时间内定期对成批的验证数据计算指标。在你的结果文件中,你会看到以下额外的度量:

  • validation_loss: 验证批次的损失
  • validation_sequence_accuracy: 在验证批中,模型预测的token与真实完成的token完全匹配的百分比。例如,在 batch_size 为 3 的情况下,如果你的数据包含完成度 [[1, 2], [0, 5], [4, 2]] 而模型预测 [[1, 1], [0, 5], [4, 2]] ,这个准确率将是 2/3 = 0.67
  • validation_token_accuracy: 验证批中被模型正确预测的token的百分比。例如,在 batch_size 为 3 的情况下,如果你的数据包含完成 [[1, 2], [0, 5], [4, 2]] 而模型预测为 [[1, 1], [0, 5], [4, 2]] ,这个准确率将是 5/6 = 0.83

超参数

我们已经挑选了默认的超参数,这些参数在一系列的使用情况下都能很好地工作。唯一需要的参数是训练文件。

也就是说,调整用于微调的超参数往往可以使模型产生更高质量的输出。特别是,你可能想配置以下内容:

  • model:要微调的基本模型的名称。你可以选择 "ada"、"babbage"、"curie "或 "davinci "中的一个。要了解这些模型的更多信息,请看模型文档open in new window
  • n_epochs - 默认为4。 训练模型的epochs数量。一个epoch指的是训练数据集的一个完整周期。
  • batch_size - 默认为训练集中实例数量的~0.2%,上限为256。批量大小是用于训练单个前向和后向通道的训练例子的数量。一般来说,我们发现较大的批处理量对于较大的数据集来说往往效果更好。
  • learning_rate_multiplier - 默认为0.05、0.1或0.2,取决于最终的batch_size。微调后的学习率是用于预训练的原始学习率乘以这个乘数。我们建议在0.02到0.2的范围内进行试验,看看什么能产生最好的结果。根据经验,我们发现较大的学习率通常在较大的批次规模下表现更好。
  • compute_classification_metrics - 默认为False。如果是 "真",为了对分类任务进行微调,在每个历时结束时对验证集计算特定的分类指标(准确性、F-1得分等)。

要配置这些额外的超参数,可以通过OpenAI CLI上的命令行标志传入,比如说:

openai api fine_tunes.create \
  -t file-JD89ePi5KMsB3Tayeli5ovfW \
  -m ada \
  --n_epochs 1
1
2
3
4

从微调的模型中继续进行微调

如果你已经为你的任务微调了一个模型,现在又有了你想纳入的额外训练数据,你可以继续从模型中进行微调。这将创建一个从所有训练数据中学习的模型,而不必从头开始重新训练。

要做到这一点,在创建一个新的微调任务时,传入微调模型的名称(例如,-m curie:ft-\<org\>-\<date\>)。其他训练参数不必改变,但是如果你的新训练数据比以前的训练数据小得多,你可能会发现将learning_rate_multiplier减少2到4倍是很有用的。

权重和偏差

你可以将你的微调与权重和偏差open in new window同步,以跟踪实验、模型和数据集。

要开始,你需要一个权重和偏差open in new window账户和一个付费的OpenAI计划。为了确保你使用的是openaiwandb的最新版本,请运行:

pip install --upgrade openai wandb
1

要将你的微调与Weights & Biases同步,请运行:

openai wandb sync
1

你可以阅读权重和偏差文档open in new window,以了解有关这一整合的更多信息。

示例笔记本

分类

finetuning-classification.ipynbopen in new window

本笔记本将演示如何对一个模型进行微调,该模型可以对一段输入文本是否与棒球或曲棍球有关进行分类。我们将在本笔记本open in new window中分四步完成这项任务:

  • 数据探索 将给出数据源的概述和一个例子的样子
  • 数据准备 将把我们的数据源变成一个jsonl文件,可以用来进行微调
  • 微调 将启动微调工作,并解释所产生的模型的性能。
  • 使用模型 将展示向微调模型提出请求以获得预测结果。

问题的回答

olympics-1-collect-data.ipynbopen in new window

olympics-2-create-qa.ipynbopen in new window

olympics-3-train-qa.ipynbopen in new window

这个项目的想法是创建一个问题回答模型,基于几段提供的文本。当答案包含在段落中时,基本的GPT-3模型在回答问题方面做得很好,然而,如果答案不包含在段落中,基本的模型倾向于尽力去回答,常常导致混乱的答案。

为了创建一个只有在有足够的背景时才回答问题的模型,我们首先创建了一个基于文本段落的问题和答案的数据集。为了训练模型只在有答案的情况下进行回答,我们还添加了对抗性的例子,即问题与上下文不匹配的情况。在这些情况下,我们要求模型输出 "没有足够的背景来回答这个问题"。

我们将在三个笔记本中执行这项任务:

  1. 第一个笔记本open in new window侧重于收集最近的数据,GPT-3在它的预训练中没有看到这些数据。我们选择了2020年奥运会的主题(实际上是在2021年夏天举行的),并下载了713个独特的页面。我们将数据集按各个部分组织起来,这将作为提出和回答问题的背景。
  2. 第二个笔记本open in new window将利用Davinci-instruct,根据维基百科的某一章节提出一些问题,并根据该章节回答这些问题。
  3. 第三个笔记本open in new window将利用上下文、问题和答案对的数据集,另外创建对抗性问题和上下文对,其中问题不是在该上下文中产生的。在这些情况下,模型将被提示回答 "没有足够的背景来回答这个问题"。我们还将训练一个判别器模型,它可以预测问题是否可以根据上下文来回答。
Last Updated:
Contributors: lanheixingkong