Usare i processi markoviani
Andrej Andreevič Markov è stato un matematico russo noto principalmente per la modellazione dei processi markoviani, in cui si pongono una serie finita di possibili stati ed una probabilità di transazione da ognuno a qualsiasi altro. Nello specifico il sistema in questione non ha memoria, nel senso che le transazioni avvengono in modo casuale e non tengono conto dell’evoluzione globale del sistema, ma soltanto delle singole transazioni. I processi Markoviani nella pratica possono essere usati per modellare sequenze di eventi in cui la probabilità di ciascun evento dipende esclusivamente dallo stato precedente.
Come si usa un processo markoviano nella pratica? Sembra una cosa avulsa dalla realtà ma non è chiaramente così, a pensarci un attimo. Se ad esempio volessimo creare un bot che utilizza catene di Markov per generare saluti sempre diversi ad ogni utente che si connette, possiamo rappresentare ogni stato come un tipo di saluto e transizioni tra gli stati con probabilità associate. Il codice per creare il grafo, per inciso, è disponibile su Github.
Tale bot – una volta connesso a noi utenti – andrebbe ad esplorare casualmente un “grafo dei saluti”, ovvero un insieme di stati (i “pallini” del grafico) mediante una griglia (o matrice) di funzioni di probabilità di transazione. In questo modo esibirebbe una dose di “umanità” che si esplica nell’emulazione di un comportamento tipicamente umano, ovvero che quando salutiamo qualcuno non usiamo un algoritmo deterministico o dei passi pre-impostati come A, B, C, D…, ma salutiamo semplicemente “come ci viene” di farlo. L’intuizione di Markov di metà Ottocento è fondamentale perchè darà il via a tutto ciò che vedremo in seguito, e che culminerà con lo sviluppo di ChatGPT e degli LLM (Large Language Models).
![Di Andrea444460 - Opera propria, CC0, https://commons.wikimedia.org/w/index.php?curid=46404362](https://lipercubo.it/wp-content/uploads/2024/07/Andrej_Markov-282x300.jpg)
Ecco un esempio di come possiamo implementare questo in linguaggio Python, includendo un grafo animato che mostra la transizione tra i saluti:
- Creiamo la catena di Markov:
- Definiamo gli stati (i saluti:).
- Definiamo le probabilità di transizione tra gli stati.
- Generiamo i saluti:
- Utilizziamo le probabilità di transizione per determinare il prossimo saluto.
- Visualizziamo il processo:
- Utilizziamo
networkx
ematplotlib
per creare e animare il grafo che rappresenta la catena di Markov.
- Utilizziamo
Il concetto chiave è ovviamente quello di matrice di transizione degli stati, la nostra “mappa” che permette di stabilire la probabilità di passare da uno stato a qualsiasi altro. In forma Python si tratta di un dizionario:
transitions = { |
“salve”: {“ciao”: 0.3, “buongiorno”: 0.3, “buonasera”: 0.2, “hey”: 0.2}, |
“ciao”: {“salve”: 0.2, “buongiorno”: 0.3, “buonasera”: 0.2, “hey”: 0.3}, |
“buongiorno”: {“salve”: 0.25, “ciao”: 0.25, “buonasera”: 0.25, “hey”: 0.25}, |
“buonasera”: {“salve”: 0.3, “ciao”: 0.3, “buongiorno”: 0.2, “hey”: 0.2}, |
“hey”: {“salve”: 0.25, “ciao”: 0.25, “buongiorno”: 0.25, “buonasera”: 0.25} |
}
ma potremmo anche riscriverla come tabella, in cui righe e colonne rappresentano tutti gli stati possibili, quindi una tabella in questo caso 5×5.
Come si è evoluta l’idea negli anni
Il passaggio teorico dai processi di Markov ai modelli di linguaggio di grandi dimensioni (LLM) che generano linguaggio parlato in modo realistico coinvolge diversi stadi di sviluppo e concetti chiave.Le catene di Marco trasmettono di scrivere un testo eventualmente realistico che però è totalmente non deterministico, perché si basa su un modello probabilistico puro e soprattutto perché non esiste il concetto di memoria, quindi l’algoritmo (in termini informatici) non “ricorderà” ciò che ha detto e questo fornirà alla lunga la sensazione all’utente di stare parlando con qualcuno che tira fuori parole letteralmente a caso.
In prima istanza sono stati introdotti gli N-grammi, (per semplificare) insieme di parole che possono formare potenziali frasi, ed in cui le frasi di senso compiuto hanno probabilità più alta delle altre. Essi sono stati sfruttati anche da Google per costruire corpus di testo per consentire, ad esempio, il completamento delle frasi che iniziamo a scrivere, e per “prevedere” cosa voglia l’utente che faccia una ricerca su Google. In un modello bigramma (2-gram), ad esempio, la frase “io vado” può essere seguita da “a casa” con una certa probabilità e da “a scuola” con un’altra probabilità. La predizione della prossima parola dipende dalle due parole precedenti, e in questo caso c’è un concetto di “memoria” che è stato introdotto nel sistema.
Con l’uso dei modelli di linguaggio basati su probabilità, in seguito, si è continuato a calcolare la probabilità (una grandezza decimale che va da 0 a 1, oppure più comunemenete da 0% a 100%) di vari corpus di testo. ad esempio potremmo calcolare che la sequenza “buona giornata” appare con una frequenza di 0.50 e “buona serata” con una frequenza di 0.50, proprio per il fatto che per 12 ore al giorno usiamo una espressione e per le altre 12 ne usiamo un’altra.
L’evoluzione successiva è stata l’introduzione delle reti neurali, in vari tipi di implementazioni, le quali sono in grado di mantenere informazioni su sequenze più lunghe e gestirle al meglio. Il passo decisivo verso gli LLM è stata l’introduzione dei modelli Transformer, come il modello BERT (Bidirectional Encoder Representations from Transformers) e GPT (Generative Pre-trained Transformer). I Transformer utilizzano il meccanismo di attenzione, che permette di pesare l’importanza di diverse parti della sequenza di input e di gestirle in modo efficace.
Gli LLM come GPT-3 sono pre-addestrati su enormi dataset di testo, utilizzando una quantità significativa di dati per apprendere le strutture e i modelli linguistici. Successivamente, questi modelli possono essere affinati (fine-tuning) su compiti specifici utilizzando dataset più piccoli ma rilevanti per il compito.
Grazie alla capacità di apprendere rappresentazioni complesse e contestuali del linguaggio, gli LLM sono in grado di generare testo che è contestualmente appropriato e grammaticalmente corretto, rendendo la generazione di linguaggio parlato più realistica. La combinazione di pre-training su larga scala, meccanismi di attenzione e architetture di rete neurale avanzate permette a questi modelli di superare significativamente i modelli basati su Markov e N-gram in termini di coerenza e rilevanza del testo generato.
![](https://lipercubo.it/wp-content/uploads/2022/12/vice-vehicle-felon_4.png)
Ingegnere per passione, consulente per necessità; ho creato Lipercubo.it. – Mastodon