Connect with us

Intelligenza artificiale

La Guida Unica di cui Hai Bisogno per Ottimizzare Llama 3 o Altri Modelli Open Source

mm
FINE TUNING OPEN SOURCE LLM PYTHON GUIDE

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:

  1. Selezione di un Modello Pre-addestrato: Scegli un modello di base che si allinei con l’architettura desiderata.
  2. Raccolta di un Set di Dati Rilevante: Raccogli e pre-elabora un set di dati specifico per il compito.
  3. Ottimizzazione: Adatta il modello utilizzando il set di dati per migliorare le sue prestazioni su compiti specifici.
  4. Valutazione: Valuta le prestazioni del modello ottimizzato utilizzando metriche qualitative e quantitative.

Concetti e Tecniche

Ottimizzazione di Grandi Modelli Linguistici

Ottimizzazione di Grandi Modelli Linguistici

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

  1. 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.
  2. 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

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

  1. Impostazione dell’Ambiente: Installa le librerie necessarie e imposta l’ambiente di calcolo.
  2. Caricamento e Pre-elaborazione del Set di Dati: Carica il set di dati e pre-elaboralo in un formato adatto al modello.
  3. Caricamento del Modello Pre-addestrato: Carica il modello di base con le configurazioni di quantizzazione se si utilizza QLoRA.
  4. Tokenizzazione: Tokenizza il set di dati per prepararlo all’addestramento.
  5. Addestramento: Ottimizza il modello utilizzando il set di dati preparato.
  6. 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-8B su 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

Ho trascorso gli ultimi cinque anni immergendomi nel fascinante mondo 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à continua mi ha anche portato verso l'elaborazione del linguaggio naturale, un campo che sono ansioso di esplorare ulteriormente.