🔨

ローカルからGemini APIのファインチューニングを行う

2024/08/17に公開

ローカルから「Gemini API」のファインチューニングを行うための備忘録です。
google colabとさほど変わらないですが、補足情報を追加しています。

準備

「Gemini API」のファインチューニングを行うために、以下の準備を行います。

1. client_secret.jsonの取得

Gemini APIのファインチューニングを行うにはOAuth認証が必要です。そのため、Google Cloud Platformの認証情報を取得します。

以下公式より引用+一部修正

1. API を有効にする

Google API を使用する前に、Google Cloud プロジェクトで有効にする必要があります。

  • Google Cloud コンソールで、Google Generative Language API を有効にします。

2. OAuth 同意画面を構成する

次に、プロジェクトの OAuth 同意画面を構成し、自分自身をテストとして追加します。

  1. Google Cloud コンソールで、メニュー >API とサービス >OAuth 同意画面OAuth 同意画面に移動
  2. アプリのユーザータイプとして [外部] を選択し、[作成] をクリックします。
  3. アプリ登録フォームに入力し [保存して次へ] をクリックします。
  4. 現時点では、スコープの追加をスキップして [保存して次へ] をクリックします。
  5. テストユーザーを追加します。
    1. [テストユーザー] で [ユーザーを追加] をクリックします。
    2. メールアドレスと、その他の承認されたテストユーザーを入力します。 [保存して次へ] をクリックします。

3. デスクトップ アプリケーションの認証情報を承認する

エンドユーザーとして認証を行い、アプリ内でユーザーデータにアクセスするには、1 つ以上の OAuth 2.0 クライアント ID を作成する必要があります。

  1. Google Cloud コンソールで、メニュー >API とサービス > 認証情報認証情報に移動します。
  2. [+認証情報を作成] > OAuth クライアント IDを選択します。
  3. [アプリケーションの種類] にデスクトップ アプリを選択します。
  4. [名前] フィールドに、認証情報の名前を入力します。
  5. [作成] をクリックします。
  6. [JSONをダウンロード]ボタンをクリックして JSON ファイルを保存します。名前を付けて保存 client_secret_<identifier>.json。名前を client_secret.json に変更します。 それを作業ディレクトリに移動します。

手順通りに進めて、以下の様に「client_secret.json」を作業ディレクトリに保存しておきます。

workdir/
└── client_secret.json

2. gcloud CLIのインストール

「gcloud CLI」を環境に合わせてインストールします。

https://cloud.google.com/sdk/docs/install?hl=ja

3. OAuthの認証

作業ディレクトリに移動して、以下のコマンドを実行してOAuth認証を行います。

gcloud auth application-default login --client-id-file client_secret.json --scopes='https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/generative-language.tuning'

認証画面がブラウザ表示されるので、手順に従って認証を行います。

4. ライブラリのインストール

「Gemini API」のファインチューニングを行うために、以下のライブラリをインストールします。

pip install google-generativeai

ファインチューニング

1. ベースとなるモデルの選択

以下のコードで現在利用可能なモデルの一覧を取得します。

for m in genai.list_models():
  if 'createTunedModel' in m.supported_generation_methods:
    print(m.name)

2024/8/17現在、gemini-1.0-pro-001gemini-1.5-flash-001-tuningのモデルが利用可能です。

models/gemini-1.0-pro-001
models/gemini-1.5-flash-001-tuning

今回はgemini-1.5-flash-001-tuningをベースとしてファインチューニングを行います。

base_model = genai.get_base_model('models/gemini-1.5-flash-001-tuning')

2. 訓練データの準備

後ほど使用するcreate_tuned_model関数の引数で渡すtraining_dataは、以下の形式である必要があります。
公式ドキュメント

データセット形式 詳細
protos.Dataset オブジェクト -
Iterable - protos.TuningExample オブジェクト
- {'text_input': text_input, 'output': output} 形式の辞書
- (text_input, output) 形式のタプル
Iterable[str]Mapping - input_keyoutput_key を使用して、入力/出力として使用する列を選択
CSVファイル - ローカルパス(str または pathlib.Path として)
- CSVファイルのURL
- Google Sheetsファイルの URL
pd.read_csv で読み込まれ、Mapping として扱われます)
JSONファイル - ローカルパス(str または pathlib.Path として)
(内容は Iterable または Mapping として扱われます)

今回は、公式と同様に{'text_input': text_input, 'output': output} 形式の辞書を使用します。

3. ファインチューニングの実行

import random

name = f'generate-num-{random.randint(0,10000)}'
operation = genai.create_tuned_model(
    # チューニング済みのモデルも`source_model="tunedModels/..."`で指定可能。
    source_model=base_model.name,
    # training_data='path/to/training_data.csv',
    # training_data='path/to/training_data.json'でも可能
    training_data=[
        {
             'text_input': '1',
             'output': '2',
        },{
             'text_input': '3',
             'output': '4',
        },{
             'text_input': '-3',
             'output': '-2',
        },{
             'text_input': 'twenty two',
             'output': 'twenty three',
        },{
             'text_input': 'two hundred',
             'output': 'two hundred one',
        },{
             'text_input': 'ninety nine',
             'output': 'one hundred',
        },{
             'text_input': '8',
             'output': '9',
        },{
             'text_input': '-98',
             'output': '-97',
        },{
             'text_input': '1,000',
             'output': '1,001',
        },{
             'text_input': '10,100,000',
             'output': '10,100,001',
        },{
             'text_input': 'thirteen',
             'output': 'fourteen',
        },{
             'text_input': 'eighty',
             'output': 'eighty one',
        },{
             'text_input': 'one',
             'output': 'two',
        },{
             'text_input': 'three',
             'output': 'four',
        },{
             'text_input': 'seven',
             'output': 'eight',
        }
    ],
    id = name,
    epoch_count = 100,
    batch_size=4,
    learning_rate=0.001,
)

引数で指定するepoch_count,batch_size,learning_rateについての補足

  • epoch_count : モデルの学習回数
    学習データを何回繰り返して学習するかを指定するパラメータ。epochが大きいほど、学習データを繰り返し学習するため、学習精度が向上しますが、過学習を引き起こす可能性があります。

  • batch_size : バッチサイズ
    モデルが一度に学習するデータの数を指定するパラメータ。バッチサイズが大きいほど、学習データを一度に多く処理できるため、学習速度が向上します。

  • learning_rate : 学習率
    モデルが学習する際のステップサイズを指定するパラメータ。学習率の値が大きいほど、一度に変更する重みパラメータの大きさが大きくなり学習速度は上がります。逆に小さい場合は学習の速度が下がります。

4. チューニングの進行状況を確認

import time

for status in operation.wait_bar():
  time.sleep(30)

すでに実行している場合は、以下の手順で進行状況を確認できます。

# すべてのチューニングを取得
for o in genai.list_operations():
  print(o.name)

実行結果

tunedModels/xxxxxx/operations/xxxxxx
tunedModels/yyyyyy/operations/yyyyyy

operationの名前が取得できたら、以下のコードで進行状況を取得できます。

# 確認したいperationの名前を指定
operation = genai.get_operation('tunedModels/yyyyyy/operations/yyyyyy')
for status in operation.wait_bar():
  time.sleep(30)

チューニング結果の確認

import pandas as pd
import seaborn as sns

model = operation.result()

snapshots = pd.DataFrame(model.tuning_task.snapshots)

sns.lineplot(data=snapshots, x = 'epoch', y='mean_loss')

モデルの評価

generate_contentを使用して、ファインチューニングしたモデルを評価します。

model = genai.GenerativeModel(model_name=f'tunedModels/{name}')

result = model.generate_content('55')
print(result.text)

モデルの削除

genai.delete_tuned_model(f'tunedModels/{name}')

Discussion