Intelligenza artificiale
La Guida Unica di cui Hai Bisogno per Ottimizzare Llama 3 o Altri Modelli Open Source
L’ottimizzazione di grandi modelli linguistici (LLM) come Llama 3 comporta l’adattamento di un modello pre-addestrato a compiti specifici utilizzando un set di dati specifico del dominio. Questo processo sfrutta le conoscenze pre-esistenti del modello, rendendolo efficiente e conveniente rispetto all’addestramento da zero. In questa guida, percorreremo i passaggi per ottimizzare Llama 3 utilizzando QLoRA (Quantized LoRA), un metodo efficiente per i parametri che minimizza l’utilizzo della memoria e i costi computazionali.
Panoramica dell’Ottimizzazione
L’ottimizzazione comporta diversi passaggi chiave:
- Selezione di un Modello Pre-addestrato: Scegli un modello di base che si allinei con l’architettura desiderata.
- Raccolta di un Set di Dati Rilevante: Raccogli e pre-elabora un set di dati specifico per il compito.
- Ottimizzazione: Adatta il modello utilizzando il set di dati per migliorare le sue prestazioni su compiti specifici.
- Valutazione: Valuta le prestazioni del modello ottimizzato utilizzando metriche qualitative e quantitative.
Concetti e Tecniche
Ottimizzazione Completa
Ottimizzazione completa aggiorna tutti i parametri del modello, rendendolo specifico per il nuovo compito. Questo metodo richiede risorse computazionali significative e spesso è impraticabile per modelli molto grandi.
Ottimizzazione Efficientemente Parametrizzata (PEFT)
PEFT aggiorna solo un subset dei parametri del modello, riducendo i requisiti di memoria e costo computazionale. Questa tecnica previene la dimenticanza catastrofica e mantiene la conoscenza generale del modello.
Adattamento di Basso Rango (LoRA) e Quantized LoRA (QLoRA)
LoRA ottimizza solo poche matrici di basso rango, mentre QLoRA quantizza queste matrici per ridurre ulteriormente l’impronta di memoria.
Metodi di Ottimizzazione
- Ottimizzazione Completa: Comporta l’addestramento di tutti i parametri del modello sul set di dati specifico del compito. Sebbene questo metodo possa essere molto efficace, è anche computazionalmente costoso e richiede una grande quantità di memoria.
- Ottimizzazione Efficientemente Parametrizzata (PEFT): PEFT aggiorna solo un subset dei parametri del modello, rendendolo più efficiente in termini di memoria. Tecniche come LoRA e QLoRA rientrano in questa categoria.
Cosa è LoRA?

Confronto tra metodi di ottimizzazione: QLoRA migliora LoRA con quantizzazione a 4 bit e ottimizzatori paginati per la gestione dei picchi di memoria
LoRA è un metodo di ottimizzazione migliorato in cui, invece di ottimizzare tutti i pesi del modello pre-addestrato, due matrici più piccole che approssimano la matrice più grande vengono ottimizzate. Queste matrici costituiscono l’adattatore LoRA. Questo adattatore ottimizzato viene quindi caricato nel modello pre-addestrato e utilizzato per l’inferenza.
Vantaggi Chiave di LoRA:
- Efficienza della Memoria: LoRA riduce l’impronta di memoria ottimizzando solo matrici più piccole invece di tutto il 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 più in là 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, mantenendo allo stesso tempo un livello di efficacia paragonabile.
Vantaggi Chiave di QLoRA:
- Efficienza della Memoria Ancora Maggiore: 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 l’ottimizzazione, i parametri del modello vengono regolati in base al nuovo set di dati, aiutandolo a comprendere e generare contenuti rilevanti per il compito specifico. Questo processo mantiene la conoscenza linguistica generale acquisita durante l’addestramento pre-addestrato, adattando il modello alle sfumature del dominio di destinazione.
Ottimizzazione nella Pratica
Full Fine-Tuning vs. PEFT
- Ottimizzazione Completa: Comporta l’addestramento dell’intero modello, che può essere computazionalmente costoso e richiede una grande quantità di memoria.
- Ottimizzazione Efficientemente Parametrizzata (PEFT): PEFT ottimizza solo un subset dei parametri del modello, riducendo i requisiti di memoria e prevenendo la dimenticanza catastrofica, rendendolo un’alternativa più efficiente.
Passaggi di Implementazione
- Impostazione dell’Ambiente: Installa le librerie necessarie e imposta l’ambiente di calcolo.
- Caricamento e Pre-elaborazione del Set di Dati: Carica il set di dati e pre-elaboralo in un formato adatto al modello.
- Caricamento del Modello Pre-addestrato: Carica il modello di base con le configurazioni di quantizzazione se si utilizza QLoRA.
- Tokenizzazione: Tokenizza il set di dati per prepararlo all’addestramento.
- Addestramento: Ottimizza il modello utilizzando il set di dati preparato.
- Valutazione: Valuta le prestazioni del modello su compiti specifici utilizzando metriche qualitative e quantitative.
Guida Passo dopo Passo per Ottimizzare LLM
Impostazione dell’Ambiente
Useremo 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
Assicurati di avere installate le librerie necessarie:
!pip install -qqq -U bitsandbytes transformers peft accelerate datasets scipy einops evaluate trl rouge_score
2. Importazione delle Librerie e Impostazione 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 # Disabilita il logging di Weights and Biases os.environ['WANDB_DISABLED'] = "true" interpreter_login()
3. Caricamento del Set di Dati
Useremo il set di dati DialogSum per questo tutorial:
Pre-elabora il set di dati secondo le esigenze del modello, compresa l’applicazione di modelli appropriati e l’assicurazione che il formato dei dati sia adatto all’ottimizzazione (Hugging Face) (DataCamp).
dataset_name = "neil-code/dialogsum-test" dataset = load_dataset(dataset_name)
Ispeziona la struttura del set di dati:
print(dataset['test'][0])
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 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
Configura il 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
Ottimizzazione di Llama 3 o Altri Modelli
Quando si ottimizzano modelli come Llama 3 o altri modelli open-source di stato dell’arte, ci sono considerazioni e aggiustamenti specifici richiesti per garantire prestazioni ottimali. Ecco i passaggi dettagliati e approfondimenti su come affrontare questo per diversi modelli, compresi Llama 3, GPT-3 e Mistral.
5.1 Utilizzo di Llama 3
Selezione del Modello:
- Assicurati di avere l’identificatore di modello corretto dall’hub dei modelli Hugging Face. Ad esempio, il modello Llama 3 potrebbe essere identificato come
meta-llama/Meta-Llama-3-8Bsu Hugging Face. - Assicurati di richiedere l’accesso e di accedere al tuo account Hugging Face se richiesto per modelli come Llama 3 (Hugging Face)
Tokenizzazione:
- Utilizza il tokenizzatore appropriato per Llama 3, assicurandoti che sia compatibile con il modello e supporti le funzionalità richieste come padding e token speciali.
Memoria e Calcolo:
- L’ottimizzazione di grandi modelli come Llama 3 richiede risorse computazionali significative. Assicurati che il tuo ambiente, come una potente configurazione GPU, possa gestire i requisiti di memoria e di elaborazione. Assicurati che l’ambiente possa gestire i requisiti di memoria, che possono essere mitigati utilizzando tecniche come QLoRA per ridurre l’impronta di memoria (Hugging Face Forums)
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
)
Tokenizzazione:
A seconda del caso d’uso specifico e dei requisiti del modello, assicurati di configurare correttamente il tokenizzatore senza impostazioni ridondanti. Ad esempio, use_fast=True è consigliato per migliori prestazioni (Hugging Face) (Weights & Biases).
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
5.2 Utilizzo di Altri Modelli Popolari (ad es. GPT-3, Mistral)
Selezione del Modello:
- Per modelli come GPT-3 e Mistral, assicurati di utilizzare il nome e l’identificatore di modello corretti dall’hub dei modelli Hugging Face o da altre fonti.
Tokenizzazione:
- Simile a Llama 3, assicurati che il tokenizzatore sia configurato correttamente e compatibile con il modello.
Memoria e Calcolo:
- Ogni modello può avere requisiti di memoria diversi. Aggiusta la configurazione dell’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
)
Esempio per Mistral:
model_name = 'mistral-7B'
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
)
Considerazioni sulla Tokenizzazione: Ogni modello può avere requisiti di tokenizzazione unici. Assicurati che il tokenizzatore corrisponda al modello e sia configurato correttamente.
Esempio di Tokenizzatore per Llama 3:
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
Esempio di Tokenizzatore per GPT-3 e Mistral:
tokenizer = AutoTokenizer.from_pretrained( model_name, use_fast=True )
7. Test del Modello con Inferenza Zero-Shot
Valuta il modello di 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 Set di Dati
Converte 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)
Tokenizza il set di dati 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)
9. Prepara il modello per QLoRA











