# 1. Tokenizzazione ## Tokenizzazione **Tokenizzazione** è il processo di suddivisione dei dati, come il testo, in pezzi più piccoli e gestibili chiamati _token_. Ogni token viene quindi assegnato a un identificatore numerico unico (ID). Questo è un passaggio fondamentale nella preparazione del testo per l'elaborazione da parte dei modelli di machine learning, specialmente nel natural language processing (NLP). > [!TIP] > L'obiettivo di questa fase iniziale è molto semplice: **Dividere l'input in token (ids) in un modo che abbia senso**. ### **Come Funziona la Tokenizzazione** 1. **Suddivisione del Testo:** - **Tokenizzatore di Base:** Un tokenizzatore semplice potrebbe suddividere il testo in parole e segni di punteggiatura individuali, rimuovendo gli spazi. - _Esempio:_\ Testo: `"Ciao, mondo!"`\ Token: `["Ciao", ",", "mondo", "!"]` 2. **Creazione di un Vocabolario:** - Per convertire i token in ID numerici, viene creato un **vocabolario**. Questo vocabolario elenca tutti i token unici (parole e simboli) e assegna a ciascuno un ID specifico. - **Token Speciali:** Questi sono simboli speciali aggiunti al vocabolario per gestire vari scenari: - `[BOS]` (Inizio Sequenza): Indica l'inizio di un testo. - `[EOS]` (Fine Sequenza): Indica la fine di un testo. - `[PAD]` (Padding): Usato per rendere tutte le sequenze in un batch della stessa lunghezza. - `[UNK]` (Sconosciuto): Rappresenta token che non sono nel vocabolario. - _Esempio:_\ Se `"Ciao"` è assegnato ID `64`, `","` è `455`, `"mondo"` è `78`, e `"!"` è `467`, allora:\ `"Ciao, mondo!"` → `[64, 455, 78, 467]` - **Gestione delle Parole Sconosciute:**\ Se una parola come `"Addio"` non è nel vocabolario, viene sostituita con `[UNK]`.\ `"Addio, mondo!"` → `["[UNK]", ",", "mondo", "!"]` → `[987, 455, 78, 467]`\ _(Assumendo che `[UNK]` abbia ID `987`)_ ### **Metodi di Tokenizzazione Avanzati** Mentre il tokenizzatore di base funziona bene per testi semplici, ha limitazioni, specialmente con vocabolari ampi e nella gestione di parole nuove o rare. I metodi di tokenizzazione avanzati affrontano questi problemi suddividendo il testo in sottounità più piccole o ottimizzando il processo di tokenizzazione. 1. **Byte Pair Encoding (BPE):** - **Scopo:** Riduce la dimensione del vocabolario e gestisce parole rare o sconosciute suddividendole in coppie di byte frequentemente occorrenti. - **Come Funziona:** - Inizia con caratteri individuali come token. - Unisce iterativamente le coppie di token più frequenti in un singolo token. - Continua fino a quando non ci sono più coppie frequenti da unire. - **Vantaggi:** - Elimina la necessità di un token `[UNK]` poiché tutte le parole possono essere rappresentate combinando token di sottoparola esistenti. - Vocabolario più efficiente e flessibile. - _Esempio:_\ `"giocando"` potrebbe essere tokenizzato come `["gioca", "ndo"]` se `"gioca"` e `"ndo"` sono sottoparole frequenti. 2. **WordPiece:** - **Usato Da:** Modelli come BERT. - **Scopo:** Simile a BPE, suddivide le parole in unità di sottoparola per gestire parole sconosciute e ridurre la dimensione del vocabolario. - **Come Funziona:** - Inizia con un vocabolario di base di caratteri individuali. - Aggiunge iterativamente la sottoparola più frequente che massimizza la probabilità dei dati di addestramento. - Utilizza un modello probabilistico per decidere quali sottoparole unire. - **Vantaggi:** - Bilancia tra avere una dimensione del vocabolario gestibile e rappresentare efficacemente le parole. - Gestisce in modo efficiente parole rare e composte. - _Esempio:_\ `"infelicità"` potrebbe essere tokenizzato come `["in", "felicità"]` o `["in", "felice", "tà"]` a seconda del vocabolario. 3. **Unigram Language Model:** - **Usato Da:** Modelli come SentencePiece. - **Scopo:** Utilizza un modello probabilistico per determinare il set di token di sottoparola più probabile. - **Come Funziona:** - Inizia con un ampio set di token potenziali. - Rimuove iterativamente i token che migliorano meno la probabilità del modello sui dati di addestramento. - Finalizza un vocabolario in cui ogni parola è rappresentata dalle unità di sottoparola più probabili. - **Vantaggi:** - Flessibile e può modellare il linguaggio in modo più naturale. - Risultati spesso in tokenizzazioni più efficienti e compatte. - _Esempio:_\ `"internazionalizzazione"` potrebbe essere tokenizzato in sottoparole più piccole e significative come `["internazionale", "izzazione"]`. ## Esempio di Codice Comprendiamo meglio questo attraverso un esempio di codice da [https://github.com/rasbt/LLMs-from-scratch/blob/main/ch02/01_main-chapter-code/ch02.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch02/01_main-chapter-code/ch02.ipynb): ```python # Download a text to pre-train the model import urllib.request url = ("https://raw.githubusercontent.com/rasbt/LLMs-from-scratch/main/ch02/01_main-chapter-code/the-verdict.txt") file_path = "the-verdict.txt" urllib.request.urlretrieve(url, file_path) with open("the-verdict.txt", "r", encoding="utf-8") as f: raw_text = f.read() # Tokenize the code using GPT2 tokenizer version import tiktoken token_ids = tiktoken.get_encoding("gpt2").encode(txt, allowed_special={"[EOS]"}) # Allow the user of the tag "[EOS]" # Print first 50 tokens print(token_ids[:50]) #[40, 367, 2885, 1464, 1807, 3619, 402, 271, 10899, 2138, 257, 7026, 15632, 438, 2016, 257, 922, 5891, 1576, 438, 568, 340, 373, 645, 1049, 5975, 284, 502, 284, 3285, 326, 11, 287, 262, 6001, 286, 465, 13476, 11, 339, 550, 5710, 465, 12036, 11, 6405, 257, 5527, 27075, 11] ``` ## Riferimenti - [https://www.manning.com/books/build-a-large-language-model-from-scratch](https://www.manning.com/books/build-a-large-language-model-from-scratch)