Kaggle「AI Mathematical Olympiad」に挑戦!ファインチューニング済みGemma Instruct 2Bモデルで数学問題を解き明かせ

LLM

こんにちは!この記事では、Kaggleの「AI Mathematical Olympiad」コンペティションに向けて、ファインチューニング済みのGemma Instruct 2Bモデルを使用する方法を解説します。初心者の方でも完璧に理解できるよう、丁寧に説明していきますので、ぜひ最後までお付き合いください。

必要なライブラリのインポートとモデルのダウンロード

まずは、必要なライブラリをインポートし、ファインチューニング済みのモデルをダウンロードしましょう。

from kaggle_secrets import UserSecretsClient
user_secrets = UserSecretsClient()
KAGGLE_USERNAME = user_secrets.get_secret("KAGGLE_USERNAME")
import os
import kagglehub

os.environ["KERAS_BACKEND"] = "jax"  # JAXをバックエンドとして指定
# JAXバックエンドでのメモリ断片化を回避
os.environ["XLA_PYTHON_CLIENT_MEM_FRACTION"]="1.00"

import keras
import keras_nlp

# Finetuned model
FINETUNED_MODEL_DIR = f"./gemma_demo"

MODEL_BASE = "aimo_gemma"
MODEL_NAME = f"{MODEL_BASE}_train_finetuning_h5"
FINETUNED_WEIGHTS_PATH = f"{FINETUNED_MODEL_DIR}/{MODEL_NAME}.weights.h5"
FINETUNED_VOCAB_PATH = f"{FINETUNED_MODEL_DIR}/vocabulary.spm"
FRAMEWORK = "jax"
VER = 8
handle = f'{KAGGLE_USERNAME}/{MODEL_BASE}/{FRAMEWORK}/{MODEL_NAME}_v{VER}'
# Download latest version
print(f"handle:{handle}")
path = kagglehub.model_download(handle)
print("モデルファイルのパス:", path)
import glob
weights_path = glob.glob(f"{path}/*.h5")[0]

モデルの準備

次に、ダウンロードしたモデルを準備します。LoRA (Low-Rank Adaptation) を有効化してメモリ使用量を削減し、入力シーケンス長を512に制限します。また、最適化アルゴリズムにAdamWを使用し、Layer NormalizationとBiasの重みを減衰の対象から除外します。

# Gemma Instruct 2Bモデルのロード
gemma_lm = keras_nlp.models.GemmaCausalLM.from_preset("gemma_instruct_2b_en")
gemma_lm.summary()

# LoRA (Low-Rank Adaptation) を有効化し、メモリ使用量を削減
gemma_lm.backbone.enable_lora(rank=64)

# 入力シーケンス長を512に制限して、メモリ使用量をコントロール
gemma_lm.preprocessor.sequence_length = 512

# 最適化アルゴリズムにAdamWを使用し、Layer NormalizationとBiasの重みを減衰の対象から除外
optimizer = keras.optimizers.AdamW(
    learning_rate=5e-5,
    weight_decay=0.01,
)
optimizer.exclude_from_weight_decay(var_names=["bias", "scale"])

# モデルのコンパイル
gemma_lm.compile(
    loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
    optimizer=optimizer,
    weighted_metrics=[keras.metrics.SparseCategoricalAccuracy()],
)
# ファインチューニング済みのモデルの重みを読み込む
gemma_lm.load_weights(weights_path, skip_mismatch=True)

予測の生成

準備したモデルを使って、テストデータの各問題に対して予測を生成します。

# 必要なライブラリのインポート
import pandas as pd

# testデータの読み込み
test = pd.read_csv("/kaggle/input/ai-mathematical-olympiad-prize/test.csv")

# 予測結果を格納するリストの初期化
predictions = []

# testデータの各問題に対して予測を生成
for index, row in test.iterrows():
    question = row['problem']
    prompt = f"Context: You are an intelligent system designed to solve mathematical problems and provide only the numeric answer without any additional explanations or steps.\n\nProblem: {question}\n\nInstructions:\n- Analyze the given mathematical problem carefully.\n- Identify the unknown quantity or value to be determined.\n- Apply the appropriate mathematical concepts, formulas, and operations to solve the problem.\n- Output only the final numeric answer to the problem, without any additional text or explanations.\n\nAnswer:"
    answer = gemma_lm.generate(prompt, max_length=256)
    numeric_answer = ''.join(filter(str.isdigit, answer.split(':')[-1]))
    numeric_answer = int(numeric_answer) % 1000  # 数値のみを抽出し、1000で割った余りを取る
    predictions.append(numeric_answer)

# 提出用のDataFrameを作成
submission = pd.DataFrame({'id': test['id'], 'predicted': predictions})

trainデータでの正解率の算出

テストデータが少ない場合は、trainデータを使用して正解率を算出します。

# testデータが少ない場合はtrainデータを使用
if len(test) < 5:  
    df = pd.read_csv('/kaggle/input/ai-mathematical-olympiad-prize/train.csv')
    PRIVATE = False
else:
    df = test.copy()
    PRIVATE = True

# 予測結果を格納するリストの初期化
predictions = []

# testデータの各問題に対して予測を生成
for index, row in df.iterrows():
    question = row['problem']
    prompt = f"Context: You are an intelligent system designed to solve mathematical problems and provide only the numeric answer without any additional explanations or steps.\n\nProblem: {question}\n\nInstructions:\n- Analyze the given mathematical problem carefully.\n- Identify the unknown quantity or value to be determined.\n- Apply the appropriate mathematical concepts, formulas, and operations to solve the problem.\n- Output only the final numeric answer to the problem, without any additional text or explanations.\n\nAnswer:"
    answer = gemma_lm.generate(prompt, max_length=256)
    numeric_answer = ''.join(filter(str.isdigit, answer.split(':')[-1]))
    print("--------------")
    print(f"numeric_answer:{numeric_answer}")
    try:
        numeric_answer = int(numeric_answer) % 1000  # 数値のみを抽出し、1000で割った余りを取る
    except:
        numeric_answer = -1

    predictions.append(numeric_answer)

# モデルの予測結果を追加
df['model_answer'] = predictions  

# 正解と予測が一致しているかチェック
df['match'] = df.answer == df.model_answer  

# PRIVATEフラグがFalseの場合、正解率を表示
if not PRIVATE:
    print(f'{df.match.sum()} matches in {len(df)} examples')
df
PRIVATE

最後に、予測結果をCSVファイルに出力します。

submission.to_csv("submission.csv",index=False,header=True)
submission

これで、ファインチューニング済みのGemma Instruct 2Bモデルを使用して、Kaggleの「AI Mathematical Olympiad」コンペティションに挑戦する準備が整いました。初心者の方でも、この記事を参考にしながら、モデルの準備から予測の生成まで一通りの流れを理解することができるはずです。ぜひ、自分の手を動かしながら、コードを実行してみてください。わからないことがあれば、気軽に質問してくださいね。一緒に頑張りましょう!

ノートブック

Google Colaboratory
AIMO Gemma Instruct 2B Finetuning inference
Explore and run machine learning code with Kaggle Notebooks | Using data from multiple data sources

参考サイト

KerasとJAXを使ってGemmaモデルをTPU分散学習する方法
Explore and run machine learning code with Kaggle Notebooks | Using data from Gemma
kagglehub を使った大規模言語モデル gemma のファインチューニングとモデル共有
Explore and run machine learning code with Kaggle Notebooks | Using data from multiple data sources

コメント

タイトルとURLをコピーしました