#
Cosa fanno i Transformer?

In questa sezione, vedremo di cosa sono capaci i modelli Transformer e useremo il nostro primo strumento della libreria 🤗 Transformer: la funzione `pipeline()`.

👀 Lo vedi il pulsante Open in Colab in alto a destra? Cliccalo per aprire il blocco note Colab di Google che contiene tutti gli esempi di codice di questa sezione. Ritroverai il pulsante in ogni sezione che contiene esempi di codice.

Se intendi compilare gli esempi localmente, ti consigliamo di dare un occhio alla sezione setup.

##
I Transformer sono ovunque!

I modelli Transformer sono utilizzati per eseguire qualsiasi compito di NLP, come ad esempio quelli menzionati nelle sezioni precedenti. Ecco alcune delle aziende e organizzazioni che utilizzano Hugging Face e i modelli Transformer, e contribuiscono a loro volta alla comunità condividendo i propri modelli:

La libreria 🤗 Transformer fornisce la funzionalità per creare e utilizzare questi modelli condivisi. Il Model Hub contiene migliaia di modelli pre-addestrati che possono essere scaricati e usati liberamente. Puoi anche caricare i tuoi modelli nell’Hub!

⚠️ L'Hugging Face Hub non si limitata ai soli modelli Transformer. Chiunque può condividere qualsiasi tipo di modello o dataset (insieme di dati)! Crea un profilo huggingface.co per approfittare di tutte le funzioni disponibili!

Prima di scoprire come funzionino i modelli Transformer dietro le quinte, vediamo qualche esempio di come questi possano essere utilizzati per risolvere alcuni problemi interessanti di NLP.

##
Lavorare con le pipeline

L’oggetto più basilare della libreria 🤗 Transformer è la funzione `pipeline()`. Questa connette un modello con tutte le fasi necessarie di preprocessing e postprocessing, permettendoci così di fornire un qualsiasi testo come input diretto e ottenere una risposta intelligibile:

    from transformers import pipeline

    classifier = pipeline("sentiment-analysis")
    classifier("I've been waiting for a HuggingFace course my whole life.")

    [{'label': 'POSITIVE', 'score': 0.9598047137260437}]

È anche possibile lavorare su più frasi!

    classifier(
        ["I've been waiting for a HuggingFace course my whole life.", "I hate this so much!"]
    )

    [{'label': 'POSITIVE', 'score': 0.9598047137260437},
     {'label': 'NEGATIVE', 'score': 0.9994558095932007}]

Per default, questa pipeline seleziona un preciso modello pre-addestrato che è stato affinato per il sentiment analysis in inglese. Quando creiamo l’oggetto `classifier`, il modello viene scaricato e memorizzato nella cache. Se inizializziamo di nuovo il comando, verrà utilizzato il modello salvato nella cache e non ci sarà quindi bisogno di scaricare di nuovo il modello.

Tre passaggi principali sono coinvolti quando passiamo del testo in un pipeline:

1. Il testo è pre-elaborato in un formato che il modello può capire.
2. Gli input pre-elaborati vengono passati al modello.
3. Le previsioni del modello sono post-elaborate in un formato accessibile all’utilizzatore.

Tra le pipeline disponibili al momento ci sono:

- `feature-extraction` (per ottenere la rappresentazione vettoriale di un testo)
- `fill-mask`
- `ner` (riconoscimento delle entità nominate, named entity recognition)
- `question-answering`
- `sentiment-analysis`
- `summarization`
- `text-generation`
- `translation`
- `zero-shot-classification`

Proviamo a vederne alcune!

##
Classificazione zero-shot

Cominceremo con l’affrontare un compito impegnativo che consiste nella classificazione di testi non etichettati. Si tratta di uno scenario comune in molti progetti pratici perché l’annotazione testuale richiede tempo e competenza settoriale. In questo caso d’uso, la pipeline `zero-shot-classification` è molto potente e permette di specificare le etichette da utilizzare per la classificazione, in modo da non dover fare affidamento sulle etichette del modello pre-addestrato. Abbiamo già visto come il modello riesca a classificare una frase utilizzando le etichette ‘positiva’ e ‘negativa’, ma è anche possibile classificare testi utilizzando una qualsiasi serie di etichette di nostra scelta.

    from transformers import pipeline

    classifier = pipeline("zero-shot-classification")
    classifier(
        "This is a course about the Transformers library",
        candidate_labels=["education", "politics", "business"],
    )

    {'sequence': 'This is a course about the Transformers library',
     'labels': ['education', 'business', 'politics'],
     'scores': [0.8445963859558105, 0.111976258456707, 0.043427448719739914]}

Questa pipeline si chiama zero-shot perché non hai bisogno di affinare il modello usando i tuoi dati per poterlo utilizzare. È direttamente in grado di generare una previsione probabilistica per qualsiasi lista di etichette tu voglia!

✏️ Provaci anche tu! Divertiti creando sequenze ed etichette e osserva come si comporta il modello.

##
Generazione di testi

Vediamo ora come utilizzare la pipeline per generare testi. L’idea è di fornire un prompt (richiesta) che verrà auto-completato dal modello, il quale genererà il testo mancante. Si tratta di un compito simile alla funzione di scrittura facilitata che troviamo al giorno d’oggi in molti cellulari. La generazione di testi presenta una componente arbitraria, per cui non essere sorpreso/a se non ottieni gli stessi risultati che mostriamo qui sotto.

    from transformers import pipeline

    generator = pipeline("text-generation")
    generator("In this course, we will teach you how to")

    [{'generated_text': 'In this course, we will teach you how to understand and use '
                        'data flow and data interchange when handling user data. We '
                        'will be working with one or more of the most commonly used '
                        'data flows — data flows of various types, as seen by the '
                        'HTTP'}]

Usando l’argomento `num_return_sequences` puoi controllare quante sequenze diverse vengono generate e, con l’argomento `max_length`, la lunghezza totale dell’output testuale.

✏️ Provaci anche tu! Usa gli argomenti `num_return_sequences` e `max_length` per generare due frasi di 15 parole ciascuna.

##
Utilizzo di un qualsiasi modello dell’Hub in una pipeline

Gli esempi precedenti utilizzavano il modello di default per il compito dato, ma puoi anche scegliere un modello particolare dell’Hub da utilizzare in una pipeline per un compito specifico, come ad esempio la generazione testuale. Vai al Model Hub e clicca sull’etichetta corrispondente a destra, in modo da mostrare solo i modelli supportati per il compito in questione. Dovresti ritrovarti in una pagina come questa.

Proviamo il modello `distilgpt2`! Ecco come caricarlo nella pipeline usata in precedenza:

    from transformers import pipeline

    generator = pipeline("text-generation", model="distilgpt2")
    generator(
        "In this course, we will teach you how to",
        max_length=30,
        num_return_sequences=2,
    )

    [{'generated_text': 'In this course, we will teach you how to manipulate the world and '
                        'move your mental and physical capabilities to your advantage.'},
     {'generated_text': 'In this course, we will teach you how to become an expert and '
                        'practice realtime, and with a hands on experience on both real '
                        'time and real'}]

Puoi affinare la ricerca di un modello cliccando sulle etichette corrispondenti alle lingue, e scegliere in seguito un modello che generi testo in un’altra lingua. Il Model Hub contiene anche checkpoint per modelli multilingue che supportano numerose lingue.

Quando avrai selezionato un modello cliccando su di esso, vedrai che esiste un widget che ti permette di provarlo direttamente online. In questo modo, puoi testare velocemente le capacità del modello prima di scaricarlo.

✏️ Provaci anche tu! Usa i filtri per trovare un modello di generazione testuale per un’altra lingua. Sentiti libero/a di divertirti con il widget e usalo in una pipeline!

###
La Inference API

Tutti i modelli possono essere testati direttamente attraverso il tuo browser utilizzando l’Inference API che trovi nel sito di Hugging Face. Puoi divertirti con il modello direttamente in questa pagina, inserendo testo personalizzato e osservando come il modello processi i dati fornitigli.

La Inference API che alimenta il widget è disponibile anche come prodotto a pagamento, il che è comodo se ne hai bisogno per i tuoi flussi di lavoro. Vedi la pagina dei prezzi per maggiori informazioni.

##
Mask filling

La prossima pipeline che proverai è `fill-mask`. L’idea di questo compito è di completare gli spazi bianchi in un dato testo:

    from transformers import pipeline

    unmasker = pipeline("fill-mask")
    unmasker("This course will teach you all about <mask> models.", top_k=2)

    [{'sequence': 'This course will teach you all about mathematical models.',
      'score': 0.19619831442832947,
      'token': 30412,
      'token_str': ' mathematical'},
     {'sequence': 'This course will teach you all about computational models.',
      'score': 0.04052725434303284,
      'token': 38163,
      'token_str': ' computational'}]

L’argomento `top_k` gestisce il numero di possibilità che vuoi mostrare. Nota che qui il modello inserisce la `<mask>` word speciale, la quale viene spesso chiamata mask token. Altri modelli di tipo mask-filling potrebbero avere mask token diversi, quindi è sempre bene verificare quale sia la corretta mask word quando esploriamo nuovi modelli. Un modo per verificarla consiste nel trovare la mask word utilizzata nel widget.

✏️ Provaci anche tu! Cerca il modello `bert-base-cased` nell’Hub e identifica la sua mask word nel widget dell’Inference API. Cosa predice questo modello per la frase nel nostro esempio `pipeline` qui sopra?

##
Riconoscimento delle entità nominate

Il riconoscimento delle entità nominate (Named entity recognition, NER) è un compito in cui il modello deve determinare quali parti dell’input testuale corrispondono a entità quali persone, località, o organizzazioni. Guardiamo a un esempio:

    from transformers import pipeline

    ner = pipeline("ner", grouped_entities=True)
    ner("My name is Sylvain and I work at Hugging Face in Brooklyn.")

    [{'entity_group': 'PER', 'score': 0.99816, 'word': 'Sylvain', 'start': 11, 'end': 18},
     {'entity_group': 'ORG', 'score': 0.97960, 'word': 'Hugging Face', 'start': 33, 'end': 45},
     {'entity_group': 'LOC', 'score': 0.99321, 'word': 'Brooklyn', 'start': 49, 'end': 57}
    ]

Qui il modello ha correttamente identificato che Sylvain è una persona (PER), Hugging Face un’organizzazione (ORG), e Brooklyn una località (LOC).

Passiamo l’opzione `grouped_entities=True` nella funzione di creazione della pipeline per raggruppare le parti frasali che corrispondono alla stessa entità: qui il modello raggruppa correttamente “Hugging” e “Face” come singola organizzazione, nonostante il nome sia formato da più parole. A dire il vero, come vedremo nel prossimo capitolo, il preprocessing divide perfino alcune parole in parti più piccole. Ad esempio, `Sylvain` viene suddiviso in quattro parti: `S`, `##yl`, `##va`, and `##in`. Al momento del post-processing, la pipeline raggruppa le parti con successo.

✏️ Provaci anche tu! Nel Model Hub, cerca un modello capace di effettuare part-of-speech tagging (comunemente abbreviato come POS) in inglese. Cosa predice il modello per la frase nell’esempio qui sopra?

##
Risposta a domande

La pipeline `question-answering` risponde a domande utilizzando informazioni da un contesto prestabilito:

    from transformers import pipeline

    question_answerer = pipeline("question-answering")
    question_answerer(
        question="Where do I work?",
        context="My name is Sylvain and I work at Hugging Face in Brooklyn",
    )

    {'score': 0.6385916471481323, 'start': 33, 'end': 45, 'answer': 'Hugging Face'}

Nota che questa pipeline non genera risposte ma estrae informazioni da un contesto fornito.

##
Riassunto

Quello del riassunto è un compito che trasforma un testo in un testo più breve, conservando tutti (o quasi) gli argomenti più importanti del testo di partenza. Ecco un esempio:

    from transformers import pipeline

    summarizer = pipeline("summarization")
    summarizer(
        """
        America has changed dramatically during recent years. Not only has the number of
        graduates in traditional engineering disciplines such as mechanical, civil,
        electrical, chemical, and aeronautical engineering declined, but in most of
        the premier American universities engineering curricula now concentrate on
        and encourage largely the study of engineering science. As a result, there
        are declining offerings in engineering subjects dealing with infrastructure,
        the environment, and related issues, and greater concentration on high
        technology subjects, largely supporting increasingly complex scientific
        developments. While the latter is important, it should not be at the expense
        of more traditional engineering.

        Rapidly developing economies such as China and India, as well as other
        industrial countries in Europe and Asia, continue to encourage and advance
        the teaching of engineering. Both China and India, respectively, graduate
        six and eight times as many traditional engineers as does the United States.
        Other industrial countries at minimum maintain their output, while America
        suffers an increasingly serious decline in the number of engineering graduates
        and a lack of well-educated engineers.
    """
    )

    [{'summary_text': ' America has changed dramatically during recent years . The '
                      'number of engineering graduates in the U.S. has declined in '
                      'traditional engineering disciplines such as mechanical, civil '
                      ', electrical, chemical, and aeronautical engineering . Rapidly '
                      'developing economies such as China and India, as well as other '
                      'industrial countries in Europe and Asia, continue to encourage '
                      'and advance engineering .'}]

Come nella generazione di testi, puoi specificare un `max_length` o `min_length` per il testo da generare.

##
Traduzione

Per compiti di traduzione, puoi utilizzare un modello di default indicando la coppia linguistica nel nome del compito (come ad esempio `"translation_en_to_fr"`), anche se il metodo più semplice è di scegliere il modello che desideri utilizzare dal Model Hub. Qui in seguito traduciamo dal francese all’inglese:

    from transformers import pipeline

    translator = pipeline("translation", model="Helsinki-NLP/opus-mt-fr-en")
    translator("Ce cours est produit par Hugging Face.")

    [{'translation_text': 'This course is produced by Hugging Face.'}]

Come per le funzioni di generazione testuale e riassunto, è possibile specificare un `max_length` o un `min_length` per il risultato.

✏️ Provaci anche tu! Cerca modelli di traduzione in altre lingue e prova a tradurre la frase precedente in un paio di lingue diverse.

Finora abbiamo mostrato pipeline a solo scopo dimostrativo. Tali pipeline sono state programmate per compiti ben specifici e non sono in grado di eseguire variazioni di questi ultimi. Nel prossimo capitolo, imparerai cosa si nasconde dentro la funzione `pipeline()` e come personalizzarne il comportamento.