天天看点

了解如何使用 OpenAI API 和 Python 定制高级神经网络模型

GPT-3,第三代Generative Pre-trained Transformer, 是OpenAI打造的前沿神经网络深度学习模型。 通过使用大量互联网数据,GPT-3 可以用最少的输入生成多样化和强大的机器生成文本。 GPT-3 的应用范围广泛,不仅限于文本摘要、翻译、聊天机器人开发和内容生成。

尽管 GPT-3 具有鲁棒性,但可以通过针对特定用例对其进行微调来进一步提高 GPT-3 的性能。

但是我们所说的微调是什么意思?

这是在自定义用例数据集上训练预训练 GPT-3 的过程,使模型能够更好地适应特定用例或领域的细微差别,从而获得更准确的结果。

成功执行微调的先决条件是

(1) 对 Python 编程有基本的了解

(2) 熟悉机器学习和自然语言处理。

下面介绍使用 Python 在自己的数据上微调 GPT-3 模型的过程,涵盖从获取 API key创建到准备数据、训练模型和验证模型的所有步骤。

哪些 GPT 模型可以微调?

可以微调的 GPT 模型包括 Ada、Babbage、Curie 和 Davinci。 这些模型属于 GPT-3 系列。 此外,需要注意的是,微调目前不适用于更新的 GPT-3.5-turbo 模型或其他 GPT-4。

微调 GPT 的应用场景有哪些?

分类和条件生成是可以从微调 GPT-3 等语言模型中受益的两类问题。

分类

对于分类问题,提示中的每个输入都被分配了一个预定义的类,下面说明了一些情况:

  • 确保真实陈述:如果一家公司想要验证其网站上的广告是否提及了正确的产品和公司,则可以对分类器进行微调以过滤掉不正确的广告,确保模型没有胡编乱造。
  • 情绪分析:这涉及根据情绪对文本进行分类,例如正面、负面或中性。
  • 电子邮件分类:要将收到的电子邮件分类为许多预定义类别之一。

条件生成

此类别中的问题涉及基于给定输入生成内容。 应用程序包括解释、总结、实体提取、产品描述编写、虚拟助手(聊天机器人)等。 例子包括:

  • 根据维基百科文章制作引人入胜的广告。 在此用例中,确保提供的样本是高质量的,因为微调模型将尝试模仿示例的风格。
  • 实体提取。 此任务类似于语言转换问题。 通过按字母顺序或按照它们在原始文本中出现的相同顺序对提取的实体进行排序来提高性能。
  • 客户支持聊天机器人。 聊天机器人通常包括有关对话的相关上下文(订单详细信息)、到目前为止的对话摘要以及最新消息。

微调 GPT-3 的步骤

必须创建 OpenAI 开发者帐户才能访问 API 密钥,步骤如下:

首先,从 OpenAI 官方网站 创建一个帐户。

然后,选择右上角的用户配置文件图标并单击“查看 API 密钥”以访问创建新 API 密钥或使用现有 API 密钥的页面。

了解如何使用 OpenAI API 和 Python 定制高级神经网络模型

通过提供有意义的名称(在本例中)从“Create new secret key”选项卡创建新密钥 GPT3_fine_tuning_key ,然后自动生成 API 密钥。

了解如何使用 OpenAI API 和 Python 定制高级神经网络模型
了解如何使用 OpenAI API 和 Python 定制高级神经网络模型

数据集

我们将针对问答场景微调 GPT-3 模型,该场景包含结构化的问答模式,旨在帮助模型理解模型需要执行的任务。 整个训练和测试数据中的每对问题和答案都保持一致的格式。

问答数据集格式:

{
"prompt": "my prompt ->",
"completion": "the answer of the prompt. \n"
}           
  • “prompt”是模型读取和处理的输入文本。 主要分隔符是箭头符号 (->),用于将提示与预期响应区分开来。
  • “completion”是对提示的预期响应。 反斜杠“\n”符号用作停止序列以指示答案的结束。

通过对数据集格式的理解,我们可以生成训练和验证数据集,如下所示。 这些提示和完成是使用 ChatGPT 生成的。

training_data = [
        {
            "prompt": "What is the capital of France?->",
            "completion": """ The capital of France is Paris.\n"""
        },
        {
            "prompt": "What is the primary function of the heart?->",
            "completion": """ The primary function of the heart is to pump blood throughout the body.\n"""
        },
        {
            "prompt": "What is photosynthesis?->",
            "completion": """ Photosynthesis is the process by which green plants and some other organisms convert sunlight into chemical energy stored in the form of glucose.\n"""
        },
        {
            "prompt": "Who wrote the play 'Romeo and Juliet'?->",
            "completion": """ William Shakespeare wrote the play 'Romeo and Juliet'.\n"""
        },
        {
            "prompt": "Which element has the atomic number 1?->",
            "completion": """ Hydrogen has the atomic number 1.\n"""
        },
        {
            "prompt": "What is the largest planet in our solar system?->",
            "completion": """ Jupiter is the largest planet in our solar system.\n"""
        },
        {
            "prompt": "What is the freezing point of water in Celsius?->",
            "completion": """ The freezing point of water in Celsius is 0 degrees.\n"""
        },
        {
            "prompt": "What is the square root of 144?->",
            "completion": """ The square root of 144 is 12.\n"""
        },
        {
            "prompt": "Who is the author of 'To Kill a Mockingbird'?->",
            "completion": """ The author of 'To Kill a Mockingbird' is Harper Lee.\n"""
        },
        {
            "prompt": "What is the smallest unit of life?->",
            "completion": """ The smallest unit of life is the cell.\n"""
        }
]

validation_data = [
        {
            "prompt": "Which gas do plants use for photosynthesis?->",
            "completion": """ Plants use carbon dioxide for photosynthesis.\n"""
        },
        {
            "prompt": "What are the three primary colors of light?->",
            "completion": """ The three primary colors of light are red, green, and blue.\n"""
        },
        {
            "prompt": "Who discovered penicillin?->",
            "completion": """ Sir Alexander Fleming discovered penicillin.\n"""
        },
        {
            "prompt": "What is the chemical formula for water?->",
            "completion": """ The chemical formula for water is H2O.\n"""
        },
        {
            "prompt": "What is the largest country by land area?->",
            "completion": """ Russia is the largest country by land area.\n"""
        },
        {
            "prompt": "What is the speed of light in a vacuum?->",
            "completion": """ The speed of light in a vacuum is approximately 299,792 kilometers per second.\n"""
        },
        {
            "prompt": "What is the currency of Japan?->",
            "completion": """ The currency of Japan is the Japanese Yen.\n"""
        },
        {
            "prompt": "What is the smallest bone in the human body?->",
            "completion": """ The stapes, located in the middle ear, is the smallest bone in the human body.\n"""
        }
]           

基础配置

我们需要通过安装必要的库来准备工作环境,尤其是 OpenAI Python 库,如下所示:

pip install openai           
import openai           

准备数据集

如上所示,处理列表格式对于小型数据集可能很方便。 以 JSONL(JSON 行)格式保存数据有几个好处, 好处包括可扩展性、互操作性、简单性以及与 OpenAI API 的兼容性,OpenAI API 在创建微调作业时需要 JSONL 格式的数据。

以下代码利用辅助函数 prepare_data 以 JSONL 格式创建训练和验证数据:

import json

training_file_name = "training_data.jsonl"
validation_file_name = "validation_data.jsonl"

def prepare_data(dictionary_data, final_file_name):
    
        with open(final_file_name, 'w') as outfile:
            for entry in dictionary_data:
                json.dump(entry, outfile)
                outfile.write('\n')

prepare_data(training_data, "training_data.jsonl")
prepare_data(validation_data, "validation_data.jsonl")           

在 notebook 中,可以对训练数据和验证数据使用以下语句来完成数据集的准备。

!openai tools fine_tunes.prepare_data -f "training_data.jsonl"
!openai tools fine_tunes.prepare_data -f "validation_data.jsonl"           

最后,我们将这两个数据集上传到OpenAI开发者账号,如下:

training_file_id = upload_data_to_OpenAI(training_file_name)
validation_file_id = upload_data_to_OpenAI(validation_file_name)

print(f"Training File ID: {training_file_id}")
print(f"Validation File ID: {validation_file_id}")           

前面代码的成功执行后,会显示训练和验证数据的唯一标识符。

了解如何使用 OpenAI API 和 Python 定制高级神经网络模型

创建微调作业

这个微调过程很大程度上受到了 openai-cookbook 在 Microsoft Azure 上进行微调的启发。

为了执行微调,我们将使用以下两个步骤:

(1) 定义超参数

(2) 触发微调

我们将微调 davinci 模型并使用训练和验证数据集使用 3 的批量大小和 0.3 的学习率,运行 15 个 epoch。

create_args = {
        "training_file": training_file_id,
        "validation_file": validation_file_id,
        "model": "davinci",
        "n_epochs": 15,
        "batch_size": 3,
        "learning_rate_multiplier": 0.3
}

response = openai.FineTune.create(**create_args)
job_id = response["id"]
status = response["status"]

print(f'Fine-tunning model with jobID: {job_id}.')
print(f"Training Response: {response}")
print(f"Training Status: {status}")           

上面的代码为 jobID ( ft-CfuVdcqEYfPcbLPbbnVnd2kh )任务,会生成以下信息。

了解如何使用 OpenAI API 和 Python 定制高级神经网络模型
了解如何使用 OpenAI API 和 Python 定制高级神经网络模型

我们可以通过运行以下代码来更深入地了解训练过程:

import signal
import datetime

def signal_handler(sig, frame):
        status = openai.FineTune.retrieve(job_id).status
        print(f"Stream interrupted. Job is still {status}.")
        return

print(f'Streaming events for the fine-tuning job: {job_id}')
signal.signal(signal.SIGINT, signal_handler)

events = openai.FineTune.stream_events(job_id)
try:
        for event in events:
            print(f'{datetime.datetime.fromtimestamp(event["created_at"])} {event["message"]}')

except Exception:
        print("Stream interrupted (client disconnected).")           

下面生成了所有的 epoch,以及微调的状态,即成功。

了解如何使用 OpenAI API 和 Python 定制高级神经网络模型

检查微调作业状态

验证我们的操作是否成功

import time

status = openai.FineTune.retrieve(id=job_id)["status"]
if status not in ["succeeded", "failed"]:
        print(f'Job not in terminal status: {status}. Waiting.')
        while status not in ["succeeded", "failed"]:
            time.sleep(2)
            status = openai.FineTune.retrieve(id=job_id)["status"]
            print(f'Status: {status}')
else:
        print(f'Finetune job {job_id} finished with status: {status}')

print('Checking other finetune jobs in the subscription.')
result = openai.FineTune.list()
print(f'Found {len(result.data)} finetune jobs.')           

执行结果如下:

null

There is a total of 27 finetune jobs.

模型的验证

最后,可以从“fine_tuned_model”属性中检索微调模型。 以下打印语句显示最终模式的名称是: curie:ft-personal-2023-05-04-15-54-08

# Retrieve the finetuned model
fine_tuned_model = result.fine_tuned_model
print(fine_tuned_model)           
了解如何使用 OpenAI API 和 Python 定制高级神经网络模型

使用此模型,我们通过提供提示、模型名称并使用该函数创建查询来验证其结果 openai.Completion.create() 。

检索结果如下:

new_prompt = "Which part is the smallest bone in the entire human body?"
answer = openai.Completion.create(
  model=fine_tuned_model,
  prompt=new_prompt
)

print(answer['choices'][0]['text'])

new_prompt = """ Which type of gas is utilized by plants during the process of photosynthesis?"""
answer = openai.Completion.create(
  model=fine_tuned_model,
  prompt=new_prompt
)

print(answer['choices'][0]['text'])           

尽管提示的书写方式与验证数据集中的不完全相同,但模型仍设法将它们映射到正确答案。 对先前请求的答复如下所示。

了解如何使用 OpenAI API 和 Python 定制高级神经网络模型

通过很少的训练样本,我们拥有了一个不错的微调模型,当然 更大的训练规模可以获得更好的结果。