{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "EAsv3uyVZERg"
},
"source": [
"# Quantization Aware Training (QAT)\n",
"\n",
"[](https://colab.research.google.com/github/google-deepmind/gemma/blob/main/colabs/quantization_aware_training.ipynb)\n",
"\n",
"This is an example on how to obtain and run quantized versions of Gemma models. It's best to first read the [finetuning](https://gemma-llm.readthedocs.io/en/latest/finetuning.html) colab to understand this one.\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"executionInfo": {
"elapsed": 3,
"status": "ok",
"timestamp": 1741556668372,
"user": {
"displayName": "",
"userId": ""
},
"user_tz": -60
},
"id": "7EM9c9_kZERg"
},
"outputs": [],
"source": [
"!pip install -q gemma"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"executionInfo": {
"elapsed": 5222,
"status": "ok",
"timestamp": 1741556673717,
"user": {
"displayName": "",
"userId": ""
},
"user_tz": -60
},
"id": "j85GsCFMZERg"
},
"outputs": [],
"source": [
"# Common imports\n",
"import os\n",
"import treescope\n",
"import optax\n",
"\n",
"# Gemma imports\n",
"from kauldron import kd\n",
"from gemma import gm\n",
"from gemma import peft"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "4Chiw4WkZERg"
},
"source": [
"By default, Jax do not utilize the full GPU memory, but this can be overwritten. See [GPU memory allocation](https://docs.jax.dev/en/latest/gpu_memory_allocation.html):"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"executionInfo": {
"elapsed": 52,
"status": "ok",
"timestamp": 1741556673898,
"user": {
"displayName": "",
"userId": ""
},
"user_tz": -60
},
"id": "yh5RMMLy4DR1"
},
"outputs": [],
"source": [
"os.environ[\"XLA_PYTHON_CLIENT_MEM_FRACTION\"]=\"1.00\""
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "-apwpcjNZERg"
},
"source": [
"## Config updates\n",
"\n",
"If you're familiar with the [finetuning](https://gemma-llm.readthedocs.io/en/latest/finetuning.html) tutorial, switching to QAT only require 1 change to the trainer.\n",
"\n",
"This is slightly different to LoRA (we discuss the difference below)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "Id0PQE16ZERg"
},
"source": [
"### 1. Model\n",
"\n",
"Wrap the model in the `gm.nn.QuantizationAwareTrainingWrapper`. This will apply model surgery to replace all the linear and compatible layers with Simulation for Quantized layers. You can choose among several options for quantization:\n",
"\n",
"* SFP8: switched floating point in 8 bits (very efficient with gemma.cpp)\n",
"* Q4_0: per-block integer quantization (equivalent to 4.5 bits per weights), very popular on llama.cpp\n",
"* INT4: per-channel weight quantization (almost exactly 4 bits per weights)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"executionInfo": {
"elapsed": 9380,
"status": "ok",
"timestamp": 1741556683410,
"user": {
"displayName": "",
"userId": ""
},
"user_tz": -60
},
"id": "rKHZ6d3-ZERg"
},
"outputs": [],
"source": [
"model = gm.nn.QuantizationAwareWrapper(\n",
" method = peft.QuantizationMethod.INT8,\n",
" model=gm.nn.Gemma3_4B(tokens=\"batch.input\", text_only=True),\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "9MBCCglxdwht"
},
"source": [
"Internally, this uses the [`gemma.peft`](https://github.com/google-deepmind/gemma/blob/main/gemma/peft) mini-library to perform model surgery."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"executionInfo": {
"elapsed": 54,
"status": "ok",
"timestamp": 1741556683592,
"user": {
"displayName": "",
"userId": ""
},
"user_tz": -60
},
"id": "lS_OkUkWgsvP"
},
"outputs": [],
"source": [
"init_transform = wrapped=gm.ckpts.LoadCheckpoint(\n",
" path=gm.ckpts.CheckpointPath.GEMMA3_4B_IT,\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "O9kiQmjgdwht"
},
"source": [
"## Training"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "ybKFzaE_dwht"
},
"source": [
"### Data pipeline\n",
"\n",
"Like for the [finetuning](https://gemma-llm.readthedocs.io/en/latest/finetuning.html) example, we recreate the tokenizer:"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"executionInfo": {
"elapsed": 822,
"status": "ok",
"timestamp": 1741556684537,
"user": {
"displayName": "",
"userId": ""
},
"user_tz": -60
},
"id": "u5MZYuTBdwht",
"outputId": "7eaa77fc-179e-4f8a-cfa7-cb5cd63e2597"
},
"outputs": [
{
"data": {
"text/plain": [
"[<_Gemma3SpecialTokens.BOS: 2>, 2094, 563, 614, 2591, 13315]"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"tokenizer = gm.text.Gemma3Tokenizer()\n",
"\n",
"tokenizer.encode('This is an example sentence', add_bos=True)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "0QNkBrD8dwht"
},
"source": [
"And the data pipeline:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"colab": {
"height": 394
},
"executionInfo": {
"elapsed": 17257,
"status": "ok",
"timestamp": 1741556701922,
"user": {
"displayName": "",
"userId": ""
},
"user_tz": -60
},
"id": "ULN7oQ_8dwht",
"outputId": "781108d4-eb01-479e-8028-96320966967c"
},
"outputs": [
{
"data": {
"text/html": [
"