Corso
In questo tutorial impareremo a eseguire il fine-tuning del modello Gemma 2 sul dataset di conversazioni tra pazienti e medici. Convertiremo inoltre il modello nel formato GGUF, in modo che possa essere usato in locale sul laptop offline.
Prima di procedere con il fine-tuning del modello Gemma 2 sul dataset di conversazioni paziente-medico, conosceremo Gemma 2 e i suoi miglioramenti rispetto alle generazioni precedenti. Poi uniremo l’adapter salvato al modello base, pubblicheremo il modello completo su Hugging Face Hub e useremo uno Space di Hugging Face per convertire e quantizzare il modello. Infine, scaricheremo il modello quantizzato e lo useremo in locale con l’applicazione Jan.

Immagine dell’autore
Capire Gemma 2
Gemma 2 è l’ultimo rilascio della famiglia Gemma di large language models (LLM) open di Google. È disponibile per ricercatori e sviluppatori in due dimensioni, 9 miliardi (9B) e 27 miliardi (27B) di parametri, con una licenza adatta all’uso commerciale. Questo significa che puoi farne il fine-tuning sul tuo dataset privato e distribuire il modello ottimizzato in produzione senza restrizioni.

Fonte: Google lancia Gemma 2
Gemma 2 offre notevoli progressi in termini di prestazioni ed efficienza in inferenza. L’architettura riprogettata garantisce un’inferenza fulminea su vari setup hardware e un’integrazione senza soluzione di continuità con i principali framework di IA come Hugging Face Transformers, JAX, PyTorch e TensorFlow.
Gemma 2 include anche solide misure di sicurezza e strumenti per un’adozione etica dell’IA. Supera Llama 3 e Groq-1 su vari benchmark e offre un’integrazione migliorata con Keras 3 per un fine-tuning e un’inferenza del modello più fluidi.
Se vuoi approfondire la prima generazione dei modelli Gemma, ti consigliamo il nostro tutorial Fine Tuning Google Gemma: Enhancing LLMs with Customized Instructions. Questa risorsa fornisce indicazioni complete su come fare fine-tuning dei modelli Gemma, come Gemma 7b-it, su dataset e task specifici.
Accedere a Gemma 2
In questa sezione scaricheremo il modello, lo caricheremo con quantizzazione a 4 bit e poi eseguiremo l’inferenza su GPU.
- Installa tutti i pacchetti Python necessari.
%%capture
%pip install -U bitsandbytes
%pip install -U transformers
%pip install -U accelerate
- Usiamo Kaggle come ambiente di sviluppo. Dobbiamo creare una variabile d’ambiente tramite la funzione "Secrets" e poi attivarla. La variabile d’ambiente contiene un token Hugging Face che puoi generare accedendo al sito di Hugging Face.

- Recupera in modo sicuro il token Hugging Face da Kaggle Secrets e usalo per accedere alla CLI di Hugging Face. L’accesso ci aiuterà a scaricare modelli e dataset con restrizioni.
from huggingface_hub import login
from kaggle_secrets import UserSecretsClient
user_secrets = UserSecretsClient()
hf_token = user_secrets.get_secret("HUGGINGFACE_TOKEN")
login(token = hf_token)
- Carica il tokenizer usando il link del repository del modello Gemma 2 su Hugging Face.
- Carica il modello usando il nome, le impostazioni di quantizzazione a 4 bit e la device map. Per prima cosa scaricherà i file completi del modello, poi lo caricherà in 4 bit per ottimizzare calcolo e memoria.
Nota: Il modello Gemma 2 9B-It è grande e, anche con 16 GB di memoria GPU, non possiamo caricarlo per intero. Per questo lo carichiamo con quantizzazione a 4 bit.
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig, AutoConfig
modelName = "google/gemma-2-9b-it"
bnbConfig = BitsAndBytesConfig(
load_in_4bit = True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.bfloat16,
)
tokenizer = AutoTokenizer.from_pretrained(modelName)
model = AutoModelForCausalLM.from_pretrained(
modelName,
device_map = "auto",
quantization_config=bnbConfig
)
- Crea il prompt usando le istruzioni di sistema e la domanda dell’utente.
- Converti i prompt in token usando i tokenizer.
- Genera la risposta e poi decodificala in testo inglese leggibile.
- Mostra il risultato convertendo lo stile Markdown in formato HTML.
from IPython.display import Markdown, display
system = "You are a skilled software architect who consistently creates system designs for various applications."
user = "Design a system with the ASCII diagram for the customer support application."
prompt = f"System: {system} \n User: {user} \n AI: "
inputs = tokenizer(prompt, return_tensors='pt', padding=True, truncation=True).to("cuda")
outputs = model.generate(**inputs, max_length=500, num_return_sequences=1)
text = tokenizer.decode(outputs[0], skip_special_tokens=True)
Markdown(text.split("AI:")[1])
Come possiamo vedere, il modello Gemma 2 ha fatto un ottimo lavoro.

Se riscontri problemi con l’esecuzione del codice sopra, consulta il Notebook Kaggle: Gemma 2 Simple Inference on GPU.
Fine-tuning di Gemma 2 con LoRA
In questa sezione eseguiremo il fine-tuning del modello Gemma 2 9B-It sul dataset sanitario, che consiste in conversazioni tra pazienti e medici. Caricheremo il modello e il tokenizer, caricheremo il dataset, lo convertiremo, configureremo il modello con gli argomenti di training e tracceremo le prestazioni con l’API Weights and Biases.
Se ti interessa capire la teoria del fine-tuning, leggi la nostra guida An Introductory Guide to Fine-Tuning LLMs.
1. Configurazione
Installa i pacchetti Python necessari per caricare, fare fine-tuning e valutare il modello sul dataset medico.
%%capture
%pip install -U transformers
%pip install -U datasets
%pip install -U accelerate
%pip install -U peft
%pip install -U trl
%pip install -U bitsandbytes
%pip install -U wandb
Carica i pacchetti Python necessari e le funzioni.
from transformers import (
AutoModelForCausalLM,
AutoTokenizer,
BitsAndBytesConfig,
HfArgumentParser,
TrainingArguments,
pipeline,
logging,
)
from peft import (
LoraConfig,
PeftModel,
prepare_model_for_kbit_training,
get_peft_model,
)
import os, torch, wandb
from datasets import load_dataset
from trl import SFTTrainer, setup_chat_format
Accedi alla CLI di Hugging Face usando la chiave API che abbiamo salvato con Kaggle Secrets.
from huggingface_hub import login
from kaggle_secrets import UserSecretsClient
user_secrets = UserSecretsClient()
hf_token = user_secrets.get_secret("HUGGINGFACE_TOKEN")
login(token = hf_token)
Carica la chiave API di Weights and Biases da Kaggle Secrets per avviare il progetto di monitoraggio delle prestazioni del modello.
wb_token = user_secrets.get_secret("wandb")
wandb.login(key=wb_token)
run = wandb.init(
project='Fine-tune Gemma-2-9b-it on HealthCare Dataset',
job_type="training",
anonymous="allow"
)
Imposta l’ID del modello e del dataset per caricarli da Hugging Face Hub. Inoltre, imposta il nome del modello con fine-tuning per creare un repository su Hugging Face e caricarlo.
base_model = "google/gemma-2-9b-it"
dataset_name = "lavita/ChatDoctor-HealthCareMagic-100k"
new_model = "Gemma-2-9b-it-chat-doctor"
2. Caricamento del modello e del tokenizer
Impostazione del tipo di dato e dell’implementazione dell’attenzione in base alla GPU.
if torch.cuda.get_device_capability()[0] >= 8:
!pip install -qqq flash-attn
torch_dtype = torch.bfloat16
attn_implementation = "flash_attention_2"
else:
torch_dtype = torch.float16
attn_implementation = "eager"
Dobbiamo creare la configurazione QLoRA per caricare il modello con precisione a 4 bit, riducendo l’uso di memoria e accelerando il processo di fine-tuning.
# QLoRA config
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch_dtype,
bnb_4bit_use_double_quant=True,
)
Usando l’URL del modello, la configurazione LoRA e l’implementazione dell’attenzione, carica il modello Gemma 2 9B-It e il tokenizer.
# Load model
model = AutoModelForCausalLM.from_pretrained(
base_model,
quantization_config=bnb_config,
device_map="auto",
attn_implementation=attn_implementation
)
# Load tokenizer
tokenizer = AutoTokenizer.from_pretrained(base_model, trust_remote_code=True)
3. Aggiunta dell’adapter al layer
Crea la funzione Python che userà il modello ed estrarrà i nomi di tutti i moduli lineari.
import bitsandbytes as bnb
def find_all_linear_names(model):
cls = bnb.nn.Linear4bit
lora_module_names = set()
for name, module in model.named_modules():
if isinstance(module, cls):
names = name.split('.')
lora_module_names.add(names[0] if len(names) == 1 else names[-1])
if 'lm_head' in lora_module_names: # needed for 16 bit
lora_module_names.remove('lm_head')
return list(lora_module_names)
modules = find_all_linear_names(model)
Il fine-tuning dell’intero modello richiede molto tempo, quindi per accelerare l’addestramento creeremo e collegheremo un adapter, ottenendo un processo più veloce ed efficiente in memoria.
Lo strato di adattamento viene creato usando i moduli target e il tipo di task. Successivamente impostiamo il formato chat per modello e tokenizer. Infine, colleghiamo il modello base all’adapter per creare un modello PEFT (Parameter Efficient Fine-Tuning).
# LoRA config
peft_config = LoraConfig(
r=16,
lora_alpha=32,
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM",
target_modules=modules
)
model, tokenizer = setup_chat_format(model, tokenizer)
model = get_peft_model(model, peft_config)
4. Caricamento del dataset
Ora caricheremo il dataset lavita/ChatDoctor-HealthCareMagic-100k dall’hub di Hugging Face. Il dataset consiste in tre colonne:
- instruction: contiene le istruzioni di sistema.
- input: la richiesta dettagliata del paziente.
- output: la risposta del medico alla richiesta del paziente.
Dopo aver caricato il dataset, lo mescoleremo e selezioneremo 1000 campioni per ridurre ulteriormente i tempi di training. Infine, creeremo il formato chat usando il template predefinito e lo useremo per creare la colonna “text”.
#Importing the dataset
dataset = load_dataset(dataset_name, split="all")
dataset = dataset.shuffle(seed=65).select(range(1000)) # Only use 1000 samples for quick demo
def format_chat_template(row):
row_json = [{"role": "system", "content": row["instruction"]},
{"role": "user", "content": row["input"]},
{"role": "assistant", "content": row["output"]}]
row["text"] = tokenizer.apply_chat_template(row_json, tokenize=False)
return row
dataset = dataset.map(
format_chat_template,
num_proc= 4,
)
dataset
Output:
Dataset({
features: ['instruction', 'input', 'output', 'text'],
num_rows: 1000
})
Vediamo la colonna “text” della riga 3.
dataset['text'][3]
La colonna “text” contiene istruzioni, richiesta del paziente e risposta del medico nello stile OpenAI.

Per la valutazione del modello, divideremo il dataset in training e test.
dataset = dataset.train_test_split(test_size=0.1)
5. Compilazione e training del modello
Ora imposteremo gli argomenti di training e i parametri SFT e avvieremo il processo di addestramento.
Puoi modificare i vari iperparametri in base al tuo ambiente, alla potenza di calcolo e alla memoria. Gli iperparametri sotto sono ottimizzati per il Notebook Kaggle. Quindi, se vuoi eseguire la stessa procedura su Google Colab, valuta di sperimentare con gli algoritmi di training.
# Setting Hyperparamter
training_arguments = TrainingArguments(
output_dir=new_model,
per_device_train_batch_size=1,
per_device_eval_batch_size=1,
gradient_accumulation_steps=2,
optim="paged_adamw_32bit",
num_train_epochs=1,
eval_strategy="steps",
eval_steps=0.2,
logging_steps=1,
warmup_steps=10,
logging_strategy="steps",
learning_rate=2e-4,
fp16=False,
bf16=False,
group_by_length=True,
report_to="wandb"
)
# Setting sft parameters
trainer = SFTTrainer(
model=model,
train_dataset=dataset["train"],
eval_dataset=dataset["test"],
peft_config=peft_config,
max_seq_length= 512,
dataset_text_field="text",
tokenizer=tokenizer,
args=training_arguments,
packing= False,
)
model.config.use_cache = False
trainer.train()
Il fine-tuning del modello ha richiesto quasi 25 minuti e, come possiamo vedere, la training loss e la validation loss si sono ridotte gradualmente. Per prestazioni migliori, prova a eseguire il fine-tuning sul dataset completo per almeno tre epoche.
Il fine-tuning può essere un po’ tecnico per chi è alle prime armi o non tecnico. Se cerchi una soluzione più semplice, dai un’occhiata al tutorial Fine-Tuning OpenAI's GPT-4: A Step-by-Step Guide. Copre un modo semplice per fare fine-tuning di un modello all’avanguardia usando l’API di OpenAI.
6. Valutazione del modello
Concluderemo l’esperimento su Weights and Biases, che genererà un report di valutazione.
wandb.finish()
model.config.use_cache = True

Per visualizzare il report dettagliato, vai al tuo account Weights and Biases e clicca sul nome del progetto "Fine-tune Gemma-2-9b-it on Healthcare Dataset".

Screenshot da wandb.ai
7. Salvataggio delle modifiche
Ora salveremo in locale l’adapter con fine-tuning e lo caricheremo anche su Hugging Face Hub.
trainer.model.save_pretrained(new_model)
trainer.model.push_to_hub(new_model, use_temp_dir=False)
Per usare l’adapter salvato in un altro notebook Kaggle, dobbiamo salvare il notebook. Possiamo farlo cliccando su “Save Version” in alto a destra. Poi seleziona “Quick Save” e “Always save output when creating a Quick Save”, quindi premi il pulsante “Save”.

Se hai problemi a eseguire il codice, clona il Notebook Kaggle ed eseguilo. Devi configurare le chiavi API di Hugging Face e Weights & Biases tramite Kaggle Secrets.
Per capire se il fine-tuning o la Retrieval-Augmented Generation (RAG) sia più adatto al tuo caso d’uso, ti consiglio vivamente di leggere il post RAG vs Fine-Tuning.
Unire il modello base con l’adapter
Ora uniremo l’adapter al modello base e caricheremo il modello completo su Hugging Face Hub.
Crea un nuovo notebook Kaggle con CPU come acceleratore e installa i pacchetti Python necessari.
Perché usiamo la CPU come acceleratore? Non sarà lento? Sì, ma la macchina GPU su Kaggle offre solo 16 GB di memoria, sufficienti per un modello da 7 miliardi di parametri ma non per uno da 9 miliardi. La macchina CPU invece offre 30 GB, sufficienti per caricare sia il modello base che l’adapter.
%%capture
%pip install -U bitsandbytes
%pip install -U transformers
%pip install -U accelerate
%pip install -U peft
%pip install -U trl
Recupera la chiave API da Kaggle Secrets e accedi alla CLI di Hugging Face.
from huggingface_hub import login
from kaggle_secrets import UserSecretsClient
user_secrets = UserSecretsClient()
hf_token = user_secrets.get_secret("HUGGINGFACE_TOKEN")
login(token = hf_token)
Per accedere al modello salvato, devi importare il notebook Kaggle salvato. Per farlo, clicca sul pulsante “Add Input” in alto a destra e seleziona la scheda “Your Work”. Poi clicca sul pulsante più del notebook salvato per accedere a tutti i suoi file.

Configura l’URL del modello base fornendo il nome del repository su Hugging Face. Inoltre, configura l’URL dell’adapter specificando la directory locale in cui è salvato.
base_model_url = "google/gemma-2-9b-it"
new_model_url = "/kaggle/input/fine-tune-gemma-2-9b-it-on-healthcare-dataset/Gemma-2-9b-it-chat-doctor/"
Carica il tokenizer e il modello completo usando l’URL del modello base. Assicurati di impostare il device “cpu” e il dtype “float16”.
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig, pipeline
from peft import PeftModel
import torch
from trl import setup_chat_format
# Reload tokenizer and model
tokenizer = AutoTokenizer.from_pretrained(base_model_url)
base_model_reload= AutoModelForCausalLM.from_pretrained(
base_model_url,
low_cpu_mem_usage=True,
return_dict=True,
torch_dtype=torch.float16,
device_map="cpu",
)
Imposta il formato chat sul modello base appena caricato e combinalo con l’adapter. Infine, caricheremo e uniremo l’adapter al modello base.
La funzione merge_and_unload() ci aiuterà a fondere i pesi dell’adapter con il modello base e a usarlo come modello autonomo.
base_model_reload, tokenizer = setup_chat_format(base_model_reload, tokenizer)
model = PeftModel.from_pretrained(base_model_reload, new_model_url)
model = model.merge_and_unload()
Salva in locale il modello completo e il tokenizer.
model.save_pretrained("Gemma-2-9b-it-chat-doctor")
tokenizer.save_pretrained("Gemma-2-9b-it-chat-doctor")
Carica inoltre tutti i file del modello e il tokenizer su Hugging Face Hub.
model.push_to_hub("Gemma-2-9b-it-chat-doctor", use_temp_dir=False)
tokenizer.push_to_hub("Gemma-2-9b-it-chat-doctor", use_temp_dir=False)
Puoi andare al repository del tuo modello su Hugging Face e visualizzare tutti i file.

Fonte: kingabzpro/Gemma-2-9b-it-chat-doctor · Hugging Face
Se riscontri problemi nell’unire i modelli usando la CPU, consulta il Notebook Kaggle.
Quantizzazione con Hugging Face Space
Con lo Space di Hugging Face GGUF My Repo, la conversione e la quantizzazione dei modelli sono diventate semplici e veloci. Tutto ciò che devi fare è accedere e fornire l’ID del modello.

Fonte: GGUF My Repo - uno Space di Hugging Face di ggml-org
Creerà per te un nuovo repository di modello con un file quantizzato che potrai scaricare successivamente per usarlo in locale. È davvero così semplice.
Puoi approfondire la teoria della quantizzazione leggendo il nostro articolo Quantization for Large Language Models (LLMs): Reduce AI Model Sizes Efficiently.

Fonte: kingabzpro/Gemma-2-9b-it-chat-doctor-Q4_K_M-GGUF · Hugging Face
Se invece vuoi “sporcarti le mani” ed eseguire gli script di llama.cpp per conto tuo, dai un’occhiata al tutorial Fine-Tuning Llama 3 and Using It Locally.
Uso del modello con fine-tuning in locale
Per usare il modello quantizzato in locale:
- Per prima cosa scarica e installa l’applicazione Jan dal sito ufficiale.
- Avvia l’app e vai al “Model Hub”. Puoi accedere ai menu cliccando sul pulsante di Windows “🪟” in alto a sinistra.
- Incolla il link al repository del modello con fine-tuning nella barra di ricerca e premi invio: "kingabzpro/Gemma-2-9b-it-chat-doctor-Q4_K_M-GGUF"

- Verrai reindirizzato a un nuovo menu, dove avrai l’opzione per scaricare il modello direttamente.

- Vai al menu “Thread” e seleziona il modello con fine-tuning dal tab “Model” in alto a destra.

- Inizia a fare domande all’assistente AI e ottieni risposte personalizzate.

- Come possiamo vedere, la risposta iniziale è mediocre. Dobbiamo modificare alcuni parametri del modello. Vai al tab “Model” e inizia a regolare i seguenti argomenti:
- Stop: <endofstring>, Best wishes, Chat Doctor.
- Frequency Penalty: 0,5
- Max Tokens: 680
- Vai al tab “Assistant” e cambia le Instructions in “Sei un medico: rispondi alle domande mediche in base alla descrizione del paziente”.
- Metti alla prova il modello con più domande e sperimenta risultati di alta qualità e al punto.

Conclusione
Gemma 2 è un ottimo modello e può dare il meglio se usi il framework Keras 3 per il fine-tuning distribuito e l’inferenza. Otterrai tempi più rapidi di training e inferenza rispetto all’uso di Transformers.
Puoi imparare a fare fine-tuning del modello Gemma ed eseguire l’inferenza con Keras 3 seguendo il tutorial Fine-Tune and Run Inference on Google's Gemma Model with TPU.
In questo tutorial abbiamo conosciuto i modelli Gemma 2 e come accedervi tramite la libreria Transformers. Abbiamo anche imparato a fare fine-tuning del modello su conversazioni paziente-medico, a unire l’adapter al modello base, a pubblicare il modello completo su Hugging Face Hub, a convertire e quantizzare il modello usando uno Space di Hugging Face, a scaricarlo e a eseguirlo in locale sul laptop con l’app Jan.
È un progetto divertente che gli appassionati di IA dovrebbero provare. Migliorerà la capacità di risolvere i problemi che emergono durante il fine-tuning dei large language models. Le sfide principali riguardano spesso i limiti di memoria e calcolo, oltre alla riduzione della loss.
Puoi anche imparare a sviluppare i tuoi LLM con PyTorch e Hugging Face nel corso Developing Large Language Models su DataCamp.
In quanto data scientist certificato, sono appassionato di sfruttare tecnologie all’avanguardia per creare applicazioni di machine learning innovative. Con una solida esperienza in riconoscimento vocale, analisi e reportistica dei dati, MLOps, AI conversazionale e NLP, ho affinato le mie competenze nello sviluppo di sistemi intelligenti in grado di avere un impatto concreto. Oltre alla mia expertise tecnica, sono anche un comunicatore efficace, con il talento di rendere chiari e sintetici concetti complessi. Di conseguenza, sono diventato un blogger molto seguito in ambito data science, condividendo idee ed esperienze con una community in crescita di professionisti dei dati. Attualmente mi concentro sulla creazione e sull’editing di contenuti, lavorando con large language model per sviluppare contenuti potenti e coinvolgenti che possano aiutare aziende e singoli a valorizzare al meglio i propri dati.


