Addestramento Distribuito Addestra BART/T5 per la Sintesi utilizzando 🤗 Transformers e Amazon SageMaker

'Addestramento Distribuito di BART/T5 per la Sintesi con 🤗 Transformers e Amazon SageMaker'

In caso te lo fossi perso: il 25 marzo abbiamo annunciato una collaborazione con Amazon SageMaker per rendere più facile creare modelli di Machine Learning all’avanguardia e spedire funzionalità NLP all’ultimo grido più velocemente.

Insieme al team di SageMaker, abbiamo costruito 🤗 Containers di Deep Learning ottimizzati per i Transformers per accelerare l’addestramento dei modelli basati su Transformers. Grazie amici di AWS!🤗 🚀

Con il nuovo estimatore HuggingFace nel SDK Python di SageMaker, puoi iniziare l’addestramento con una sola riga di codice.

Il post del blog di annunci fornisce tutte le informazioni che devi conoscere sull’integrazione, incluso un esempio di “Come iniziare” e link alla documentazione, agli esempi e alle funzionalità.

elencate nuovamente qui:

  • 🤗 Documentazione Transformers: Amazon SageMaker
  • Notebook di esempio
  • Documentazione Amazon SageMaker per Hugging Face
  • Documentazione SDK Python SageMaker per Hugging Face
  • Container di Deep Learning

Se non sei familiare con Amazon SageMaker: “Amazon SageMaker è un servizio completamente gestito che fornisce a ogni sviluppatore e scienziato dei dati la capacità di creare, addestrare e distribuire modelli di machine learning (ML) rapidamente. SageMaker rimuove il lavoro pesante da ogni passaggio del processo di machine learning per rendere più facile sviluppare modelli di alta qualità.” [REF]


Useremo i nuovi DLC di Hugging Face e l’estensione di Amazon SageMaker per addestrare un modello Seq2Seq-transformer distribuito sul compito di summarization utilizzando le librerie transformers e datasets, quindi caricheremo il modello su huggingface.co e lo testeremo.

Come strategia di addestramento distribuito utilizzeremo il Data Parallelism di SageMaker, che è stato integrato nell’API del Trainer. Per utilizzare il data-parallelism dobbiamo solo definire il parametro distribution nel nostro estimatore HuggingFace.

# configurazione per l'esecuzione dell'addestramento su smdistributed Data Parallel
distribution = {'smdistributed':{'dataparallel':{ 'enabled': True }}}

In questo tutorial, utilizzeremo un’istanza del notebook di Amazon SageMaker per eseguire il nostro lavoro di addestramento. Puoi imparare qui come configurare un’istanza del notebook.

Cosa faremo:

  • Configurare un ambiente di sviluppo e installare sagemaker
  • Scegliere lo script 🤗 Transformers examples/
  • Configurare l’addestramento distribuito e gli iperparametri
  • Creare un estimatore HuggingFace e avviare l’addestramento
  • Caricare il modello fine-tuned su huggingface.co
  • Testare l’inferenza

Modello e Dataset

Stiamo per effettuare il fine-tuning di facebook/bart-large-cnn sul dataset samsum. “BART è un modello sequenza-a-sequenza addestrato con denoising come obiettivo di pretraining.” [REF]

Il dataset samsum contiene circa 16k conversazioni simili a messaggi con riassunti.

{"id": "13818513",
 "summary": "Amanda ha fatto dei biscotti e li porterà a Jerry domani.",
 "dialogue": "Amanda: Ho fatto dei biscotti. Ne vuoi qualcuno?\r\nJerry: Certo!\r\nAmanda: Te li porterò domani :-)"}

Configurare un ambiente di sviluppo e installare sagemaker

Dopo che la nostra istanza del notebook di SageMaker è in esecuzione, possiamo selezionare Jupyter Notebook o JupyterLab e creare un nuovo notebook con il kernel conda_pytorch_p36.

Nota: L’uso di Jupyter è opzionale: potremmo anche avviare lavori di addestramento di SageMaker da qualsiasi punto in cui abbiamo installato un SDK, connettività al cloud e autorizzazioni appropriate, come un laptop, un altro IDE o un pianificatore di attività come Airflow o AWS Step Functions.

Dopo di che possiamo installare le dipendenze richieste

!pip install transformers "datasets[s3]" sagemaker --upgrade

installa git-lfs per il caricamento del modello.

!curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.rpm.sh | sudo bash
!sudo yum install git-lfs -y
!git lfs install

Per eseguire l’addestramento su SageMaker è necessario creare una sessione sagemaker e fornire un ruolo IAM con i permessi corretti. Questo ruolo IAM verrà successivamente allegato al TrainingJob consentendogli di scaricare i dati, ad esempio da Amazon S3.

import sagemaker

sess = sagemaker.Session()
role = sagemaker.get_execution_role()

print(f"ARN del ruolo IAM utilizzato per eseguire l'addestramento: {role}")
print(f"Bucket S3 utilizzato per archiviare gli artefatti: {sess.default_bucket()}")

La repository 🤗 Transformers contiene diversi script examples/ per il fine-tuning dei modelli su compiti che vanno dal language-modeling alla token-classification. Nel nostro caso, stiamo utilizzando run_summarization.py dagli esempi in seq2seq/.

Nota: è possibile utilizzare questo tutorial così com’è per addestrare il proprio modello su uno script di esempi diverso.

Dato che HuggingFace Estimator ha il supporto git integrato, possiamo specificare uno script di addestramento archiviato in un repository GitHub come entry_point e source_dir.

Utilizzeremo il DLC transformers 4.4.2, il che significa che dobbiamo configurare v4.4.2 come il ramo da cui scaricare gli script di esempio compatibili.

#git_config = {'repo': 'https://github.com/huggingface/transformers.git','branch': 'v4.4.2'} # v4.4.2 si riferisce alla `transformers_version` utilizzata nell'estimatore.
# utilizzato a causa di un pacchetto mancante in v4.4.2
git_config = {'repo': 'https://github.com/philschmid/transformers.git','branch': 'master'} # v4.4.2 si riferisce alla `transformers_version` utilizzata nell'estimatore.

Configurare l’addestramento distribuito e gli iperparametri

Successivamente, definiremo i nostri iperparametri e configureremo la nostra strategia di addestramento distribuito. Come iperparametro, possiamo definire qualsiasi Seq2SeqTrainingArguments e quelli definiti in run_summarization.py.

# iperparametri, che vengono passati al job di addestramento
iperparametri={
    'per_device_train_batch_size': 4,
    'per_device_eval_batch_size': 4,
    'model_name_or_path':'facebook/bart-large-cnn',
    'dataset_name':'samsum',
    'do_train':True,
    'do_predict': True,
    'predict_with_generate': True,
    'output_dir':'/opt/ml/model',
    'num_train_epochs': 3,
    'learning_rate': 5e-5,
    'seed': 7,
    'fp16': True,
}

# configurazione per l'esecuzione dell'addestramento su smdistributed Data Parallel
distribuzione = {'smdistributed':{'dataparallel':{ 'enabled': True }}}

Dato che stiamo utilizzando la parallelizzazione dei dati di SageMaker, il nostro total_batch_size sarà per_device_train_batch_size * n_gpus.


Creare un estimatore HuggingFace e avviare l’addestramento

Ultimo passo prima dell’addestramento è creare un estimatore HuggingFace. L’Estimator gestisce l’addestramento end-to-end di Amazon SageMaker. Definiamo quale script di fine-tuning dovrebbe essere utilizzato come entry_point, quale instance_type dovrebbe essere utilizzato e quali iperparametri vengono passati.

from sagemaker.huggingface import HuggingFace

# creare l'estimatore
huggingface_estimator = HuggingFace(
      entry_point='run_summarization.py', # script
      source_dir='./examples/seq2seq', # percorso relativo all'esempio
      git_config=git_config,
      instance_type='ml.p3dn.24xlarge',
      instance_count=2,
      transformers_version='4.4.2',
      pytorch_version='1.6.0',
      py_version='py36',
      role=role,
      hyperparameters = iperparametri,
      distribution = distribuzione
)

Come instance_type stiamo utilizzando ml.p3dn.24xlarge, che contiene 8x NVIDIA A100 con un instance_count di 2. Ciò significa che eseguiremo l’addestramento su 16 GPU e un total_batch_size di 16*4=64. Addestreremo un modello con 400 milioni di parametri con un total_batch_size di 64, il che è incredibile. Per avviare l’addestramento chiamiamo il metodo .fit().

# avvio del lavoro di addestramento
huggingface_estimator.fit()

2021-04-01 13:00:35 Avvio - Avvio del lavoro di addestramento...
2021-04-01 13:01:03 Avvio - Avvio delle istanze di ML richiesteProfilerReport-1617282031: In corso
2021-04-01 13:02:23 Avvio - Preparazione delle istanze per l'addestramento......
2021-04-01 13:03:25 Download - Download dei dati di input...
2021-04-01 13:04:04 Addestramento - Download dell'immagine di addestramento...............
2021-04-01 13:06:33 Addestramento - Download dell'immagine di addestramento completato. Addestramento in corso
....
....
2021-04-01 13:16:47 Caricamento - Caricamento del modello di addestramento generato
2021-04-01 13:27:49 Completato - Lavoro di addestramento completato
Secondi di addestramento: 2882
Secondi fatturabili: 2882

I secondi di addestramento sono 2882 perché sono moltiplicati per il numero di istanze. Se calcoliamo 2882/2=1441, otteniamo la durata dal “Download dell’immagine di addestramento” al “Lavoro di addestramento completato”. Convertito in denaro reale, il nostro addestramento su 16 NVIDIA Tesla V100-GPU per un modello di sintesi di stato dell’arte ammonta a circa 28$.


Carica il modello sintonizzato su huggingface.co

Dato che il nostro modello ha ottenuto un punteggio abbastanza buono, lo caricheremo su huggingface.co, creeremo una model_card e lo testeremo con il widget Hosted Inference. Per caricare un modello, è necessario creare un account qui .

Possiamo scaricare il nostro modello da Amazon S3 e decomprimerlo utilizzando il seguente frammento di codice.

import os
import tarfile
from sagemaker.s3 import S3Downloader

local_path = 'my_bart_model'

os.makedirs(local_path, exist_ok = True)

# scarica il modello da S3
S3Downloader.download(
    s3_uri=huggingface_estimator.model_data, # s3 uri in cui si trova il modello addestrato
    local_path=local_path, # percorso locale in cui verrà salvato il file *.tar.gz
    sagemaker_session=sess # sessione sagemaker utilizzata per addestrare il modello
)

# decomprimi il modello
tar = tarfile.open(f"{local_path}/model.tar.gz", "r:gz")
tar.extractall(path=local_path)
tar.close()
os.remove(f"{local_path}/model.tar.gz")

Prima di caricare il nostro modello su huggingface.co, dobbiamo creare una model_card. La model_card descrive il modello e include iperparametri, risultati e specifica quale dataset è stato utilizzato per l’addestramento. Per creare una model_card creiamo un file README.md nella nostra local_path

# leggi i risultati di valutazione e test
with open(f"{local_path}/eval_results.json") as f:
    eval_results_raw = json.load(f)
    eval_results={}
    eval_results["eval_rouge1"] = eval_results_raw["eval_rouge1"]
    eval_results["eval_rouge2"] = eval_results_raw["eval_rouge2"]
    eval_results["eval_rougeL"] = eval_results_raw["eval_rougeL"]
    eval_results["eval_rougeLsum"] = eval_results_raw["eval_rougeLsum"]

with open(f"{local_path}/test_results.json") as f:
    test_results_raw = json.load(f)
    test_results={}
    test_results["test_rouge1"] = test_results_raw["test_rouge1"]
    test_results["test_rouge2"] = test_results_raw["test_rouge2"]
    test_results["test_rougeL"] = test_results_raw["test_rougeL"]
    test_results["test_rougeLsum"] = test_results_raw["test_rougeLsum"]

Dopo aver estratto tutte le metriche che vogliamo includere, creiamo il nostro README.md. Oltre alla generazione automatica della tabella dei risultati, aggiungiamo manualmente le metriche al metadata della nostra model card sotto model-index

import json

MODEL_CARD_TEMPLATE = """
---
language: it
tags:
- sagemaker
- bart
- sintesi
license: apache-2.0
datasets:
- samsum
model-index:
- name: {model_name}
  results:
  - task: 
      name: Sintesi di testo astratto
      type: sintesi-di-testo-astratto
    dataset:
      name: "SAMSum Corpus: un dataset di dialoghi annotati dall'uomo per la sintesi astratta" 
      type: samsum
    metrics:
       - name: ROGUE-1 di validazione
         type: rogue-1
         value: 42.621
       - name: ROGUE-2 di validazione
         type: rogue-2
         value: 21.9825
       - name: ROGUE-L di validazione
         type: rogue-l
         value: 33.034
       - name: ROGUE-1 di test
         type: rogue-1
         value: 41.3174
       - name: ROGUE-2 di test
         type: rogue-2
         value: 20.8716
       - name: ROGUE-L di test
         type: rogue-l
         value: 32.1337
widget:
- text: | 
    Jeff: Posso addestrare un modello 🤗 Transformers su Amazon SageMaker? 
    Philipp: Certamente puoi utilizzare il nuovo Hugging Face Deep Learning Container. 
    Jeff: ok.
    Jeff: e come posso iniziare? 
    Jeff: dove posso trovare la documentazione? 
    Philipp: ok, ok puoi trovare tutto qui. https://huggingface.co/blog/the-partnership-amazon-sagemaker-and-hugging-face 
---

## `{model_name}`

Questo modello è stato addestrato utilizzando Amazon SageMaker e il nuovo Hugging Face Deep Learning container.

Per ulteriori informazioni, consulta:
- [🤗 Documentazione di Transformers: Amazon SageMaker](https://huggingface.co/transformers/sagemaker.html)
- [Esempi di notebook](https://github.com/huggingface/notebooks/tree/master/sagemaker)
- [Documentazione di Amazon SageMaker per Hugging Face](https://docs.aws.amazon.com/sagemaker/latest/dg/hugging-face.html)
- [Documentazione Python SDK SageMaker per Hugging Face](https://sagemaker.readthedocs.io/en/stable/frameworks/huggingface/index.html)
- [Deep Learning Container](https://github.com/aws/deep-learning-containers/blob/master/available_images.md#huggingface-training-containers)

## Iperparametri

    {hyperparameters}


## Utilizzo
    from transformers import pipeline
    summarizer = pipeline("summarization", model="philschmid/{model_name}")

    conversation = '''Jeff: Posso addestrare un modello 🤗 Transformers su Amazon SageMaker? 
    Philipp: Certamente puoi utilizzare il nuovo Hugging Face Deep Learning Container. 
    Jeff: ok.
    Jeff: e come posso iniziare? 
    Jeff: dove posso trovare la documentazione? 
    Philipp: ok, ok puoi trovare tutto qui. https://huggingface.co/blog/the-partnership-amazon-sagemaker-and-hugging-face                                           
    '''
    nlp(conversation)

## Risultati

| chiave | valore |
| ------ | ------ |
{eval_table}
{test_table}



"""

# Genera la model card (todo: aggiungi più dati da Trainer)
model_card = MODEL_CARD_TEMPLATE.format(
    model_name=f"{hyperparameters['model_name_or_path'].split('/')[1]}-{hyperparameters['dataset_name']}",
    hyperparameters=json.dumps(hyperparameters, indent=4, sort_keys=True),
    eval_table="\n".join(f"| {k} | {v} |" for k, v in eval_results.items()),
    test_table="\n".join(f"| {k} | {v} |" for k, v in test_results.items()),
)

with open(f"{local_path}/README.md", "w") as f:
    f.write(model_card)

Dopo aver ottenuto il nostro modello decompresso e la scheda del modello posizionati in my_bart_model, possiamo utilizzare l’SDK huggingface_hub per creare un repository e caricarlo su huggingface.co – oppure semplicemente andare su https://huggingface.co/new e creare un nuovo repository e caricarlo.

from getpass import getpass
from huggingface_hub import HfApi, Repository

hf_username = "philschmid" # il tuo nome utente su huggingface.co
hf_email = "[email protected]" # email utilizzata per il commit
repository_name = f"{hyperparameters['model_name_or_path'].split('/')[1]}-{hyperparameters['dataset_name']}" # nome del repository su huggingface.co
password = getpass("Inserisci la tua password:") # crea un prompt per l'inserimento della password

# ottieni il token hf
token = HfApi().login(username=hf_username, password=password)

# crea il repository
repo_url = HfApi().create_repo(token=token, name=repository_name, exist_ok=True)

# crea un'istanza di Repository
model_repo = Repository(use_auth_token=token,
                        clone_from=repo_url,
                        local_dir=local_path,
                        git_user=hf_username,
                        git_email=hf_email)

# carica il modello nell'hub
model_repo.push_to_hub()

Test di inferenza

Dopo aver caricato il nostro modello, possiamo accedervi su https://huggingface.co/{hf_username}/{repository_name}

print(f"https://huggingface.co/{hf_username}/{repository_name}")

E utilizzare il widget “Hosted Inference API” per testarlo.

https://huggingface.co/philschmid/bart-large-cnn-samsum