Intel e Hugging Face si uniscono per democratizzare l’accelerazione hardware dell’apprendimento automatico

Intel e Hugging Face collaborano per democratizzare l'accelerazione hardware nell'apprendimento automatico.

La missione di Hugging Face è di democratizzare il buon machine learning e massimizzare il suo impatto positivo su settori e società. Non solo ci sforziamo di avanzare modelli Transformer, ma lavoriamo anche duramente per semplificare la loro adozione.

Oggi, siamo entusiasti di annunciare che Intel si è ufficialmente unita al nostro programma di partner hardware. Grazie alla libreria open-source Optimum, Intel e Hugging Face collaboreranno per costruire un’accelerazione hardware all’avanguardia per allenare, ottimizzare e prevedere con i Transformers.

I modelli Transformer sono sempre più grandi e complessi, il che può causare sfide di produzione per applicazioni sensibili alla latenza come la ricerca o i chatbot. Purtroppo, l’ottimizzazione della latenza è da tempo un problema difficile per i praticanti del Machine Learning (ML). Anche con una profonda conoscenza del framework sottostante e della piattaforma hardware, è necessaria molta prova ed errore per capire quali manopole e funzionalità sfruttare.

Intel fornisce una base completa per l’IA accelerata con la piattaforma Intel Xeon Scalable CPU e una vasta gamma di strumenti software, framework e librerie per l’IA ottimizzati per l’hardware. Pertanto, aveva perfettamente senso che Hugging Face e Intel unissero le forze e collaborassero per costruire potenti strumenti di ottimizzazione dei modelli che consentissero agli utenti di ottenere le migliori prestazioni, scalabilità e produttività su piattaforme Intel.

“*Siamo entusiasti di lavorare con Hugging Face per portare le ultime innovazioni dell’hardware Intel Xeon e del software Intel AI alla comunità dei Transformers, attraverso l’integrazione open source e le esperienze di sviluppo integrate*”, afferma Wei Li, Vicepresidente e General Manager di Intel, AI and Analytics.

Negli ultimi mesi, Intel e Hugging Face hanno collaborato per scalare i carichi di lavoro dei Transformer. Abbiamo pubblicato guide dettagliate sull’ottimizzazione e benchmark sull’inferenza (parte 1, parte 2) e raggiunto una latenza a cifre singole millisecondo per DistilBERT sui più recenti processori Intel Xeon Ice Lake. Sul lato dell’allenamento, abbiamo aggiunto il supporto per gli acceleratori Habana Gaudi, che offrono fino al 40% di miglior rapporto prezzo-prestazioni rispetto alle GPU.

Il prossimo passo logico era ampliare questo lavoro e condividerlo con la comunità di ML. Ecco la libreria open source Optimum Intel! Approfondiamola.

Ottieni prestazioni di picco dei Transformers con Optimum Intel

Optimum è una libreria open-source creata da Hugging Face per semplificare l’accelerazione dei Transformer su una crescente gamma di dispositivi per l’allenamento e l’inferenza. Grazie alle tecniche di ottimizzazione integrate, puoi iniziare ad accelerare i tuoi carichi di lavoro in pochi minuti, utilizzando script predefiniti o apportando modifiche minime al tuo codice esistente. I principianti possono utilizzare Optimum così com’è ottenendo risultati eccellenti. Gli esperti possono continuare a ottimizzare per massime prestazioni.

Optimum Intel fa parte di Optimum e si basa sulla libreria Intel Neural Compressor (INC). INC è una libreria open-source che fornisce interfacce unificate tra diversi framework di deep learning per tecnologie di compressione di rete popolari, come quantizzazione, potatura e distillazione della conoscenza. Questo strumento supporta strategie di ottimizzazione automatica guidate dall’accuratezza per aiutare gli utenti a creare rapidamente il miglior modello quantizzato.

Con Optimum Intel, puoi applicare tecniche di ottimizzazione all’avanguardia ai tuoi Transformers con uno sforzo minimo. Vediamo un esempio completo.

Case study: Quantizzazione di DistilBERT con Optimum Intel

In questo esempio, eseguiremo la quantizzazione post-training su un modello DistilBERT ottimizzato per la classificazione. La quantizzazione è un processo che riduce memoria e requisiti di calcolo riducendo la larghezza dei bit dei parametri del modello. Ad esempio, è spesso possibile sostituire i parametri in virgola mobile a 32 bit con interi a 8 bit a spese di una piccola riduzione nell’accuratezza delle previsioni.

Abbiamo già ottimizzato il modello originale per classificare le recensioni dei prodotti per scarpe in base alla loro valutazione a stelle (da 1 a 5 stelle). Puoi visualizzare questo modello e la sua versione quantizzata nell’hub di Hugging Face. Puoi anche testare il modello originale in questo spazio.

Cominciamo! Tutto il codice è disponibile in questo notebook.

Come al solito, il primo passo è installare tutte le librerie necessarie. Vale la pena menzionare che dobbiamo lavorare con una versione solo CPU di PyTorch affinché il processo di quantizzazione funzioni correttamente.

pip -q uninstall torch -y 
pip -q install torch==1.11.0+cpu --extra-index-url https://download.pytorch.org/whl/cpu
pip -q install transformers datasets optimum[neural-compressor] evaluate --upgrade

In seguito, prepariamo un dataset di valutazione per valutare le prestazioni del modello durante la quantizzazione. Partendo dal dataset che abbiamo utilizzato per ottimizzare il modello originale, manteniamo solo alcune migliaia di recensioni e le relative etichette e le salviamo sul disco locale.

Iniziamo caricando il modello originale, il suo tokenizer e il dataset di valutazione dal hub di Hugging Face.

from datasets import load_dataset
from transformers import AutoModelForSequenceClassification, AutoTokenizer

model_name = "juliensimon/distilbert-amazon-shoe-reviews"
model = AutoModelForSequenceClassification.from_pretrained(model_name, num_labels=5)
tokenizer = AutoTokenizer.from_pretrained(model_name)
eval_dataset = load_dataset("prashantgrao/amazon-shoe-reviews", split="test").select(range(300))

Successivamente, definiamo una funzione di valutazione che calcola le metriche del modello sul dataset di valutazione. Ciò consente alla libreria Optimum Intel di confrontare queste metriche prima e dopo la quantizzazione. A tal scopo, la libreria di valutazione di Hugging Face è molto comoda!

import evaluate

def eval_func(model):
    task_evaluator = evaluate.evaluator("text-classification")
    results = task_evaluator.compute(
        model_or_pipeline=model,
        tokenizer=tokenizer,
        data=eval_dataset,
        metric=evaluate.load("accuracy"),
        label_column="labels",
        label_mapping=model.config.label2id,
    )
    return results["accuracy"]

Successivamente, impostiamo il lavoro di quantizzazione utilizzando una [configurazione]. Puoi trovare i dettagli su questa configurazione nella documentazione di Neural Compressor. Qui, optiamo per la quantizzazione dinamica post-training con una riduzione accettabile dell’accuratezza del 5%. Se l’accuratezza diminuisce più del 5% consentito, verrà quantizzata una parte diversa del modello fino a quando non si ottiene una riduzione accettabile dell’accuratezza o si raggiunge il numero massimo di prove consentito, impostato qui a 10.

from neural_compressor.config import AccuracyCriterion, PostTrainingQuantConfig, TuningCriterion

tuning_criterion = TuningCriterion(max_trials=10)
accuracy_criterion = AccuracyCriterion(tolerable_loss=0.05)
# Carica la configurazione di quantizzazione che specifica la quantizzazione che vogliamo applicare
quantization_config = PostTrainingQuantConfig(
    approach="dynamic",
    accuracy_criterion=accuracy_criterion,
    tuning_criterion=tuning_criterion,
)

Ora possiamo avviare il lavoro di quantizzazione e salvare il modello risultante e il suo file di configurazione nella memoria locale.

from neural_compressor.config import PostTrainingQuantConfig
from optimum.intel.neural_compressor import INCQuantizer

# La directory in cui verrà salvato il modello quantizzato
save_dir = "./model_inc"
quantizer = INCQuantizer.from_pretrained(model=model, eval_fn=eval_func)
quantizer.quantize(quantization_config=quantization_config, save_directory=save_dir)

Il log ci dice che Optimum Intel ha quantizzato 38 operatori Linear e 2 operatori Embedding.

[INFO] |******Statistiche Precisione Mista*****|
[INFO] +----------------+----------+---------+
[INFO] |    Tipo Op     |  Totale  |   INT8  |
[INFO] +----------------+----------+---------+
[INFO] |   Embedding    |    2     |    2    |
[INFO] |     Linear     |    38    |    38   |
[INFO] +----------------+----------+---------+

Confrontando il primo livello del modello originale ( model.distilbert.transformer.layer[0] ) e la sua versione quantizzata ( inc_model.distilbert.transformer.layer[0] ), vediamo che Linear è effettivamente stato sostituito da DynamicQuantizedLinear , il suo equivalente quantizzato.

# Modello originale

TransformerBlock(
  (attention): MultiHeadSelfAttention(
    (dropout): Dropout(p=0.1, inplace=False)
    (q_lin): Linear(in_features=768, out_features=768, bias=True)
    (k_lin): Linear(in_features=768, out_features=768, bias=True)
    (v_lin): Linear(in_features=768, out_features=768, bias=True)
    (out_lin): Linear(in_features=768, out_features=768, bias=True)
  )
  (sa_layer_norm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)
  (ffn): FFN(
    (dropout): Dropout(p=0.1, inplace=False)
    (lin1): Linear(in_features=768, out_features=3072, bias=True)
    (lin2): Linear(in_features=3072, out_features=768, bias=True)
  )
  (output_layer_norm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)
)

# Modello quantizzato

TransformerBlock(
  (attention): MultiHeadSelfAttention(
    (dropout): Dropout(p=0.1, inplace=False)
    (q_lin): DynamicQuantizedLinear(in_features=768, out_features=768, dtype=torch.qint8, qscheme=torch.per_channel_affine)
    (k_lin): DynamicQuantizedLinear(in_features=768, out_features=768, dtype=torch.qint8, qscheme=torch.per_channel_affine)
    (v_lin): DynamicQuantizedLinear(in_features=768, out_features=768, dtype=torch.qint8, qscheme=torch.per_channel_affine)
    (out_lin): DynamicQuantizedLinear(in_features=768, out_features=768, dtype=torch.qint8, qscheme=torch.per_channel_affine)
  )
  (sa_layer_norm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)
  (ffn): FFN(
    (dropout): Dropout(p=0.1, inplace=False)
    (lin1): DynamicQuantizedLinear(in_features=768, out_features=3072, dtype=torch.qint8, qscheme=torch.per_channel_affine)
    (lin2): DynamicQuantizedLinear(in_features=3072, out_features=768, dtype=torch.qint8, qscheme=torch.per_channel_affine)
  )
  (output_layer_norm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)
)

Molto bene, ma come influisce questo sull’accuratezza e sul tempo di previsione?

Prima e dopo ogni passaggio di quantizzazione, Optimum Intel esegue la funzione di valutazione sul modello attuale. L’accuratezza del modello quantizzato è ora leggermente inferiore ( 0.546 ) rispetto al modello originale ( 0.574 ). Vediamo anche che il passaggio di valutazione del modello quantizzato è stato 1,34 volte più veloce rispetto al modello originale. Niente male per poche righe di codice!

[INFO] |**********************Statistiche del Risultato Ottimale**********************|
[INFO] +--------------------+----------+---------------+------------------+
[INFO] |     Tipo Info      | Baseline | Risultato Tune 1 | Miglior risultato Tune |
[INFO] +--------------------+----------+---------------+------------------+
[INFO] |     Accuratezza     |  0.5740  |     0.5460    |      0.5460      |
[INFO] | Durata (secondi)   | 13.1534  |     9.7695    |      9.7695      |
[INFO] +--------------------+----------+---------------+------------------+

Puoi trovare il modello risultante ospitato sul Hugging Face hub. Per caricare un modello quantizzato ospitato localmente o sul hub 🤗, puoi fare come segue:

from optimum.intel.neural_compressor import INCModelForSequenceClassification

inc_model = INCModelForSequenceClassification.from_pretrained(save_dir)

Siamo appena iniziati

In questo esempio, ti abbiamo mostrato come quantizzare facilmente i modelli dopo l’addestramento con Optimum Intel, e questo è solo l’inizio. La libreria supporta anche altri tipi di quantizzazione oltre alla potatura, una tecnica che annulla o rimuove i parametri del modello che hanno poco o nessun impatto sull’outcome previsto.

Siamo entusiasti di collaborare con Intel per offrire agli utenti di Hugging Face massima efficienza sui più recenti processori Intel Xeon e sulle librerie di intelligenza artificiale Intel. Per ricevere aggiornamenti, ti preghiamo di dare una stella a Optimum Intel e rimanere sintonizzato su molte nuove funzionalità in arrivo!

Molte grazie a Ella Charlaix per il suo aiuto su questo post.