【Python】ChatGPTのファインチューニング(Fine-Tuning)実践方法|特定のタスクに特化したモデル作成

当ページには広告が含まれています。

こんにちは、DXCEL WAVEの運営者(@dxcelwave)です!

こんな方におすすめ!
  • ChatGPTのファインチューニングに興味がある
  • OpenAI APIとPythonを用いてファインチューニングを実践する方法が知りたい
目次

【OpenAI】ChatGPTとは?

ChatGPTとは、OpenAIが開発した対話型チャットボットのモデルです。ChatGPTの名前は、GPT-3という第3世代の生成言語モデルに由来しています。

ChatGPTのモデルには、人工知能(AI)が搭載されており、人間の発話に対して自然なやり取りを可能にしています。また、英語をはじめ、中国語、日本語、フランス語など複数言語を認識し、人間らしく応答できるのも特徴的です。

さらに、ChatGPTではチャットの他に、画像生成など近年多様な機能がリリースされてます。以下、ChatGPTで代表するGPTモデルおよびOpenAIが提供するAPI機能一覧を示します。

  • チャット機能
  • テキストから画像を生成
  • オーディオを文字起こし
  • Python、SQL、JavaScript等のコードを理解
  • 問題あるネガティブ発言検出
  • テキスト文章のベクトル変換

【参考】OpenAI社のAPI利用方法

本記事ではChatGPTを用いたPythonプログラミングについて解説します。その際、Open AIが提供するAPI情報が必要になります。「ChatGPTの概要」および「API情報の取得手順」については、こちらの記事で詳しく解説しています。

あわせて読みたい
【Python×ChatGPT】チャットボット作成入門|OpenAI APIの利用申請手順も解説 「ChatGPT APIの利用手順」と「PythonでChatGPT APIを呼び出し、チャットボットを作成する方法」についてそれぞれ解説します。

【参考】ChatGPTを詳しく学びたい方向けの学習講座

ChatGPTを詳しく学びたい方向けに安価で学べるオンライン講座も併せてご紹介します。

【ChatGPT】ファインチューニングとは?

ChatGPTのファインチューニングとは、既に学習済みの大規模な言語モデルであるGPT(Generative Pre-trained Transformer)を、特定のタスクに最適化することを指します。

例えば、医療・金融・製造など特定の業界の専門用語にも特化したモデル等を作成する際に有効です。

一般的に、ChatGPTは自然言語処理タスクに適したモデルであり、多くの場合、チャットボットや会話システムの開発に使用されます。しかし、ChatGPTを特定のタスクに最適化するには、そのタスクに関連する学習データを使用して、モデルを再学習する必要があります。

ファインチューニングにより、ChatGPTはより高度な自然言語処理タスクを実行できるようになり、より高い精度で応答を生成することが期待できるようになります。

【事前準備】Python環境構築・ファインチューニング用学習データ準備

OpenAIが提供するAPIを用いてPythonでChatGPTのファインチューニングを実践するに際して、以下2点事前に対応する必要があります。

  • OpenAIライブラリのインストール
  • 【必須】ファインチューニング用学習データの準備
  • 【任意】ファインチューニング用検証データの準備

OpenAIライブラリのインストール

今回言及する翻訳機能実装に際して、OpenAI提供のChatGPT APIをPython環境で利用できるライブラリが必要になります。

コマンドプロンプト(WIndows)またはターミナル(Mac)を用いてインストールしましょう。

pip install openai

【必須】ファインチューニング用学習データの準備

ChatGPTモデルのファインチューニング実践に際して、学習用のデータを準備します。

学習用データのフォーマット(JSONL)

学習用データは、以下に示すフォーマットのもとJSONLファイル形式で準備します。

promptの値には質問文、completionの値には回答文を準備します。

{"prompt": "", "completion": ""}
{"prompt": "", "completion": ""}
{"prompt": "", "completion": ""}
・・・

学習用サンプルデータ

後続のPythonプログラム実践に際して、ファインチューニング用サンプルデータ(training.jsonl)を次のように準備することとします。

{"prompt": "「DXCEL WAVE」とは?", "completion": "DXCEL WAVEとは、DX推進に関連する記事を多数投稿しているメディアです。"}
{"prompt": "「DXCEL WAVE」の記事から学べるChatGPTの内容とは?", "completion": "DXCELWEVEでは、OpenAIが提供するAPIの利用方法・PythonによるChatGPTモデルの活用方法が学習できます。"}

※ChatGPTモデル精度の良い回答を得るには、ファインチューニング用のデータを数百行程度用意するのが良いとされています。今回はファインチューニングの方法論解説を目的とするため上記2行のみのデータを用いたいと思います。

【任意】ファインチューニング用検証データの準備

ファインチューニングプロセスで検証データも併せて渡すと、モデル性能の細かなチューニングも実施することができます。検証用データは必須ではないため、一旦無くてもファインチューニング自体は可能です。

検証データも学習データ同様にJSONL形式で次のようなフォーマットとして準備します。

{"prompt": "", "completion": ""}
{"prompt": "", "completion": ""}
{"prompt": "", "completion": ""}
・・・

ChatGPTモデルのファインチューニングをPythonで実践

それでは実際にPythonプログラムを記述し、ChatGPTモデルのファインチューニングを実施したいと思います。以下の手順で進めていきます。

  • 各種Pythonライブラリ読込
  • 学習データ・検証用データのアップロード
  • ファインチューニング実行
  • 【参考】ファインチューニング実行プロセスを経過状況確認
  • ファインチューニング済モデルの利用

各種Pythonライブラリ読込

はじめに、Pythonプログラムの先頭にライブラリとAPI認証情報を記述します。

前述で取得したOrganization IDシークレットキーもそれぞれ入力しましょう。

import openai

openai.organization = "<Organization IDをここに入力>"
openai.api_key      = "<APIシークレットキーをここに入力>"

学習用データ・検証用データのアップロード

続いて、ファインチューニング用のデータをOpenAIのAPIを用いてアップロードします。

コード

検証用データの準備は任意のため、データの準備状況に応じて適切なコードを利用ください。

学習用データのみアップロードする場合はこちら
import json

# 学習用データのファイルパス
filepath_train = "./data/training.jsonl"

# ファイルアップロード(学習)
upload_file_train = openai.File.create(
                                      file=open(filepath_train, "rb"), # ファイル(JSONL)
                                      purpose='fine-tune',             # ファイルのアップロード目的
                                            )

# 出力
print(upload_file_train)
学習用データ+検証用データをアップロードする場合はこちら
import json

# 学習用データのファイルパス
filepath_train = "./data/training.jsonl"

# 検証用データのファイルパス
filepath_val   = "./data/validation.jsonl"

# ファイルアップロード(学習)
upload_file_train = openai.File.create(
                                      file=open(filepath_train, "rb"), # ファイル(JSONL)
                                      purpose='fine-tune',             # ファイルのアップロード目的
                                            )

# ファイルアップロード(検証)
upload_file_val   = openai.File.create(
                                      file=open(filepath_val, "rb"),   # 学習ファイル(JSONL)
                                      purpose='fine-tune',             # ファイルのアップロード目的
                                            )

# 出力
print(upload_file_train)

出力イメージ

# {
#   "bytes": 382,
#   "created_at": 1685433406,
#   "filename": "file",
#   "id": "file-fudxOqnQx2uoCks5A0OhaBws",
#   "object": "file",
#   "purpose": "fine-tune",
#   "status": "uploaded",
#   "status_details": null
# }

ファインチューニング実行

前述でアップロードした学習用データおよび検証用データを用いてファインチューニングを行います。

コード

ファインチューニングには、openai.FineTune.create()メソッドに対して、引数に前述でアップロードしたファイルID(file-xxxxx)およびモデルを指定し実行します。

検証用データの準備は任意のため、データの準備状況に応じて適切なコードを利用ください。

学習用データを用いてファインチューニングを実行する場合はこちら
# 引数情報
file_id_train = upload_file_train.id     # 学習用データのファイルID "file-xxxxx"
model         = 'davinci'                # チューニングするモデル 


# ファインチューニング実行
FineTune = openai.FineTune.create(training_file   = file_id_train,              # 学習用データのファイルID
                                  model           = model,                      # モデル
                                )
学習用データ+検証用データを用いてファインチューニングを実行する場合はこちら
# 引数情報
file_id_train = upload_file_train.id     # 学習用データのファイルID "file-xxxxx"
file_id_val   = upload_file_val.id       # 検証用データのファイルID "file-xxxxx"
model         = 'davinci'                # チューニングするモデル 


# ファインチューニング実行
FineTune = openai.FineTune.create(training_file   = file_id_train,              # 学習用データのファイルID
                                  validation_file = file_id_val,                # 検証用データのファイルID 
                                  model           = model,                      # モデル
                                  compute_classification_metrics = True,        # Trueの場合、検証データを用いて精度評価
                                  classification_n_classes       = 2,           # 分類タスク内のクラスの数
                                  classification_positive_class  = 'accuracy',  # 分類タスクにおいてポジティブクラスの指定基準
                                )

出力イメージ

ファインチューニング後、次のような出力結果が得られます。

# 出力
print(FineTune)

# 出力イメージ
# <FineTune fine-tune id=ft-h18MqDkdRToXkcTWYr0riZ5d at 0x7fbbe003e5e0> JSONL: {
#   "created_at": 1685434188,
#   "events": [
#     {
#       "created_at": 1685434188,
#       "level": "info",
#       "message": "Created fine-tune: ft-h18MqDkdRToXkcTWYr0riZ5d",
#       "object": "fine-tune-event"
#     }
#   ],
#   "fine_tuned_model": null,
#   "hyperparams": {
#     "batch_size": null,
#     "classification_n_classes": 2,
#     "classification_positive_class": "accuracy",
#     "compute_classification_metrics": true,
#     "learning_rate_multiplier": null,
#     "n_epochs": 4,
#     "prompt_loss_weight": 0.01
#   },
#   "id": "ft-h18MqDkdRToXkcTWYr0riZ5d",
#   "model": "davinci",
#   "object": "fine-tune",
#   "organization_id": "org-oSFB9qBWmVGNAiquOkpXUsAd",
#   "result_files": [],
#   "status": "pending",
#   "training_files": [
#     {
#       "bytes": 382,
#       "created_at": 1685433406,
#       "filename": "file",
#       "id": "file-fudxOqnQx2uoCks5A0OhaBws",
#       "object": "file",
#       "purpose": "fine-tune",
#       "status": "processed",
#       "status_details": null
#     }
#   ],
#   "updated_at": 1685434188,
#   "validation_files": [
#     {
#       "bytes": 397,
#       "created_at": 1685433385,
#       "filename": "file",
#       "id": "file-ZHNqxenmx2yZ2bWDBmRAdO2Y",
#       "object": "file",
#       "purpose": "fine-tune",
#       "status": "processed",
#       "status_details": null
#     }
#   ]
# }

【引数情報】openai.FineTune.create()

ファインチューニング用の引数には、今回必須として指定したファイルIDおよびモデルの他に、次のような引数を指定できます。

スクロールできます
引数名概要デフォルト値
training_fileファインチューニング用にアップロードした学習用のファイルID
validation_fileファインチューニング用にアップロードした検証用のファイルID
modelファインチューニングに用いる言語モデルdavinci
n_epochsモデル学習するエポック数。 エポックとは、学習データセットの1つの完全なサイクルを指す。4
batch_size学習に使用するバッチサイズ。デフォルトでは、学習データセット内のサンプル数の約0.2% になるように動的に構成される。上限は 256。一般に、バッチサイズが大きく、データセットが大きいほどうまく機能する傾向がある。Null
learning_rate_multiplier学習率。デフォルトでは、学習率乗数は最終的なバッチサイズに応じて 0.05、0.1、または 0.2 にとなる。(学習率が大きいほど、バッチサイズが大きいほどパフォーマンスが向上する傾向有)。 0.02 ~ 0.2 の範囲の値を試して、何が最良の結果を生み出すかを確認することを推奨。Null
prompt_loss_weightプロンプトトークンの損失に使用する重み。 プロンプトの生成にモデルがどれだけ学習するかを制御。0.01
compute_classification_metricsTrueの場合、各エポックの終了時に検証データを用いて、精度やF-1スコアなど評価指標を計算。False
classification_n_classes分類タスク内のクラスの数Null
classification_positive_class二項分類におけるポジティブクラス。正解率、再現率、 F1指標の計算に必要。Null
classification_betas指定されたbeta値で Fベータスコアが計算される。バイナリ分類のみで有効。beta=1の場合、精度と再現率は同じ重みが与えれる。 beta scoreが大きいほど、正解率よりも再現率が重視される。Null
suffixモデル名に追加される最大40 文字の文字列。Null

【参考】ファインチューニング実行プロセスを経過状況確認

ファインチューニングジョブのステータスは次のように確認できます。

この時、ファインチューニング時に生成されたモデルのIDModelも併せて確認できます。モデルIDは、後続で実際にモデルを利用する際に必要となります。

コード

from datetime import datetime

# チューニング状況チェック
FineTune_data = FineTune.list().data
num           = len(FineTune_data)

for i in range(num):
    timestamp     = FineTune_data[i].created_at
    datetime      = datetime.fromtimestamp(timestamp)
    fine_tuned_id = FineTune_data[i].id
    status        = openai.FineTune.retrieve(id=fine_tuned_id).status
    model         = openai.FineTune.retrieve(id=fine_tuned_id).fine_tuned_model
    
    print(f'Create At: {datetime}')
    print(f'FineTune ID: {fine_tuned_id}')
    print(f'Model: {model}')
    print(f'Statsu: {status}\n')

出力イメージ

# Create At: 2023-05-29 17:06:15
# FineTune ID: ft-9rxNIic45KXR5bFqu0FWXbSY
# Model: davinci:ft-personal-2023-05-29-08-12-13
# Statsu: succeeded

# Create At: 2023-05-29 17:36:19
# FineTune ID: ft-NeF9s2Tu0z5HQBP2E3QEQFu6
# Model: None
# Statsu: failed

# Create At: 2023-05-29 17:41:55
# FineTune ID: ft-2PeaoZO4bhH2jBqFp6IdDIPB
# Model: davinci:ft-personal-2023-05-29-09-00-46
# Statsu: succeeded

ファインチューニング済モデルの利用

前述で作成したファインチューニング済モデルを利用して、実際にチャットを起動してみたいと思います。

コード

前述のステータス確認の際に取得できたモデルIDを用いてチャットボットを作成します。モデルIDはステータスがsucceedかつ、作成日が最新のモデル「モデル名:ft-personal-2023-xx-xx-xx-xx-xx」と記載のものを指定すると良いでしょう。

# ================================================================
# 関数作成
# ================================================================

# ファインチューニング時に得られたモデルID
finetuned_model   =  'davinci:ft-personal-2023-05-30-08-14-43'

def AskChatbot(message):

    # 応答設定
    completion = openai.Completion.create(
                 model       = finetuned_model,  # ファインチューニングしたモデルを選択
                 prompt      = message,          # 質問文         
                 max_tokens  = 1024,             # 生成する文章の最大単語数
                 n           = 1,                # いくつの返答を生成するか
                 stop        = None,             # 指定した単語が出現した場合、文章生成を打ち切る
                 temperature = 0.5,              # 出力する単語のランダム性(0から2の範囲) 0であれば毎回返答内容固定
    )

    # 応答
    response = completion.choices[0]["text"]
    
    # 出力
    return response

出力イメージ

結果は、学習データが少なかったためか精度の低い結果が出力されました。学習データのバリエーションを複数準備した上でファインチューニングを行うと、より良い結果が得られるでしょう。

# ================================================================
# 関数実行
# ================================================================

# 質問文
message =  "「DXCEL WAVE」ではどのようなChatGPTの記事が閲覧できるの?"

# 関数実行
res     = AskChatbot(message)

# 結果出力
print(res)

# 出力イメージ
# DXCEL WAVEでは、ChatGPTに関する記事を掲載しています。
# その中でも、特に人気の高い記事を紹介します。

【参考】AI・機械学習における配信情報まとめ

当サイトではAI・機械学習における「基礎」から「最新のプログラミング手法」に至るまで幅広く解説しております。また「おすすめの勉強方法」をはじめ、副業・転職・フリーランスとして始める「AI・機械学習案件の探し方」についても詳しく言及しています。

【仕事探し】副業・転職・フリーランス

【教育】おすすめ勉強法

【参考】記事一覧

最後に

この記事が気に入ったら
フォローしてね!

目次