天天看點

了解如何使用 OpenAI API 和 Python 定制進階神經網絡模型

作者:HuggingFace

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 定制進階神經網絡模型

通過很少的訓練樣本,我們擁有了一個不錯的微調模型,當然 更大的訓練規模可以獲得更好的結果。