Modelli e piattaforme di IA

L’unico Guida di cui Hai Bisogno per Fine-Tuning Llama 3 o Altri Modelli Open Source

mm
Aggiungi Unite.AI alle tue fonti preferite su Google

Il fine-tuning dei grandi modelli linguistici (LLM) come Llama 3 consiste nell’adattare un modello pre-addestrato a compiti specifici utilizzando un dataset specifico del dominio. Questo processo sfrutta la conoscenza pre-esistente del modello, rendendolo efficiente e conveniente rispetto all’addestramento da zero. In questa guida, passeremo attraverso i passaggi per fine-tuning Llama 3 utilizzando QLoRA (Quantized LoRA), un metodo efficiente in termini di parametri che minimizza l’utilizzo della memoria e i costi computazionali.

Panoramica del Fine-Tuning

Il fine-tuning comprende diversi passaggi chiave:

  1. Selezione del Modello Pre-addestrato: Scegliere un modello base che si allinei con l’architettura desiderata.
  2. Raccolta del Dataset: Raccogliere e pre-elaborare un dataset specifico per il compito.
  3. Fine-Tuning: Adattare il modello utilizzando il dataset per migliorare le sue prestazioni sui compiti specifici.
  4. Valutazione: Valutare il modello fine-tuning utilizzando metriche qualitative e quantitative.

Concetti e Tecniche

Fine-tuning Large Language Models

Fine-tuning Large Language Models

Full Fine-Tuning

Full fine-tuning aggiorna tutti i parametri del modello, rendendolo specifico per il nuovo compito. Questo metodo richiede risorse computazionali significative e può essere poco pratico per modelli molto grandi.

Parameter-Efficient Fine-Tuning (PEFT)

PEFT aggiorna solo una sottinsieme dei parametri del modello, riducendo i requisiti di memoria e i costi computazionali. Questa tecnica previene la dimenticanza catastrofica e mantiene la conoscenza generale del modello.

Low-Rank Adaptation (LoRA) e Quantized LoRA (QLoRA)

LoRA fine-tuning solo alcune matrici di basso rango, mentre QLoRA quantizza queste matrici per ridurre ulteriormente l’impronta di memoria.

Metodi di Fine-Tuning

  1. Full Fine-Tuning: Questo comporta l’addestramento di tutti i parametri del modello sul dataset specifico del compito. Sebbene questo metodo possa essere molto efficace, è anche computazionalmente costoso e richiede una grande quantità di memoria.
  2. Parameter Efficient Fine-Tuning (PEFT): PEFT aggiorna solo una sottinsieme dei parametri del modello, rendendolo più efficiente in termini di memoria. Tecniche come Low-Rank Adaptation (LoRA) e Quantized LoRA (QLoRA) rientrano in questa categoria.

Cosa è LoRA?

Comparing finetuning methods: QLORA enhances LoRA with 4-bit precision quantization and paged optimizers for memory spike management

Comparing finetuning methods: QLORA enhances LoRA with 4-bit precision quantization and paged optimizers for memory spike management

LoRA è un metodo di fine-tuning migliorato in cui, invece di fine-tuning tutti i pesi del modello pre-addestrato, due matrici più piccole che approssimano la matrice più grande vengono fine-tuning. Queste matrici costituiscono l’adattatore LoRA. Questo adattatore fine-tuning viene quindi caricato nel modello pre-addestrato e utilizzato per l’inferenza.

Principali Vantaggi di LoRA:

  • Efficienza della Memoria: LoRA riduce l’impronta di memoria fine-tuning solo le piccole matrici invece dell’intero modello.
  • Riutilizzabilità: Il modello originale rimane invariato e possono essere utilizzati più adattatori LoRA con esso, facilitando la gestione di più compiti con requisiti di memoria inferiori.

Cosa è Quantized LoRA (QLoRA)?

QLoRA porta LoRA un passo avanti quantizzando i pesi degli adattatori LoRA a precisione inferiore (ad esempio, 4-bit invece di 8-bit). Ciò riduce ulteriormente l’utilizzo della memoria e i requisiti di archiviazione mentre mantiene un livello di efficacia paragonabile.

Principali Vantaggi di QLoRA:

  • Maggior Efficienza della Memoria: Quantizzando i pesi, QLoRA riduce significativamente i requisiti di memoria e archiviazione del modello.
  • Mantiene le Prestazioni: Nonostante la precisione ridotta, QLoRA mantiene livelli di prestazione vicini a quelli dei modelli a precisione completa.

Adattamento Specifico del Compito

Durante il fine-tuning, i parametri del modello vengono regolati in base al nuovo dataset, aiutandolo a comprendere e generare contenuti pertinenti al compito specifico. Questo processo mantiene la conoscenza linguistica generale acquisita durante il pre-addestramento mentre adatta il modello alle sfumature del dominio di destinazione.

Fine-Tuning nella Pratica

Full Fine-Tuning vs. PEFT

  • Full Fine-Tuning: Comprende l’addestramento dell’intero modello, che può essere computazionalmente costoso e richiede una grande quantità di memoria.
  • PEFT (LoRA e QLoRA): Fine-tuning solo una sottinsieme dei parametri, riducendo i requisiti di memoria e prevenendo la dimenticanza catastrofica, rendendolo un’alternativa più efficiente.

Passaggi di Implementazione

  1. Configurazione dell’Ambiente: Installare le librerie necessarie e configurare l’ambiente di calcolo.
  2. Caricamento e Pre-elaborazione del Dataset: Caricare il dataset e pre-elaborarlo in un formato adatto al modello.
  3. Caricamento del Modello Pre-addestrato: Caricare il modello base con configurazioni di quantizzazione se si utilizza QLoRA.
  4. Tokenizzazione: Tokenizzare il dataset per prepararlo all’addestramento.
  5. Addestramento: Fine-tuning del modello utilizzando il dataset preparato.
  6. Valutazione: Valutare le prestazioni del modello su compiti specifici utilizzando metriche qualitative e quantitative.

Guida Passo dopo Passo per Fine-Tuning LLM

Configurazione dell’Ambiente

Utilizzeremo un notebook Jupyter per questo tutorial. Piattaforme come Kaggle, che offrono utilizzo gratuito di GPU, o Google Colab sono ideali per eseguire questi esperimenti.

1. Installazione delle Librerie Richieste

Assicurarsi di avere le librerie necessarie installate:

!pip install -qqq -U bitsandbytes transformers peft accelerate datasets scipy einops evaluate trl rouge_score

2. Importazione delle Librerie e Configurazione dell’Ambiente

import os
import torch
from datasets import load_dataset
from transformers import (
AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig, TrainingArguments,
pipeline, HfArgumentParser
)
from trl import ORPOConfig, ORPOTrainer, setup_chat_format, SFTTrainer
from tqdm import tqdm
import gc
import pandas as pd
import numpy as np
from huggingface_hub import interpreter_login

# Disabilitare la registrazione di Weights and Biases
os.environ['WANDB_DISABLED'] = "true"
interpreter_login()

3. Caricamento del Dataset

Utilizzeremo il dataset DialogSum per questo tutorial:

dataset_name = "neil-code/dialogsum-test"
dataset = load_dataset(dataset_name)

4. Creazione della Configurazione BitsAndBytes

Per caricare il modello in formato 4-bit:

compute_dtype = getattr(torch, "float16")
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type='nf4',
bnb_4bit_compute_dtype=compute_dtype,
bnb_4bit_use_double_quant=False,
)

5. Caricamento del Modello Pre-addestrato

Utilizzando il modello Phi-2 di Microsoft (MSFT ) per questo tutorial:

model_name = 'microsoft/phi-2'
device_map = {"": 0}
original_model = AutoModelForCausalLM.from_pretrained(
model_name,
device_map=device_map,
quantization_config=bnb_config,
trust_remote_code=True,
use_auth_token=True
)

6. Tokenizzazione

Configurazione del tokenizzatore:

tokenizer = AutoTokenizer.from_pretrained(
model_name,
trust_remote_code=True,
padding_side="left",
add_eos_token=True,
add_bos_token=True,
use_fast=False
)
tokenizer.pad_token = tokenizer.eos_token

Fine-Tuning Llama 3 o Altri Modelli

Quando si esegue il fine-tuning di modelli come Llama 3 o altri modelli open-source all’avanguardia, ci sono considerazioni e regolazioni specifiche richieste per garantire prestazioni ottimali. Ecco i passaggi dettagliati e le informazioni su come affrontare questo per diversi modelli, inclusi Llama 3, GPT-3 e Mistral.

5.1 Utilizzo di Llama 3

Selezione del Modello:

  • Assicurarsi di avere l’identificatore del modello corretto dal hub dei modelli Hugging Face. Ad esempio, il modello Llama 3 potrebbe essere identificato come meta-llama/Meta-Llama-3-8B su Hugging Face.
  • Assicurarsi di richiedere l’accesso e accedere al proprio account Hugging Face se necessario per modelli come Llama 3.

Tokenizzazione:

  • Utilizzare il tokenizzatore appropriato per Llama 3, assicurandosi che sia compatibile con il modello e supporti le funzionalità richieste come padding e token speciali.

Memoria e Calcolo:

  • Il fine-tuning di grandi modelli come Llama 3 richiede risorse computazionali significative. Assicurarsi che l’ambiente, come una configurazione GPU potente, possa gestire i requisiti di memoria e calcolo. Assicurarsi che l’ambiente possa gestire i requisiti di memoria, che possono essere mitigati utilizzando tecniche come QLoRA per ridurre l’impronta di memoria.

Esempio:

model_name = 'meta-llama/Meta-Llama-3-8B'
device_map = {"": 0}
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.float16,
bnb_4bit_use_double_quant=True,
)
original_model = AutoModelForCausalLM.from_pretrained(
model_name,
device_map=device_map,
quantization_config=bnb_config,
trust_remote_code=True,
use_auth_token=True
)

5.2 Utilizzo di Altri Modelli Popolari (ad esempio GPT-3, Mistral)

Selezione del Modello:

  • Per modelli come GPT-3 e Mistral, assicurarsi di utilizzare il nome del modello corretto e l’identificatore dal hub dei modelli Hugging Face o da altre fonti.

Tokenizzazione:

  • Simile a Llama 3, assicurarsi che il tokenizzatore sia configurato correttamente e compatibile con il modello.

Memoria e Calcolo:

  • Ogni modello può avere requisiti di memoria diversi. Regolare l’ambiente di conseguenza.

Esempio per GPT-3:

model_name = 'openai/gpt-3'
device_map = {"": 0}
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.float16,
bnb_4bit_use_double_quant=True,
)
original_model = AutoModelForCausalLM.from_pretrained(
model_name,
device_map=device_map,
quantization_config=bnb_config,
trust_remote_code=True,
use_auth_token=True
)

7. Test del Modello con Inferenza Zero-Shot

Valutare il modello base con un input di esempio:

from transformers import set_seed

set_seed(42)
index = 10
prompt = dataset['test'][index]['dialogue']
formatted_prompt = f"Instruct: Summarize the following conversation.\n{prompt}\nOutput:\n"

# Genera output
def gen(model, prompt, max_length):
inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
outputs = model.generate(**inputs, max_length=max_length)
return tokenizer.batch_decode(outputs, skip_special_tokens=True)

res = gen(original_model, formatted_prompt, 100)
output = res[0].split('Output:\n')[1]

print(f'INPUT PROMPT:\n{formatted_prompt}')
print(f'MODEL GENERATION - ZERO SHOT:\n{output}')

8. Pre-elaborazione del Dataset

Convertire le coppie di dialogo-riassunto in prompt:

def create_prompt_formats(sample):
blurb = "Below is an instruction that describes a task. Write a response that appropriately completes the request."
instruction = "### Instruct: Summarize the below conversation."
input_context = sample['dialogue']
response = f"### Output:\n{sample['summary']}"
end = "### End"

parts = [blurb, instruction, input_context, response, end]
formatted_prompt = "\n\n".join(parts)
sample["text"] = formatted_prompt
return sample

dataset = dataset.map(create_prompt_formats)

Tokenizzare il dataset formattato:

def preprocess_batch(batch, tokenizer, max_length):
return tokenizer(batch["text"], max_length=max_length, truncation=True)

max_length = 1024
train_dataset = dataset["train"].map(lambda batch: preprocess_batch(batch, tokenizer, max_length), batched=True)
eval_dataset = dataset["validation"].map(lambda batch: preprocess_batch(batch, tokenizer, max_length), batched=True)

Iperparametri e il loro Impatto

Gli iperparametri giocano un ruolo cruciale nell’ottimizzazione delle prestazioni del modello. Ecco alcuni iperparametri chiave da considerare:

  1. Tasso di Apprendimento: Controlla la velocità con cui il modello aggiorna i suoi parametri. Un tasso di apprendimento alto potrebbe portare a una convergenza più rapida, ma potrebbe superare la soluzione ottimale. Un tasso di apprendimento basso garantisce una convergenza stabile, ma potrebbe richiedere più epoche.
  2. Dimensione del Batch: Il numero di campioni elaborati prima che il modello aggiorni i suoi parametri. Dimensioni del batch più grandi possono migliorare la stabilità, ma richiedono più memoria. Dimensioni del batch più piccole potrebbero portare a più rumore nel processo di addestramento.
  3. Passi di Accumulo del Gradiente: Questo parametro aiuta a simulare dimensioni del batch più grandi accumulando i gradienti su più passi prima di eseguire un aggiornamento dei parametri.
  4. Numero di Epoche: Il numero di volte che l’intero dataset viene passato attraverso il modello. Più epoche possono migliorare le prestazioni, ma potrebbero portare a sovrapprendimento se non gestite correttamente.
  5. Decadimento del Peso: Tecnica di regolarizzazione per prevenire il sovrapprendimento penalizzando i pesi grandi.
  6. Pianificatore del Tasso di Apprendimento: Regola il tasso di apprendimento durante l’addestramento per migliorare le prestazioni e la convergenza.

Personalizzare la configurazione di addestramento regolando gli iperparametri come il tasso di apprendimento, la dimensione del batch e i passi di accumulo del gradiente in base alle specifiche esigenze del modello e del compito. Ad esempio, i modelli Llama 3 potrebbero richiedere tassi di apprendimento diversi rispetto ai modelli più piccoli.

Esempio di Configurazione di Addestramento

orpo_args = ORPOConfig(
learning_rate=8e-6,
lr_scheduler_type="linear",
max_length=1024,
max_prompt_length=512,
beta=0.1,
per_device_train_batch_size=2,
per_device_eval_batch_size=2,
gradient_accumulation_steps=4,
optim="paged_adamw_8bit",
num_train_epochs=1,
evaluation_strategy="steps",
eval_steps=0.2,
logging_steps=1,
warmup_steps=10,
report_to="wandb",
output_dir="./results/",
)

10. Addestramento del Modello

Configurare l’addestratore e iniziare l’addestramento:

trainer = ORPOTrainer(
model=original_model,
args=orpo_args,
train_dataset=train_dataset,
eval_dataset=eval_dataset,
tokenizer=tokenizer,
)
trainer.train()
trainer.save_model("fine-tuned-llama-3")

Valutazione del Modello Fine-Tuning

Dopo l’addestramento, valutare le prestazioni del modello utilizzando sia metodi qualitativi che quantitativi.

1. Valutazione Umana

Confrontare le somme generate con quelle scritte dagli esseri umani per valutare la qualità.

2. Valutazione Quantitativa

Utilizzare metriche come ROUGE per valutare le prestazioni:

from rouge_score import rouge_scorer

scorer = rouge_scorer.RougeScorer(['rouge1', 'rouge2', 'rougeL'], use_stemmer=True)
scores = scorer.score(reference_summary, generated_summary)
print(scores)

Sfide Comuni e Soluzioni

1. Limitazioni di Memoria

Utilizzare QLoRA aiuta a mitigare i problemi di memoria quantizzando i pesi del modello a 4-bit. Assicurarsi di avere abbastanza memoria GPU per gestire la dimensione del batch e la dimensione del modello.

2. Sovrapprendimento

Monitorare le metriche di valutazione per prevenire il sovrapprendimento. Utilizzare tecniche come l’arresto anticipato e il decadimento del peso.

3. Addestramento Lento

Ottimizzare la velocità di addestramento regolando la dimensione del batch, il tasso di apprendimento e utilizzando l’accumulo del gradiente.

4. Qualità dei Dati

Assicurarsi che il dataset sia pulito e ben pre-elaborato. Una cattiva qualità dei dati può avere un impatto significativo sulle prestazioni del modello.

Conclusione

Il fine-tuning dei modelli linguistici grandi utilizzando QLoRA è un modo efficiente per adattare grandi modelli pre-addestrati a compiti specifici con costi computazionali ridotti. Seguendo questa guida, è possibile fine-tuning PHI, Llama 3 o qualsiasi altro modello open-source per ottenere prestazioni elevate sui propri compiti specifici.

Ho trascorso gli ultimi cinque anni immergendomi nel mondo affascinante del Machine Learning e del Deep Learning. La mia passione e la mia esperienza mi hanno portato a contribuire a oltre 50 progetti di ingegneria del software diversi, con un focus particolare su AI/ML. La mia curiosità in corso mi ha anche portato verso l'elaborazione del linguaggio naturale, un campo che sono ansioso di esplorare ulteriormente.