Gemma3のデータセット加工とLoRAファインチューニング
作ったもの
日本語データセットをAI学習用に加工して、Gemma-3-1bをLoRAファインチューニングしました。
2種類のデータセット(論文3行まとめ、識別形質比較)を、Gemma-3専用のプロンプト形式に変換。約3,000件のデータで学習させました。
データの加工方法が一番重要だった。形式を間違えると、学習そのものが失敗する。
まずは、データ加工の流れを見てみましょう:
生のJSONデータを、AIが学習できる形式に変換します。<start_of_turn>userと<start_of_turn>modelで会話を区切る。
なぜデータ加工が重要か
最初、普通のJSON形式でデータを渡した。一度つまずいた。
Gemma-3は会話形式のデータで学習されている。ユーザーとモデルの発言を区別できないと、学習が進まない。
公式ドキュメントに書いてあったのに、見落としていた。これは想定が甘かった。
何度か試して、ようやくプロンプト形式の重要性を理解した。形式が正確でないと、損失が下がらない。エラーメッセージも出ないから、原因が分からず苦労した。
データセットの種類
1. 論文3行まとめデータセット
論文のタイトルとタグを「質問」、3行の要約を「回答」として組み合わせます。
元のデータ:
{
"ja_title_provisional_translate": "日本産キノコの新種発見",
"tags": "新種, キノコ, 日本",
"R3summary_1": "本研究では日本産の新種キノコを発見した。",
"R3summary_2": "形態学的特徴を詳細に記載した。",
"R3summary_3": "DNA解析により分類学的位置づけを行った。"
}
これをGemma-3形式に変換:
<start_of_turn>user
タイトル: 日本産キノコの新種発見
タグ: 新種, キノコ, 日本<end_of_turn>
<start_of_turn>model
本研究では日本産の新種キノコを発見した。
形態学的特徴を詳細に記載した。
DNA解析により分類学的位置づけを行った。<end_of_turn>
約1,500件のデータを、この形式で加工しました。
2. 識別形質比較データセット
2つの菌類の共通点または違いを記述したデータです。
元のデータ:
{
"comparison_source": "Candida tanticharoeniae",
"comparison_target": "Candida savonica",
"sentence": "D1/D2領域に基づく分子系統解析で近縁",
"label": "分子系統解析",
"common_or_different": 1
}
common_or_differentが1なら「共通点」、0なら「違い」。この値で質問文を変えます。
変換後:
<start_of_turn>user
Candida tanticharoeniaeとCandida savonicaの共通点を教えてください(カテゴリ: 分子系統解析)<end_of_turn>
<start_of_turn>model
D1/D2領域に基づく分子系統解析で近縁<end_of_turn>
約1,500件のデータを加工。2種類合わせて3,000件になりました。
データ加工のコード
Pythonでデータを加工しました。
def format_paper_data(data):
"""論文3行まとめをGemma-3形式に変換"""
question = f"タイトル: {data['ja_title_provisional_translate']}\nタグ: {data['tags']}"
answer = f"{data['R3summary_1']}\n{data['R3summary_2']}\n{data['R3summary_3']}"
return f"<start_of_turn>user\n{question}<end_of_turn>\n<start_of_turn>model\n{answer}<end_of_turn>"
def format_comparison_data(data):
"""識別形質比較をGemma-3形式に変換"""
source = data['comparison_source']
target = data['comparison_target']
category = data['label']
sentence = data['sentence']
# 共通点か違いかを判定
question_type = "共通点" if data['common_or_different'] == 1 else "違い"
question = f"{source}と{target}の{question_type}を教えてください(カテゴリ: {category})"
return f"<start_of_turn>user\n{question}<end_of_turn>\n<start_of_turn>model\n{sentence}<end_of_turn>"
シンプルな関数。でも、この変換が学習の成否を分けます。
LoRAファインチューニング
データを加工したら、学習を実行。
LoRAパラメータは、midori291と同じ設定:
- r=16
- lora_alpha=32
- target_modules=["q_proj", "v_proj", "k_proj", "o_proj"]
学習パラメータ:
- learning_rate=3e-4
- batch_size=8
- num_train_epochs=20
Google Colab A100で、約2時間で完了しました。
学習結果
論文要約の精度
「日本産キノコの新種発見」というタイトルで質問。
回答:「本研究では日本産の新種キノコを発見した。形態学的特徴を詳細に記載した。DNA解析により分類学的位置づけを行った。」
学習データと完全に一致。ヨシ。
菌類の識別
「Candida tanticharoeniaeとCandida savonicaの共通点は?」と質問。
回答:「D1/D2領域に基づく分子系統解析で近縁」
正確に答えた。データ加工がうまくいっている証拠です。
未知の質問
「キノコの栄養成分は?」と聞いてみた。
回答が曖昧。データセットに含まれていない情報は、答えられない。
これは仕方ない。学習データの範囲内でしか答えられないのが、ファインチューニングの限界です。
データ加工のコツ
1. プロンプト形式の正確性
Gemma-3の形式を正確に守ること。<start_of_turn>と<end_of_turn>のタグ、改行の位置まで厳密に。
少しでもズレると、学習が失敗する可能性がある。最初、改行を間違えて、損失が下がりませんでした。
2. 質問と回答の明確な区別
ユーザーの発言とモデルの発言を、はっきり区別すること。
質問文には「〜を教えてください」「〜は何ですか?」など、質問の形式で書く。回答は簡潔に、事実だけを記述。
この区別が曖昧だと、AIが何を学習していいか分からなくなります。
3. データ量のバランス
最初、論文データだけで学習した。偏りが出た。
識別形質データを追加したら、バランスが良くなった。複数種類のデータを組み合わせるのが効果的でした。
使ってみて
Gemma-3のデータセット加工は、正確さが全てです。
ポイントは以下の3つ:
- プロンプト形式の厳守:
<start_of_turn>タグの正確な配置、改行位置まで厳密に守る
- 質問と回答の区別:ユーザーとモデルの発言を明確に分ける、曖昧さを排除
- 複数データセットの組み合わせ:1種類だけでなく、2-3種類のデータを組み合わせるとバランスが良い
最初はプロンプト形式を適当に扱って、損失が下がりませんでした。公式ドキュメントを読み直して、正確な形式を理解。データ加工の重要性を痛感しました。
より詳細な実装は、midori291とmidori293で解説しています。
まとめ
今回は、日本語データセットのAIプロンプト化とLoRAファインチューニングを実装しました。
ポイントは以下の4つ:
- データ形式の正確性:Gemma-3専用の
<start_of_turn>形式に厳密に変換、改行位置も重要
- 2種類のデータセット:論文3行まとめ1,500件、識別形質比較1,500件を組み合わせ
- 加工関数の実装:Pythonで自動変換、手動では対応できない件数
- 学習結果の検証:学習データと一致する回答を確認、未知の質問には対応できない
データ加工が不正確だと、学習が失敗します。形式を間違えて何度も失敗しましたが、最終的に正確な変換方法を確立できました。
同じようなデータセット加工を考えている方の参考になれば嬉しいです。
参考にした資料
この記事で興味を持った方におすすめのリンク:
自分の関連記事:
最後まで読んでくださり、ありがとうございました。