# Gemma-4-Anleitung zur Feinabstimmung

Sie können jetzt Googles [Gemma 4](https://unsloth.ai/docs/de/modelle/qwen3.5) E2B, E4B, 26B-A4B und 31B mit [**Unsloth**](https://github.com/unslothai/unsloth). Unsloth unterstützt für Gemma 4 alle Vision-, Text-, Audio- und RL-Fine-Tuning-Verfahren.

* Unsloth trainiert Gemma 4 **\~1,5x schneller** mit **\~60 % weniger VRAM** als FA2-Setups (kein Genauigkeitsverlust)
* Wir haben viele allgemeine [Fehler für das Gemma-4-Training behoben](#bug-fixes--tips) (nicht von Unsloth abgeleitet).
* Gemma 4 E2B-Training funktioniert auf **8 GB VRAM**. E4B benötigt 10 GB VRAM.

<a href="#quickstart" class="button primary" data-icon="bolt">Schnellstart</a><a href="#bug-fixes--tips" class="button secondary" data-icon="sparkle">Fehlerbehebungen + Tipps</a>

Gemma 4 feinabstimmen über unsere **kostenlosen** **Google-Colab-Notebooks**:

| [**E4B + E2B** (Studio)](https://colab.research.google.com/github/unslothai/unsloth/blob/main/studio/Unsloth_Studio_Colab.ipynb) | [**31B** (Kaggle)](https://www.kaggle.com/code/danielhanchen/gemma4-31b-unsloth) | [E4B **(Vision + Text)**](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Gemma4_\(E4B\)-Vision.ipynb) | [E4B **(Audio)**](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Gemma4_\(E4B\)-Audio.ipynb) |
| -------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |

{% columns %}
{% column %}
Sie können Gemma 4 kostenlos mit einer UI in unserem [Unsloth Studio](https://unsloth.ai/docs/de/neu/studio)✨-Notebook ausführen und trainieren:

Sie können hier weitere [Notebooks ansehen](#unsloth-core-code-based-guide).
{% endcolumn %}

{% column %}
{% embed url="<https://colab.research.google.com/github/unslothai/unsloth/blob/main/studio/Unsloth_Studio_Colab.ipynb>" %}
{% endcolumn %}
{% endcolumns %}

* Gemma 4 E2B LoRA funktioniert mit 8–10 GB VRAM. E4B LoRA benötigt 17 GB VRAM.
* **31B QLoRA funktioniert mit 22 GB** und 26B-A4B LoRA benötigt >40 GB
* **Exportieren**/Speichern von Modellen nach GGUF usw. und Full Fine-Tuning **(FFT)** funktioniert ebenfalls.

### :bug: Fehlerbehebungen + Tipps

{% hint style="success" %}
Wenn Sie sehen, **dass Gemma-4 E2B und E4B einen Verlust von 13–15 haben, ist das völlig normal** – das ist eine häufige Eigenheit multimodaler Modelle. Das passierte auch bei Gemma-3N, Llama-Vision-, Mistral-Vision-Modellen und anderen.

**Gemma 26B und 31B haben einen niedrigeren Verlust von 1–3 oder weniger. Vision ist 2x höher, also 3–5**
{% endhint %}

#### :grapes:Gradient Accumulation kann Ihre Verluste erhöhen

{% columns %}
{% column %}

<div data-with-frame="true"><figure><img src="https://797013937-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxhOjnexMCB3dmuQFQ2Zq%2Fuploads%2FET1GgLeZanVHDpPXLkM9%2FTransformers%20%2B%20TRL%20%2B%20Gemma-4.png?alt=media&#x26;token=0149149f-4d34-4bcb-a545-42e12d5127eb" alt=""><figcaption></figcaption></figure></div>
{% endcolumn %}

{% column %}

<div data-with-frame="true"><figure><img src="https://797013937-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxhOjnexMCB3dmuQFQ2Zq%2Fuploads%2FZZola3h7ujfqz87VdnQm%2FUnsloth%20%2B%20Gemma-4.png?alt=media&#x26;token=37fc2b61-ae5b-4203-b9a7-388439aefae5" alt=""><figcaption></figcaption></figure></div>
{% endcolumn %}
{% endcolumns %}

Wenn Sie Verluste sehen, die höher als 13–15 sind (z. B. 100 oder 300), wird die Gradient Accumulation höchstwahrscheinlich nicht korrekt berücksichtigt – wir haben **dies als Teil von Unsloth und Unsloth Studio behoben.**

Um mehr über Gradient Accumulation zu erfahren, sehen Sie unseren Blog zur Fehlerbehebung bei Gradient Accumulation: <https://unsloth.ai/blog/gradient>

#### :interrobang:IndexError bei der Inferenz von Gemma-4 31B und 26B-A4B

Dieser Fehler kann bei der Inferenz mit 31B und 26B auftreten:

```python
Datei "/.../cache_utils.py", Zeile 937, in update
    keys, values = self.layers[layer_idx].update(...)
IndexError: list index out of range
```

Der Übeltäter ist unten:

```python
if hasattr(decoder_config, "num_kv_shared_layers"):
    layer_types = layer_types[: -decoder_config.num_kv_shared_layers]
```

Wobei Gemma-4 31B und 26B-A4B mit `num_kv_shared_layers = 0`. In Python, `-0 == 0`führt `layer_types[:-0]` zu `layer_types[:0] == []`. Der Cache wird mit null Layer-Slots erstellt, und schon der allererste Attention-Forward-Durchlauf stürzt ab in `Cache.update`.

#### :no\_entry: `use_cache = True` Die Generierung war bei E2B, E4B Kauderwelsch

[Siehe Issue](https://github.com/huggingface/transformers/issues/45242) "\[Gemma 4] `use_cache=False` verfälscht die Attention-Berechnung und erzeugt Müll-Logits #45242"

Gemma-4 E2B und E4B teilen sich den KV-Status über die Layer hinweg (`num_kv_shared_layers = 20` und `18`). Der Cache ist der einzige Ort, an dem frühe Layer KV für spätere Layer ablegen, damit diese sie wiederverwenden können. Wenn `use_cache=False` (wie es jedes QLoRA-Tutorial setzt, und wie `gradient_checkpointing=True` erzwingt), `Gemma4TextModel.forward` wird der Cache-Aufbau übersprungen, sodass die KV-geteilten Layer stattdessen K und V lokal aus den aktuellen Hidden States neu berechnen. Die Logits werden Müll und der Trainingsverlust divergiert.

**Vorher (`unsloth/gemma-4-E2B-it`, Prompt "What is 1+1?"):**

```
use_cache=True  -> '1 + 1 = **2**'
use_cache=False -> 'BROAD\肯. Specificallyboard K supposed\_n통  \'
max_abs_logit_diff: 48.937500
```

**Nach unserem Fix:**

```
use_cache=True  -> '1 + 1 = **2**'
use_cache=False -> '1 + 1 = **2**'
max_abs_logit_diff: 0.000000     (bitgenaue Parität, alle 9 Token identisch)
```

#### :radio:Überlauf bei Audio-Float16

`Gemma4AudioAttention` verwendet `config.attention_invalid_logits_value = -1e9` in einem `masked_fill` Aufruf. Bei fp16 (Tesla T4) überläuft -1e9 den fp16-Maximalwert von 65504 und verursacht:

```python
RuntimeError: value cannot be converted to type c10::Half without overflow
```

Dies war auf `self.config.attention_invalid_logits_value` :

```python
attn_weights = attn_weights.masked_fill(
    attention_mask.logical_not(), self.config.attention_invalid_logits_value
)
```

#### 💡Tipps für Gemma-4

1. Wenn Sie **die Denkfähigkeit** erhalten möchten, können Sie Beispiele im Denkstil mit direkten Antworten mischen (mindestens 75 % Denken beibehalten). Andernfalls können Sie es vollständig ausgeben.\
   \
   Verwenden Sie `gemma-4` für die Chat-Vorlage ohne Denken und `gemma-4-thinking` für die Denk-Variante.\
   Verwenden Sie die Denk-Variante für die größeren 26B- und 31B-Modelle und die Nicht-Denk-Variante für die kleineren.<br>

   ```python
   from unsloth.chat_templates import get_chat_template
   tokenizer = get_chat_template(
       tokenizer,
       chat_template = "gemma-4-thinking", # Oder "gemma-4"
   )
   ```
2. Um den Denkmodus zu aktivieren, verwenden Sie `enable_thinking = True / False` in `tokenizer.apply_chat_template`<br>

   Denken aktiviert:

   <pre class="language-python" data-overflow="wrap"><code class="lang-python">processor.tokenizer.apply_chat_template([
       {"role" : "user", "content" : "What is 2+2?"},
   ], tokenize = False, enable_thinking = True, add_generation_prompt = True)
   </code></pre>

   Wird ausgeben `<bos><|turn>system\n<|think|><turn|>\n<|turn>user\nWhat is 2+2?<turn|>\n<|turn>model\n`<br>

   Denken deaktiviert:

   ```python
   processor.tokenizer.apply_chat_template([
       {"role" : "user", "content" : "What is 2+2?"},
   ], tokenize = False, enable_thinking = False, add_generation_prompt = True)
   ```

   Wird ausgeben `<bos><|turn>user\nWhat is 2+2?<turn|>\n<|turn>model\n<|channel>thought\n<channel|>`
3. Gemma 4 ist leistungsstark für multilinguales Fine-Tuning, da es 140 Sprachen unterstützt.
4. Es wird empfohlen, **E4B QLoRA** statt **E2B LoRA** zu trainieren, da E4B größer ist und der Unterschied in der Quantisierungsgenauigkeit minimal ist. Gemma 4 E4B LoRA ist sogar besser.
5. Nach dem Fine-Tuning können Sie exportieren nach [GGUF](#saving-export-your-fine-tuned-model) (für llama.cpp/Unsloth/Ollama/usw.)

### ⚡Schnellstart

#### 🦥 Unsloth Studio Leitfaden

{% columns %}
{% column %}
Gemma 4 kann ausgeführt und feinabgestimmt werden in [Unsloth Studio](https://unsloth.ai/docs/de/neu/studio), unserer neuen Open-Source-Web-UI für lokale KI.

Mit Unsloth Studio können Sie Modelle lokal ausführen auf **MacOS, Windows**, Linux und NVIDIA-GPUs trainieren. Unterstützung für Intel-, MLX- und AMD-Training kommt noch diesen Monat.
{% endcolumn %}

{% column %}

<div data-with-frame="true"><figure><img src="https://797013937-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxhOjnexMCB3dmuQFQ2Zq%2Fuploads%2FpZlhqoILYOzznGpbudUk%2Funsloth%20studio%20gemma%20graphic.png?alt=media&#x26;token=75e41585-e363-45cf-a87e-4d02960766ed" alt=""><figcaption></figcaption></figure></div>
{% endcolumn %}
{% endcolumns %}

{% stepper %}
{% step %}

#### Unsloth installieren

Führen Sie im Terminal aus:

**MacOS, Linux, WSL:**

```bash
curl -fsSL https://unsloth.ai/install.sh | sh
```

**Windows PowerShell:**

```bash
irm https://unsloth.ai/install.ps1 | iex
```

{% hint style="success" %}
**Die Installation geht schnell und dauert ca. 1–2 Minuten.**
{% endhint %}
{% endstep %}

{% step %}

#### Unsloth starten

**MacOS, Linux, WSL und Windows:**

```bash
unsloth studio -H 0.0.0.0 -p 8888
```

**Dann öffnen Sie `http://localhost:8888` in Ihrem Browser.**
{% endstep %}

{% step %}

#### Gemma 4 trainieren

Beim ersten Start müssen Sie ein Passwort erstellen, um Ihr Konto zu sichern, und sich später erneut anmelden. Anschließend sehen Sie einen kurzen Einrichtungsassistenten, um ein Modell, einen Datensatz und grundlegende Einstellungen auszuwählen. Sie können ihn jederzeit überspringen.

Suchen Sie in der Suchleiste nach Gemma 4 und wählen Sie Ihr gewünschtes Modell und Ihren Datensatz aus. Passen Sie anschließend Ihre Hyperparameter und die Kontextlänge nach Wunsch an.

<div data-with-frame="true"><figure><img src="https://797013937-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxhOjnexMCB3dmuQFQ2Zq%2Fuploads%2FpZlhqoILYOzznGpbudUk%2Funsloth%20studio%20gemma%20graphic.png?alt=media&#x26;token=75e41585-e363-45cf-a87e-4d02960766ed" alt="" width="563"><figcaption></figcaption></figure></div>
{% endstep %}

{% step %}

#### Trainingsfortschritt überwachen

Nachdem Sie auf Training starten geklickt haben, können Sie den Trainingsfortschritt des Modells überwachen und beobachten. Der Trainingsverlust sollte stetig sinken.\
Nach Abschluss wird das Modell automatisch gespeichert.

<div data-with-frame="true"><figure><img src="https://797013937-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxhOjnexMCB3dmuQFQ2Zq%2Fuploads%2FeBrnu9zxARIkhOHzd0pq%2FScreenshot%202026-04-07%20at%205.53.32%E2%80%AFAM.png?alt=media&#x26;token=dae77231-5020-4e8c-b2b8-cc49a98a9edf" alt="" width="563"><figcaption></figcaption></figure></div>
{% endstep %}

{% step %}

#### Ihr feinabgestimmtes Modell exportieren

Nach Abschluss ermöglicht Unsloth Studio den Export des Modells in GGUF-, Safetensor- usw\.-Formate.

<div data-with-frame="true"><figure><img src="https://797013937-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxhOjnexMCB3dmuQFQ2Zq%2Fuploads%2FBtpx58zCdrOD4zB4DPSC%2FScreenshot%202026-04-07%20at%206.12.41%E2%80%AFAM.png?alt=media&#x26;token=05f05af2-5f7f-4b91-9c99-21d6a9b04935" alt="" width="563"><figcaption></figcaption></figure></div>
{% endstep %}

{% step %}

#### Feinabgestimmtes Modell mit Originalmodell vergleichen

Klicken Sie auf `Vergleichsmodus` um den LoRA-Adapter und das Originalmodell zu vergleichen.

<div data-with-frame="true"><figure><img src="https://797013937-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxhOjnexMCB3dmuQFQ2Zq%2Fuploads%2Fvm2CBSg7QBkKwTMKutyr%2FScreenshot%202026-04-07%20at%206.14.50%E2%80%AFAM.png?alt=media&#x26;token=8c9c159f-9d5b-4468-8984-681d19ebc427" alt="" width="563"><figcaption></figcaption></figure></div>
{% endstep %}
{% endstepper %}

#### 🦥 Unsloth Core (codebasiert) Leitfaden

Wir haben kostenlose Notebooks für Gemma 4 erstellt:

| [E4B **(Inferenz + Text)**](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Gemma4_\(E4B\)-Text.ipynb) | [E4B **(Vision + Text)**](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Gemma4_\(E4B\)-Vision.ipynb) | [E4B **(Audio)**](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Gemma4_\(E4B\)-Audio.ipynb) |
| -------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| [**31B** (Kaggle)](https://www.kaggle.com/code/danielhanchen/gemma4-31b-unsloth)                                                 | [E2B **(Vision + Text)**](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Gemma4_\(E2B\)-Vision.ipynb) | [E2B **(Audio)**](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Gemma4_\(E2B\)-Audio.ipynb) |

Wir haben auch Notebooks für die größeren Gemma-4-Modelle erstellt, aber sie benötigen A100:

| [Gemma-4-26B-A4B](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Gemma4_\(26B_A4B\)-Vision.ipynb) - A100 GPU | [Gemma-4-31B](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Gemma4_\(31B\)-Vision.ipynb) - A100 GPU |
| --------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |

{% hint style="info" %}
**Wenn Sie** [**GRPO**](https://unsloth.ai/docs/de/loslegen/reinforcement-learning-rl-guide)**machen möchten, funktioniert es in Unsloth, wenn Sie die schnelle vLLM-Inferenz deaktivieren und stattdessen die Unsloth-Inferenz verwenden. Folgen Sie unseren** [**Vision RL**](https://unsloth.ai/docs/de/loslegen/reinforcement-learning-rl-guide/vision-reinforcement-learning-vlm-rl) **Notebook-Beispielen.**
{% endhint %}

Unten ist ein eigenständiges Text-SFT-Rezept für Gemma-4-26B-A4B-it. Dies ist nur Text – siehe auch unseren Abschnitt [Vision-Fine-Tuning](https://unsloth.ai/docs/de/grundlagen/vision-fine-tuning) für weitere Details.

{% code expandable="true" %}

````python
from unsloth import FastModel
import torch

model, tokenizer = FastModel.from_pretrained(
    model_name = "unsloth/gemma-4-26B-A4B-it", # Ändern Sie dies zu unsloth/gemma-4-E2B-it usw.
    dtype = None, # None für automatische Erkennung
    max_seq_length = 8192, # Wählen Sie beliebig für langen Kontext!
    load_in_4bit = True,  # 4-Bit-Quantisierung zur Speicherreduktion
    full_finetuning = False, # [NEU!] Wir haben jetzt Full Fine-Tuning!
    # token = "YOUR_HF_TOKEN", # HF-Token für geschützte Modelle
)

"""# Gemma 4 kann Text, Vision und Audio verarbeiten!

Lassen Sie uns zuerst erleben, wie Gemma 4 multimodale Eingaben verarbeiten kann. Wir verwenden die empfohlenen Einstellungen von Gemma 4: `temperature = 1.0, top_p = 0.95, top_k = 64`
"""

from transformers import TextStreamer
# Hilfsfunktion für die Inferenz
def do_gemma_4_inference(messages, max_new_tokens = 128):
    _ = model.generate(
        **tokenizer.apply_chat_template(
            messages,
            add_generation_prompt = True, # Muss für die Generierung hinzugefügt werden
            tokenize = True,
            return_dict = True,
            return_tensors = "pt",
        ).to("cuda"),
        max_new_tokens = max_new_tokens,
        use_cache=True,
        temperature = 1.0, top_p = 0.95, top_k = 64,
        streamer = TextStreamer(tokenizer, skip_prompt = True),
    )

"""# Gemma 4 kann Bilder sehen!

<img src="https://files.worldwildlife.org/wwfcmsprod/images/Sloth_Sitting_iStock_3_12_2014/story_full_width/8l7pbjmj29_iStock_000011145477Large_mini__1_.jpg" alt="Alt text" height="256">
"""

sloth_link = "https://files.worldwildlife.org/wwfcmsprod/images/Sloth_Sitting_iStock_3_12_2014/story_full_width/8l7pbjmj29_iStock_000011145477Large_mini__1_.jpg"

messages = [{
    "role" : "user",
    "content": [
        { "type": "image", "image" : sloth_link },
        { "type": "text",  "text" : "In welchen Filmen spielt dieses Tier mit?" }
    ]
}]
Sie müssen möglicherweise 1 Minute auf den Auto-Compiler von Unsloth warten
do_gemma_4_inference(messages, max_new_tokens = 256)

"""Lass uns ein Gedicht über Faultiere machen!"""

messages = [{
    "role": "user",
    "content": [{ "type" : "text",
                  "text" : "Schreibe ein Gedicht über Faultiere." }]
}]
do_gemma_4_inference(messages)

"""# Lassen Sie uns Gemma 4 feinabstimmen!

Sie können derzeit die Vision- und Textteile per Auswahl feinabstimmen – der Audio-Teil kann ebenfalls feinabgestimmt werden – wir arbeiten daran, ihn ebenfalls auswählbar zu machen!

Wir fügen jetzt LoRA-Adapter hinzu, sodass wir nur eine kleine Menge an Parametern aktualisieren müssen!
"""

model = FastModel.get_peft_model(
    model,
    finetune_vision_layers     = False, # Für nur Text deaktivieren!
    finetune_language_layers   = True,  # Sollte aktiviert bleiben!
    finetune_attention_modules = True,  # Attention gut für GRPO
    finetune_mlp_modules       = True,  # Sollte immer aktiviert bleiben!

    r = 8,           # Größer = höhere Genauigkeit, könnte aber überfitten
    lora_alpha = 8,  # Empfohlen: alpha == r mindestens
    lora_dropout = 0,
    bias = "none",
    random_state = 3407,
)

"""<a name="Data"></a>
### Datenvorbereitung
Wir verwenden jetzt das `Gemma-4`-Format für conversational finetunes. Wir verwenden das Datenset [FineTome-100k von Maxime Labonne](https://huggingface.co/datasets/mlabonne/FineTome-100k) im ShareGPT-Stil. Gemma-4 rendert mehrstufige Gespräche wie unten:

```
<bos><|turn>user
Hallo<turn|>
<|turn>model
Hey dort!<turn|>
```
Wir verwenden unsere Funktion `get_chat_template`, um die korrekte Chat-Vorlage zu erhalten. Wir unterstützen `zephyr, chatml, mistral, llama, alpaca, vicuna, vicuna_old, phi3, llama3, phi4, qwen2.5, gemma3, gemma-4` und mehr.
"""

from unsloth.chat_templates import get_chat_template
tokenizer = get_chat_template(
    tokenizer,
    chat_template = "gemma-4-thinking",
)

"""Wir nehmen die ersten 3000 Zeilen des Datensatzes"""

from datasets import load_dataset
dataset = load_dataset("mlabonne/FineTome-100k", split = "train[:3000]")

"""Wir verwenden jetzt `standardize_data_formats`, um Datensätze testweise in das korrekte Format für Fine-Tuning zu konvertieren!"""

from unsloth.chat_templates import standardize_data_formats
dataset = standardize_data_formats(dataset)

"""Schauen wir, wie Zeile 100 aussieht!"""

dataset[100]

"""Wir müssen jetzt die Chat-Vorlage für `Gemma-3` auf die Konversationen anwenden und sie in `text` speichern. Wir entfernen das `<bos>`-Token mit removeprefix(`'<bos>'`), da wir feinabstimmen. Der Processor fügt dieses Token vor dem Training hinzu und das Modell erwartet nur eines."""

def formatting_prompts_func(examples):
   convos = examples["conversations"]
   texts = [tokenizer.apply_chat_template(convo, tokenize = False, add_generation_prompt = False).removeprefix('<bos>') for convo in convos]
   return { "text" : texts, }

dataset = dataset.map(formatting_prompts_func, batched = True)

"""Schauen wir, wie die Chat-Vorlage funktioniert hat! Beachten Sie, dass es kein `<bos>`-Token gibt, da der Processor-Tokenizer eines hinzufügen wird."""

dataset[100]["text"]

"""<a name="Train"></a>
### Modell trainieren
Jetzt trainieren wir unser Modell. Wir machen 60 Schritte, um die Dinge zu beschleunigen, aber Sie können `num_train_epochs=1` für einen vollständigen Durchlauf setzen und `max_steps=None` deaktivieren.
"""

from trl import SFTTrainer, SFTConfig
trainer = SFTTrainer(
    model = model,
    tokenizer = tokenizer,
    train_dataset = dataset,
    eval_dataset = None, # Evaluation kann eingerichtet werden!
    args = SFTConfig(
        dataset_text_field = "text",
        per_device_train_batch_size = 1,
        gradient_accumulation_steps = 4, # Verwenden Sie GA, um die Batch-Größe zu imitieren!
        warmup_steps = 5,
        # num_train_epochs = 1, # Setzen Sie dies für einen vollständigen Trainingslauf.
        max_steps = 60,
        learning_rate = 2e-4, # Für lange Trainingsläufe auf 2e-5 reduzieren
        logging_steps = 1,
        optim = "adamw_8bit",
        weight_decay = 0.001,
        lr_scheduler_type = "linear",
        seed = 3407,
        report_to = "none", # TrackIO/WandB usw. verwenden
    ),
)

"""Wir verwenden auch Unsloths Methode `train_on_completions`, um nur auf den Assistenten-Ausgaben zu trainieren und den Verlust auf die Eingaben des Nutzers zu ignorieren. Das hilft, die Genauigkeit von Finetunes zu erhöhen!"""

from unsloth.chat_templates import train_on_responses_only
trainer = train_on_responses_only(
    trainer,
    instruction_part = "<|turn>user\n",
    response_part = "<|turn>model\n",
)

"""Lassen Sie uns überprüfen, ob das Maskieren des Instruktionsteils erfolgt ist! Drucken wir die 100. Zeile erneut. Beachten Sie, dass das Sample wie erwartet nur ein einzelnes `<bos>` hat!"""

tokenizer.decode(trainer.train_dataset[100]["input_ids"])

"""Jetzt drucken wir das maskierte Beispiel - Sie sollten sehen, dass nur die Antwort vorhanden ist:"""

tokenizer.decode([tokenizer.pad_token_id if x == -100 else x for x in trainer.train_dataset[100]["labels"]]).replace(tokenizer.pad_token, " ")

"""# Lassen Sie uns das Modell trainieren!

Um einen Trainingslauf fortzusetzen, setzen Sie `trainer.train(resume_from_checkpoint = True)`
"""

trainer_stats = trainer.train()
````

{% endcode %}

{% hint style="info" %}
Wenn Sie OOM haben:

* Reduzieren Sie `per_device_train_batch_size` auf **1** und/oder reduzieren Sie `max_seq_length`.&#x20;
* Behalten Sie `use_`[`gradient_checkpointing`](https://unsloth.ai/docs/de/blog/500k-context-length-fine-tuning#unsloth-gradient-checkpointing-enhancements)`="unsloth"` aktiv (es ist dafür ausgelegt, den VRAM-Verbrauch zu reduzieren und die Kontextlänge zu erweitern).
  {% endhint %}

**Ladebeispiel für MoE (bf16 LoRA):**

```python
import os
import torch
from unsloth import FastModel

model, tokenizer = FastModel.from_pretrained(
    model_name = "unsloth/Gemma-4-26B-A4B-it",
    max_seq_length = 2048,
    load_in_4bit = False,     # MoE QLoRA nicht empfohlen, dichtes 31B ist in Ordnung
    load_in_16bit = True,     # bf16/16-Bit-LoRA
    full_finetuning = False,
)
```

Nach dem Laden fügen Sie LoRA-Adapter hinzu und trainieren ähnlich wie im obigen SFT-Beispiel.

### MoE-Fine-Tuning (26B-A4B)

Das **26B-A4B** Modell ist der Mittelweg aus Geschwindigkeit und Qualität in der Gemma-4-Reihe. Da es ein **MoE** Modell ist, bei dem pro Token nur ein Teil der Parameter aktiv ist, ist ein konservativer Fine-Tuning-Ansatz:

* verwenden Sie **LoRA** statt Full Fine-Tuning
* bevorzugen Sie **16-Bit / bf16 LoRA** wenn der Speicher es erlaubt
* beginnen Sie zuerst mit kürzeren Kontexten und kleineren Rängen
* skalieren Sie erst hoch, wenn die Pipeline stabil ist

Wenn Ihr Ziel die höchste Qualität ist und Sie mehr Speicher haben, verwenden Sie **31B** stattdessen.

### Multimodales Fine-Tuning (E2B / E4B)

Da **E2B** und **E4B** Unterstützung **für** und **Bild**Audio bietet, sind sie die wichtigsten Gemma-4-Varianten für multimodales Fine-Tuning.

* Laden Sie das multimodale Modell mit `FastVisionModel`
* lassen Sie `finetune_vision_layers = False` zuerst
* nur die Sprach-, Attention- und MLP-Layer feinabstimmen
* aktivieren Sie Vision- oder Audio-Layer später, wenn Ihre Aufgabe es erfordert

#### Gemma 4 Multimodal-LoRA-Beispiel:

{% code expandable="true" %}

````python
from unsloth import FastVisionModel # FastLanguageModel für LLMs
import torch

model, processor = FastVisionModel.from_pretrained(
    "unsloth/gemma-4-26B-A4B-it",
    load_in_4bit = True, # 4bit verwenden, um den Speicherverbrauch zu reduzieren. False für 16bit LoRA.
    use_gradient_checkpointing = "unsloth", # True oder "unsloth" für langen Kontext
)

"""Wir fügen jetzt LoRA-Adapter für parameter-effizientes Fine-Tuning hinzu, sodass wir nur 1 % aller Modellparameter effizient trainieren können.

**[NEU]** Wir unterstützen außerdem das Fine-Tuning nur der Vision-Komponente, nur der Sprachkomponente oder beider. Zusätzlich können Sie wählen, ob Sie die Attention-Module, die MLP-Layer oder beides feinabstimmen möchten!
"""

model = FastVisionModel.get_peft_model(
    model,
    finetune_vision_layers     = True, # False, wenn Vision-Layer nicht feinabgestimmt werden
    finetune_language_layers   = True, # False, wenn Sprach-Layer nicht feinabgestimmt werden
    finetune_attention_modules = True, # False, wenn Attention-Layer nicht feinabgestimmt werden
    finetune_mlp_modules       = True, # False, wenn MLP-Layer nicht feinabgestimmt werden

    r = 32,                           # Je größer, desto höher die Genauigkeit, könnte aber überfitten
    lora_alpha = 32,                  # Empfohlen: alpha == r mindestens
    lora_dropout = 0,
    bias = "none",
    random_state = 3407,
    use_rslora = False,               # Wir unterstützen rank-stabilisiertes LoRA
    loftq_config = None,               # Und LoftQ
    target_modules = "all-linear",    # Jetzt optional! Kann bei Bedarf eine Liste angegeben werden
)

"""<a name="Data"></a>
### Datenvorbereitung
Wir verwenden einen gesampelten Datensatz handschriftlicher mathematischer Formeln. Ziel ist es, diese Bilder in ein maschinenlesbares Format zu konvertieren – konkret in LaTeX –, damit sie gerendert werden können. Das ist besonders nützlich für komplexe Ausdrücke.

Sie können auf den Datensatz [hier](https://huggingface.co/datasets/unsloth/LaTeX_OCR) zugreifen. Der vollständige Datensatz ist [hier](https://huggingface.co/datasets/linxy/LaTeX_OCR).
"""

from datasets import load_dataset
dataset = load_dataset("unsloth/LaTeX_OCR", split = "train")

"""Werfen wir einen Überblick über den Datensatz. Wir betrachten das zweite Bild und die dazugehörige Beschriftung."""

dataset

dataset[2]["image"]

dataset[2]["text"]

"""Wir können LaTeX auch direkt im Browser rendern!"""

from IPython.display import display, Math, Latex

latex = dataset[3]["text"]
display(Math(latex))

"""Um den Datensatz zu formatieren, sollten alle Vision-Fine-Tuning-Aufgaben diesem Format folgen:

```python
[
    {
        "role": "user",
        "content": [
            {"type": "text", "text": instruction},
            {"type": "image", "image": sample["image"]},
        ],
    },
    {
        "role": "user",
        "content": [
            {"type": "text", "text": instruction},
            {"type": "image", "image": sample["image"]},
        ],
    },
]
```
"""

instruction = "Schreiben Sie die LaTeX-Darstellung für dieses Bild."

def convert_to_conversation(sample):
    conversation = [
        {
            "role": "user",
            "content": [
                {"type": "text", "text": instruction},
                {"type": "image", "image": sample["image"]},
            ],
        },
        {"role": "assistant", "content": [{"type": "text", "text": sample["text"]}]},
    ]
    return {"messages": conversation}
pass

"""Konvertieren wir den Datensatz in das "richtige" Format für Fine-Tuning:"""

converted_dataset = [convert_to_conversation(sample) for sample in dataset]

"""Das erste Beispiel ist jetzt wie unten strukturiert:"""

converted_dataset[0]

"""Lassen Sie uns die Gemma-4-Instruktions-Chat-Vorlage nehmen und sie in unserem Basismodell verwenden"""

from unsloth import get_chat_template

processor = get_chat_template(
    processor,
    "gemma-4-thinking"
)

"""Vor dem Fine-Tuning lassen Sie uns die Leistung des Basismodells bewerten. Wir erwarten keine starken Ergebnisse, da es diese Chat-Vorlage noch nicht gesehen hat."""

image = dataset[2]["image"]
instruction = "Schreiben Sie die LaTeX-Darstellung für dieses Bild."

messages = [
    {
        "role": "user",
        "content": [{"type": "image"}, {"type": "text", "text": instruction}],
    }
]
input_text = processor.apply_chat_template(messages, add_generation_prompt = True)
inputs = processor(
    image,
    input_text,
    add_special_tokens = False,
    return_tensors = "pt",
).to("cuda")

from transformers import TextStreamer

text_streamer = TextStreamer(processor, skip_prompt = True)
result = model.generate(**inputs, streamer = text_streamer, max_new_tokens = 128,
                        use_cache = True, temperature = 1.0, top_p = 0.95, top_k = 64)

"""Du kannst sehen, dass es absolut schrecklich ist! Es befolgt überhaupt keine Anweisungen

<a name="Train"></a>
### Modell trainieren
Jetzt trainieren wir unser Modell. Wir machen 60 Schritte, um die Sache zu beschleunigen, aber du kannst `num_train_epochs=1` für einen vollständigen Durchlauf setzen und `max_steps=None` deaktivieren. Wir unterstützen außerdem `DPOTrainer` und `GRPOTrainer` für Reinforcement Learning!!

Wir verwenden unseren neuen `UnslothVisionDataCollator`, der uns bei unserem Vision-Finetuning-Setup hilft.
"""

from unsloth.trainer import UnslothVisionDataCollator
from trl import SFTTrainer, SFTConfig

trainer = SFTTrainer(
    model = model,
    train_dataset = converted_dataset,
    processing_class = processor.tokenizer,
    data_collator = UnslothVisionDataCollator(model, processor),
    args = SFTConfig(
        per_device_train_batch_size = 1,
        gradient_accumulation_steps = 4,
        max_grad_norm = 0.3,
        warmup_ratio = 0.03,
        max_steps = 60,
        # num_train_epochs = 2, # Setze dies anstelle von max_steps für vollständige Trainingsläufe
        learning_rate = 2e-4,
        logging_steps = 1,
        save_strategy = "steps",
        optim = "adamw_8bit",
        weight_decay = 0.001,
        lr_scheduler_type = "cosine",
        seed = 3407,
        output_dir = "outputs",
        report_to = "none", # Für Weights and Biases oder andere

        # Du MUSST die folgenden Elemente für das Vision-Finetuning angeben:
        remove_unused_columns = False,
        dataset_text_field = "",
        dataset_kwargs = {"skip_prepare_dataset": True},
        max_length = 2048,
    )
)

trainer_stats = trainer.train()
````

{% endcode %}

#### Bildbeispielformat

Erinnerung: Für multimodale Gemma-4-Prompts platziere das Bild **vor** der Textanweisung.

{% code expandable="true" %}

```json
{
  "messages": [
    {
      "role": "user",
      "content": [
        {"type": "image", "image": "/path/to/image ODER object"},
        {"type": "text", "text": "Extrahiere den gesamten Text aus dieser Quittung. Gib Positionen, Gesamtbetrag, Händler und Datum als JSON zurück."}
      ]
    },
    {
      "role": "assistant",
      "content": [
        {"type": "text", "text": "{\"merchant\": \"Beispielgeschäft\", \"total\": \"19.99\"}"}
      ]
    }
  ]
}
```

{% endcode %}

#### Audio-Beispielformat

Audio ist nur für **E2B / E4B** gedacht. Halte die Clips kurz und auf die Aufgabe zugeschnitten.

{% code expandable="true" %}

```json
{
  "messages": [
    {
      "role": "user",
      "content": [
        {"type": "audio", "audio": "/path/to/audio ODER object"},
        {"type": "text", "text": "Transkribiere den folgenden Sprachabschnitt auf Englisch in englischen Text. Gib nur die Transkription aus."}
      ]
    },
    {
      "role": "assistant",
      "content": [
        {"type": "text", "text": "Hallo zusammen und willkommen zurück."}
      ]
    }
  ]
}
```

{% endcode %}

### Speichern / Export des feinabgestimmten Modells

Du kannst unsere spezifischen Anleitungen für Inferenz / Bereitstellung einsehen für [Unsloth Studio](https://unsloth.ai/docs/de/neu/studio/export), [llama.cpp](https://unsloth.ai/docs/de/grundlagen/inference-and-deployment/saving-to-gguf), [vLLM](https://unsloth.ai/docs/de/grundlagen/inference-and-deployment/vllm-guide), [llama-server](https://unsloth.ai/docs/de/grundlagen/inference-and-deployment/llama-server-and-openai-endpoint), [Ollama](https://unsloth.ai/docs/de/grundlagen/inference-and-deployment/saving-to-ollama) oder [SGLang](https://unsloth.ai/docs/de/grundlagen/inference-and-deployment/sglang-guide).

#### In GGUF speichern

Unsloth unterstützt das direkte Speichern nach GGUF:

```python
model.save_pretrained_gguf("directory", tokenizer, quantization_method = "q4_k_m")
model.save_pretrained_gguf("directory", tokenizer, quantization_method = "q8_0")
model.save_pretrained_gguf("directory", tokenizer, quantization_method = "f16")
```

Oder GGUFs zu Hugging Face hochladen:

```python
model.push_to_hub_gguf("hf_username/directory", tokenizer, quantization_method = "q4_k_m")
model.push_to_hub_gguf("hf_username/directory", tokenizer, quantization_method = "q8_0")
```

Wenn sich das exportierte Modell in einer anderen Laufzeitumgebung schlechter verhält, nennt Unsloth die häufigste Ursache: **falsches Chat-Template / EOS-Token zur Inferenzzeit** (du musst dasselbe Chat-Template verwenden, mit dem du trainiert hast).

Für weitere Details lies unsere Inferenz-Anleitungen:

{% columns %}
{% column width="50%" %}
{% content-ref url="../../grundlagen/inference-and-deployment" %}
[inference-and-deployment](https://unsloth.ai/docs/de/grundlagen/inference-and-deployment)
{% endcontent-ref %}

{% content-ref url="../../grundlagen/inference-and-deployment/saving-to-gguf" %}
[saving-to-gguf](https://unsloth.ai/docs/de/grundlagen/inference-and-deployment/saving-to-gguf)
{% endcontent-ref %}
{% endcolumn %}

{% column width="50%" %}
{% content-ref url="../../neu/studio/export" %}
[export](https://unsloth.ai/docs/de/neu/studio/export)
{% endcontent-ref %}

{% content-ref url="../../grundlagen/inference-and-deployment/vllm-guide" %}
[vllm-guide](https://unsloth.ai/docs/de/grundlagen/inference-and-deployment/vllm-guide)
{% endcontent-ref %}
{% endcolumn %}
{% endcolumns %}

### Bewährte Praktiken für Gemma-4-Daten

Gemma 4 hat einige Formatierungsdetails, die du beachten musst.

#### 1. Verwende standardmäßige Chat-Rollen

Gemma 4 verwendet die Standardrollen:

* `system`
* `user`
* `assistant`

Das bedeutet, dass dein SFT-Datensatz im regulären Chat-Format statt in älteren Gemma-spezifischen Rollenformaten geschrieben sein sollte.

#### 2. Der Denkmodus ist explizit

Wenn du das denkstilartige Verhalten während des SFT beibehalten möchtest:

* halte das Format konsistent
* entscheide, ob du auf **sichtbare Denkblöcke** oder auf **nur finale Antworten**
* trainieren **nicht** mehrere inkompatible Denkformate im selben Datensatz mischen

Für die meisten produktiven Assistenten ist das einfachste Setup, das Modell auf die **nur endgültige sichtbare Antwort**.

#### 3. Regel für Mehrfachdialoge

Für Unterhaltungen mit mehreren Runden behalte in der Gesprächshistorie nur die **endgültige sichtbare Antwort** Do **nicht** füge frühere Denkblöcke nicht in spätere Runden wieder ein.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://unsloth.ai/docs/de/modelle/gemma-4/train.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
