0% read

Gemma 4のmm_token_type_idsエラーをファインチューニングで解決する

6月 2, 2026

ごく普通のテキストのみのデータでGemma 4のファインチューニングを始めたら、最初のステップでトレーナーがこのエラーを吐いて止まった——そんな経験はありませんか?

ValueError: `mm_token_type_ids` is required as a model input when training

画像もなければ音声もない。ただのチャットデータです。なのになぜGemma 4はマルチモーダル用のトークンフィールドを要求してくるのでしょうか。これはGemma 4のリリース初日から知られている既知の引っかかりどころで(transformers issue #45200)、仕組みさえ理解すれば修正はごく小さなものです。本記事では、1行で済む暫定対処と、mm_token_type_idsエラーを完全に消し去るコピペ可能なカスタムdata collatorの両方を紹介します。

このエラーで実際に起きていること

トレースバックの最下層は、モデルのforwardパスの内部にたどり着きます。

File ".../transformers/models/gemma4/modeling_gemma4.py", line ..., in forward
    raise ValueError(
ValueError: `mm_token_type_ids` is required as a model input when training

このエラーは、データセットやLoRAの設定、GPUの種類に関係なく、トレーニングのまさに最初のステップで発生します。素のTrainerでも、TRLのSFTTrainerでも、QLoRA構成でも同じように踏み抜きます。共通点はただ一つ——マルチモーダル前提で設計されたモデルに、テキストのみのデータセットを食わせていることです。

なぜ起きるのか(根本原因)

Gemma 4は設計からしてマルチモーダルです。テキストトークンを画像・音声トークンと区別するために、このアーキテクチャはinput_idsに加えて2つの入力を導入しました。

  • token_type_ids — 従来からあるセグメント用のフィールド。
  • mm_token_type_ids — どの位置がテキスト/画像/音声なのかを示す、マルチモーダル用のトークンタイプフィールド。

問題は、Gemma 4のモデルコードが、loss を計算するトレーニング時のforwardパス(labelsが渡されたトレーニングモード)でmm_token_type_idsの存在を検証してしまう点にあります。バッチの中に画像が1枚も含まれていなくても、です。一方で、標準のtokenizerもデフォルトのdata collatorも、そのフィールドを生成することは決してありません。テキストのみの実行ならすべての値は単純に0になるはずなのですが、フィールドがゼロ埋めされているのではなく完全に欠落しているため、モデルは妥当なデフォルト値を仮定する代わりにエラーを投げてしまうわけです。(リリース初日のtransformers==5.5.0.dev0のソースビルド時点で、該当するraisemodeling_gemma4.pyforward内、トレーニング分岐に存在します。正確な行番号はコミットによって動きます。)

つまりこのバグの正体はミスマッチです——モデルはmm_token_type_ids要求するのに、tokenizerはそれを決して作らず、しかもトレーナーはたとえ自分で作っても捨ててしまう。この3つすべてを直せば、エラーは消えます。

まずは1行で動かす暫定対処

トレーニングループを自分で書いていて、とにかく今すぐ前に進めたいだけなら、forward呼び出しの前にゼロのテンソルを差し込みましょう(torchをimportしておいてください)。

import torch

inputs["mm_token_type_ids"] = torch.zeros_like(inputs["input_ids"])

テキストのみのデータでは、すべてのトークンがテキストトークンなので、input_idsと同じ形状のオールゼロのテンソルがまさに正解です。手書きのトレーニングループを動かすにはこれで十分です。ただしTrainerSFTTrainerを使う場合はforward呼び出しを自分で握っていないため、このフィールドをバッチそのものに焼き込んでおく必要があります——それを担うのが、次に紹介するcollatorです。

完全な解決策:カスタムGemma 4 data collator

ポイントは3つあり、そのすべてが必要です。どれか1つでも飛ばすと、mm_token_type_idsエラーはすぐに戻ってきます。

0. 最小限のセットアップ

以下のスニペットを端から端まで実行できるように、前提となる足場のコードを示しておきます——モデルとデータセットはご自身のものに差し替えてください。

from datasets import load_dataset
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch

model_id = "google/gemma-4-4b-it"  # any Gemma 4 checkpoint
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(model_id, torch_dtype=torch.bfloat16)

# This guide assumes each example has a `messages` field (chat format):
#   {"messages": [{"role": "user", "content": "..."},
#                 {"role": "assistant", "content": "..."}]}
# If your data is instruction/output style, convert it to messages first.
dataset = load_dataset("your/dataset", split="train")

1. tokenize時に両方のフィールドを追加する

tokenizeするときに、token_type_idsmm_token_type_idsを、input_idsと同じ長さのオールゼロのリストとして付け加えます。

def format_chat(example):
    text = tokenizer.apply_chat_template(
        example["messages"], tokenize=False, add_generation_prompt=False
    )
    tokenized = tokenizer(text, truncation=True, max_length=4096)
    tokenized["token_type_ids"] = [0] * len(tokenized["input_ids"])
    tokenized["mm_token_type_ids"] = [0] * len(tokenized["input_ids"])
    tokenized["labels"] = tokenized["input_ids"].copy()
    return tokenized

tokenized_dataset = dataset.map(format_chat, remove_columns=dataset.column_names)

このコードはシーケンス全体(プロンプト+応答)に対してlossを計算する点に注意してください。標準的なSFTの挙動——アシスタントの返答部分だけでlossを取りたい——を望むなら、ここでプロンプト部分のトークンのlabels-100に設定してマスクしてください。

2. それらを保持してpaddingするcollatorを使う

デフォルトのcollatorはこれらのカスタムフィールドをどうpaddingすればよいか分かりません。そこで自前のcollatorを定義します。これはinput_idsをpaddingし、attention_maskを組み立て、2つのトークンタイプフィールドをバッチ内の最大長までゼロ埋めし、labelsのpadding部分を-100でマスクします。

from dataclasses import dataclass
import torch

@dataclass
class GemmaCollator:
    tokenizer: object

    def __call__(self, features):
        max_len = max(len(f["input_ids"]) for f in features)
        # Gemma tokenizers define a pad token; fall back to eos just in case.
        pad_id = self.tokenizer.pad_token_id or self.tokenizer.eos_token_id
        batch = {
            "input_ids": [],
            "attention_mask": [],
            "token_type_ids": [],
            "mm_token_type_ids": [],
            "labels": [],
        }
        for f in features:
            pad_len = max_len - len(f["input_ids"])
            batch["input_ids"].append(f["input_ids"] + [pad_id] * pad_len)
            batch["attention_mask"].append([1] * len(f["input_ids"]) + [0] * pad_len)
            batch["token_type_ids"].append([0] * max_len)
            batch["mm_token_type_ids"].append([0] * max_len)
            batch["labels"].append(
                f.get("labels", f["input_ids"]) + [-100] * pad_len
            )
        return {k: torch.tensor(v) for k, v in batch.items()}

3. remove_unused_columns=Falseを設定する

これが誰もが忘れがちなステップです。デフォルトではトレーナーは、collatorが走るに、モデルのシグネチャが「認識しない」列をすべて削ぎ落としてしまいます。そのため、せっかく丁寧に追加したmm_token_type_idsが途中で消され、エラーが戻ってくるのです。この挙動をオフにしましょう。

from trl import SFTConfig, SFTTrainer

training_args = SFTConfig(
    output_dir="gemma4-finetune",
    per_device_train_batch_size=1,
    gradient_accumulation_steps=8,
    num_train_epochs=1,
    learning_rate=2e-4,
    remove_unused_columns=False,                       # <-- critical: keep mm_token_type_ids
    dataset_kwargs={"skip_prepare_dataset": True},     # we pre-tokenized ourselves
)

trainer = SFTTrainer(
    model=model,
    args=training_args,
    train_dataset=tokenized_dataset,
    data_collator=GemmaCollator(tokenizer),
)

trainer.train()

ステップ1でフィールドを作り、ステップ2で保持・paddingし、ステップ3で列の削除から守る——これで、モデルはmm_token_type_idsを受け取れるようになり、トレーニングは正常に進みます。

修正できたかを確認する

本番の実行を始める前に、バッチを1つダンプして、mm_token_type_idsが実際に存在し、ゼロの形状になっているかを確認しましょう。

collator = GemmaCollator(tokenizer)
batch = collator([tokenized_dataset[0], tokenized_dataset[1]])
print(batch.keys())
print("mm_token_type_ids" in batch)            # True
print(batch["mm_token_type_ids"].shape)        # matches input_ids
print(batch["mm_token_type_ids"].sum().item()) # 0 for text-only

mm_token_type_idsがキーに含まれていて、その合計が0なら完了です——次のtrainer.train()は、最初のステップを問題なく通過します。

よくあるミスと関連エラー

  • token_type_idsだけを追加してしまう。 この2つは別物です。Gemma 4が明確にチェックするのはmm_token_type_idsであり、mmの付かない方のフィールドだけでは検証を通過できません。
  • remove_unused_columns=Falseを忘れる。 「フィールドを追加したのにエラーが消えない」の最も多い原因がこれです。トレーナーが何も言わずに先にそれを捨ててしまいます。
  • collatorがトークンタイプフィールドを誤った長さでpaddingしてしまう。 これらはpadding後のinput_idsの長さに一致させる必要があります。元の長さに合わせると、forwardパスのさらに奥で形状不一致エラーが出ます。
  • Gemma 3でtoken_type_ids is requiredが出る。 一世代前のGemma 3では、TRLでのファインチューニング時にこれと同じエラーのmmなし版が発生します(trl issue #5032)。同じゼロ埋め戦略が有効です。
  • QLoRAが別の原因でクラッシュする。 4-bitのGemma 4ファインチューニングが、これとは無関係なadapter周りのエラーで失敗する場合、それは別の既知の問題であって(peft issue #3129)、collatorとは関係ありません。まずmm_token_type_idsエラーを直し、その後で量子化に取り組みましょう。

LoRAとQLoRAの比較、Unsloth、データセットの準備、GGUFエクスポートまで——より広範なファインチューニングのセットアップについては、Gemma 4 ファインチューニングガイドをご覧ください。

upstreamで修正される見込みは?

おそらく修正されます。transformers issue #45200で提案されているのは、テキストのみのトレーニングでmm_token_type_idsが欠落している場合、エラーを投げる代わりにモデル側で**mm_token_type_idsをゼロにデフォルト設定する**という案です。これが安定版リリースに取り込まれるまで(現状このエラーはtransformers==5.5.0.dev0のソースビルドで再現します)、上記のcollatorが信頼できる回避策です。モデルが期待する入力は、公式のGemma model docsで追跡できます。修正版が出荷されたら、カスタムcollatorを外して標準のものに戻して構いません——とはいえ、残しておいても害はありません。

FAQ

画像でファインチューニングする場合、mm_token_type_idsは必要ですか? はい、しかもその場合は実際に意味を持ちます——マルチモーダルなトークン位置はオールゼロではなく、きちんとマークされるべきです。本記事のオールゼロという近道が有効なのは、テキストのみのデータに限られます。

Unslothを使っています。これは当てはまりますか? 一部当てはまります。Unslothはモデルとtokenizerをラップし、独自のデータ処理を備えているため、このcollatorをそのまま無造作に放り込まないでください。まずUnslothを更新して再テストしましょう——そのパッチが、すでにあなたの代わりにmm_token_type_idsを注入してくれているかもしれません。それでもエラーが続く場合は、このcollatorを丸ごと差し替えるのではなく、Unslothのフローの中で同じ考え方を適用します——データのフォーマット処理(あるいはそのdata_collator)の中でmm_token_type_idsをゼロ埋めし、remove_unused_columns=Falseを維持するのです。

単にtransformersをダウングレードして回避できませんか? Gemma 4対応より前のリリースにpinすることはできますが、そうするとGemma 4自体をまったくロードできなくなります。collatorによる修正の方が、バージョンを固定するよりも安全です。

これは推論にも影響しますか? いいえ。このチェックはトレーニングのlossパスにのみゲートされています。素のgeneration/推論では、テキストのみのプロンプトに対してmm_token_type_idsを渡す必要はありません。

TRLではなく素のTrainerを使っています。これでも動きますか? はい。GemmaCollatorはフレームワークに依存しません——素のTrainerdata_collatorとして渡し、TrainingArgumentsremove_unused_columns=Falseを設定すればOKです。

次のステップ

gemma4 — interact

Stop reading. Start building.

~/gemma4 $ Get hands-on with the models discussed in this guide. No deployment, no friction, 100% free playground.

Launch Playground />
Gemma 4 AI

Gemma 4 AI

Related Guides

Gemma 4のmm_token_type_idsエラーをファインチューニングで解決する | ブログ