Negli ultimi due anni ho lavorato principalmente con large language models, occupandomi di training, fine-tuning, prompting e così via, poiché era molto richiesto dal mercato e dagli utenti. Ma credo che gli LLM che lavorano principalmente con il testo siano solo l’inizio della GenAI. A un certo punto, tutti vorranno un’AI fisica, in cui i modelli possano vedere, sentire, percepire e ragionare in modo più concreto e umano.
Quindi iniziamo con la multimodalità. In questo notebook introduco LLaVA, un’architettura in grado di interpretare sia immagini che testo per generare risposte multimodali.
In questo tutorial utilizzeremo componenti più leggeri, adatti a far girare il notebook in un ambiente gratuito come Google Colab.
Advertising
I componenti che utilizzeremo sono:
1️⃣ CLIP-ViT B/32 come image encoder 2️⃣ TinyLlama-1.1B come language model 3️⃣ Un MLP adapter a 2 layer per collegare i due modelli
model = LlavaForConditionalGeneration(llava_config).cuda()
model
E’ ora di fare qualche modifica interna al nostro modello
In precedenza abbiamo detto che è possibile costruire un modello LLaVA partendo da un image encoder pre-addestrato e un LLM pre-addestrato. Facciamolo davvero!
Il modello originale di LLaVA è inizializzato a partire da un CLIP-ViT L/14 e un Vicuna v1.5 7B. Per rendere il tutto più gestibile con le risorse offerte dal piano gratuito di Google Colab, utilizzeremo invece un CLIP-ViT B/16 e un TinyLlama 1.1B.
L’unico componente che addestreremo sarà un MLP adapter a 2 layer che collega i due modelli.
def count_parameters(model, trainable_only=False):
return sum(
p.numel()
for p in model.parameters()
if not trainable_only or p.requires_grad
)
print(f"Total parameters: {count_parameters(model)}")
print(f"Trainable parameters: {count_parameters(model, trainable_only=True)}")
Qui sotto è mostrato il formato che useremo per interagire con il nostro modello LLaVA.
La prima parte è il cosiddetto system prompt, che contiene linee guida generali su come il modello dovrebbe rispondere all’utente.
La seconda parte è un Jinja template (fondamentalmente codice) che determina come viene resa la conversazione a partire da un input strutturato (vedi esempio sotto).
LLAVA_CHAT_TEMPLATE = (
"A chat between a curious user and an artificial intelligence assistant. The assistant gives helpful, detailed, and polite answers to the user's questions. "
"{% for message in messages %}{% if message['role'] == 'user' %}USER: {% else %}ASSISTANT: {% endif %}{% for item in message['content'] %}{% if item['type'] == 'text' %}{{ item['text'] }}{% elif item['type'] == 'image' %}<image>{% endif %}{% endfor %}{% if message['role'] == 'user' %} {% else %}{{eos_token}}{% endif %}{% endfor %}"
)
tokenizer.chat_template = LLAVA_CHAT_TEMPLATE
sample_messages = [
{
"content": [
{
"index": 0,
"text": None,
"type": "image"
},
{
"index": None,
"text": "\nWhat potential activities might be popular at this location?",
"type": "text"
}
],
"role": "user"
},
{
"content": [
{
"index": None,
"text": (
"At this location, with a sandy path leading to the ocean where multiple boats, including "
"sailboats, are moored, popular activities might include boating, sailing, swimming, and "
"beachcombing. Additionally, the sandy path and shoreline provide an ideal setting for leisurely "
"strolls and picnics, while the ocean view offers a serene environment for relaxation and "
"photography. Depending on the specific area and available facilities, other water sports such as "
"kayaking, paddleboarding, and snorkeling could also be prevalent."
),
"type": "text"
}
],
"role": "assistant"
}
]
def get_data_collator(processor, ignore_index):
def collate_examples(examples):
# Extract texts and images from the raw examples
texts = []
images = []
for example in examples:
messages = example["messages"]
text = processor.tokenizer.apply_chat_template(
messages, tokenize=False, add_generation_prompt=False
)
texts.append(text)
images.append(example["images"][0])
# Process the inputs (tokenize text and transform images)
batch = processor(texts, images, return_tensors="pt", padding=True)
# Create labels
labels = batch["input_ids"].clone()
if processor.tokenizer.pad_token_id is not None:
labels[labels == processor.tokenizer.pad_token_id] = ignore_index
batch["labels"] = labels
return batch
return collate_examples
# NOTE: this does a bit more than a collate function should...
Training
args = Seq2SeqTrainingArguments(
output_dir="/content/training_output",
per_device_train_batch_size=2,
gradient_accumulation_steps=4,
learning_rate=2e-4,
max_steps=350,
lr_scheduler_type="cosine_with_min_lr",
lr_scheduler_kwargs={"min_lr": 2e-5},
warmup_ratio=0.05,
logging_strategy="steps",
logging_steps=5,
fp16=True,
remove_unused_columns=False, # Important!
optim="adamw_torch",
report_to="none",
save_strategy="no", # let's not save the checkpoint to disk, otherwise it'll take 5 mins
)
trainer = Seq2SeqTrainer(
model=model,
args=args,
data_collator=get_data_collator(
processor, ignore_index=model.config.ignore_index,
),
train_dataset=train_dataset,
)
trainer.train()
Inferenza
È importante notare che, per garantire che l’inferenza funzioni come previsto, bisognerebbe utilizzare modelli più pesanti e addestrare per un periodo di tempo più lungo.
Useremo questa immagine per l’inferenza:
conversation = [
{
"content": [
{
"type": "image"
},
{
"text": "\nWhat is represented in the image?",
"type": "text"
}
],
"role": "user"
}
]
Utilizza un image encoder più grande (es. CLIP-ViT Large) e un LLM più potente (es. Llama 3.1 8B)
Allena il modello più a lungo. Serve tempo affinché il modello impari a seguire le istruzioni in presenza di image features
Segui la procedura di addestramento multi-stadio adottata dal LLaVA originale:
Stage 1: Pre-training for Feature Alignment → addestra il modello su dati di istruzioni a singola interazione, dove viene chiesto di descrivere brevemente l’immagine. Image encoder e LLM sono congelati ❄️
Stage 2: Fine-tuning End-to-End → addestra il modello su dati di istruzioni multi-turno. Solo l’image encoder rimane congelato ❄️
Penso che questo piccolo progetto sia interessante per capire meglio come funzionano i modelli multimodali come LLaVA. Anche se abbiamo utilizzato modelli più piccoli, l’idea principale rimane la stessa: combinare visione e linguaggio in un unico sistema capace di comprendere le immagini e parlarne.
Ovviamente, i risultati ottenuti in questo toy example non sono particolarmente buoni, c’è molto margine di miglioramento. Ma far funzionare LLaVA in un ambiente con risorse limitate è già di per sé una bella sfida.
📢 Resta aggiornatoTi è piaciuto questo articolo? Rimani sempre informato seguendoci su Google Discover (scorri in basso e clicca segui) e su 🔔 Google News. Ne stiamo anche discutendo sui nostri social: 💼 LinkedIn, 📘 Facebook e 📸 Instagram. Hai una notizia o un approfondimento da segnalarci? ✉️ Scrivici
Esperto di intelligenza artificiale con una grande passione per l'esplorazione spaziale. Ho avuto la fortuna di lavorare presso l'Agenzia Spaziale Europea, contribuendo a progetti di ottimizzazione del flusso di dati e di architettura del software. Attualmente, sono AI Scientist & Coach presso la PiSchool, dove mi dedico alla prototipazione rapida di prodotti basati sull'intelligenza artificiale. Mi piace scrivere articoli riguardo la data science e recentemente sono stato riconosciuto come uno dei blogger più prolifici su Towards Data Science.
Aree di competenza:Intelligenza artificiale, AI decentralizzata su blockchain, Smart contract e protocolli ERC-8004, Sistemi multi-agente, Sicurezza e Defensive AI, Inference decentralizzata verificabile, Blockchain engineering e integrazione AI
Dopo il successo delle scorse edizioni, Red Hot Cyber è lieta di annunciare una nuova live-class del corso "Dark Web & Cyber Threat Intelligence". A differenza dei corsi e-learning pre-registrati, queste lezioni online in tempo reale, condotte dal professor Pietro Melillo, offrono un’esperienza formativa interattiva e coinvolgente, ideale per approfondire i contenuti e affrontare casi pratici.
Le Live Class sono progettate per garantire un apprendimento mirato e personalizzato, con un massimo di 14 partecipanti per sessione. Questo consente di adattare il percorso formativo alle esigenze specifiche, ma anche di mantenere alta la qualità: i posti sono limitati e nelle scorse edizioni sono andati in sold-out due settimane prima dell’inizio. Prenota subito per assicurarti il tuo posto!
Docente: Pietro Melillo, PhD presso l’Università del Sannio e docente presso IUSI University
Livello: Intermedio
Durata: 15 ore in Live Class con docente dal vivo
Prerequisiti: Navigazione Internet e conoscenze base di sicurezza informatica
Certificazione : Cyber Threat Intelligence Professional (CTIP) previo superamento dell’esame finale
Opportunità post-corso: Accesso al laboratorio operativo DarkLab per attività pratiche di intelligence
Al termine del corso, potrai accedere all’esclusivo Laboratorio di Intelligence DarkLab, un ambiente operativo dove mettere in pratica le competenze acquisite. Sarà l’occasione per sperimentare attività di investigazione nel Dark Web, analisi delle minacce e redazione di report di intelligence e ricerche approfondite.