Press "Enter" to skip to content

分布式训练:使用🤗 Transformers和Amazon SageMaker训练BART/T5进行摘要

分布式训练:使用🤗 Transformers和Amazon SageMaker训练BART/T5进行摘要 四海 第1张

如果你错过了:我们在3月25日宣布与Amazon SageMaker合作,旨在更轻松地创建最先进的机器学习模型,并更快地发布尖端的NLP功能。

与SageMaker团队一起,我们构建了🤗优化的Transformers深度学习容器,以加速基于Transformers的模型训练。感谢AWS的朋友们!🤗 🚀

通过SageMaker Python SDK中的新HuggingFace估计器,您可以通过一行代码开始训练。

分布式训练:使用🤗 Transformers和Amazon SageMaker训练BART/T5进行摘要 四海 第2张

发布的博客文章提供了有关集成的所有信息,包括“入门”示例和文档、示例和功能的链接。

在此再次列出:

  • 🤗 Transformers文档:Amazon SageMaker
  • 示例笔记本
  • Hugging Face的Amazon SageMaker文档
  • Hugging Face的Python SDK SageMaker文档
  • 深度学习容器

如果您对Amazon SageMaker不熟悉:“Amazon SageMaker是一项完全托管的服务,为每个开发人员和数据科学家提供快速构建、训练和部署机器学习(ML)模型的能力。SageMaker从机器学习过程的每个步骤中减轻了繁重的负担,使开发高质量模型更加容易。”[ REF ]


我们将使用新的Hugging Face DLCs和Amazon SageMaker扩展来在summarization任务中训练分布式Seq2Seq-transformer模型,使用transformersdatasets库,然后将模型上传到huggingface.co进行测试。

作为分布式训练策略,我们将使用SageMaker数据并行处理,这已经集成到Trainer API中。要使用数据并行处理,我们只需要在我们的HuggingFace估计器中定义distribution参数。

# configuration for running training on smdistributed Data Parallel
distribution = {'smdistributed':{'dataparallel':{ 'enabled': True }}}

在本教程中,我们将使用Amazon SageMaker笔记本实例来运行我们的训练作业。您可以在此了解如何设置笔记本实例。

我们将要做的事情:

  • 设置开发环境并安装sagemaker
  • 选择🤗 Transformers examples/ 脚本
  • 配置分布式训练和超参数
  • 创建一个HuggingFace估计器并开始训练
  • 将微调模型上传到huggingface.co
  • 进行推理测试

模型和数据集

我们将在samsum数据集上微调facebook/bart-large-cnn模型。“BART是一个带有去噪预训练目标的序列到序列模型。”[ REF ]

samsum数据集包含约16,000个类似于Messenger的对话和摘要。

{"id": "13818513",
 "summary": "Amanda烤了一些饼干,明天会给Jerry一些。",
 "dialogue": "Amanda: 我烤了一些饼干。你要吃吗?\r\nJerry: 当然!\r\nAmanda: 我明天给你 :-)"}

设置开发环境并安装sagemaker

在我们的SageMaker笔记本实例运行后,我们可以选择Jupyter Notebook或JupyterLab,并使用conda_pytorch_p36 kernel创建一个新的笔记本。

注意:使用Jupyter是可选的:我们也可以从任何安装了SDK、与云端连接并具有适当权限的地方启动SageMaker训练作业,比如笔记本电脑、其他IDE或任务调度器(如Airflow或AWS Step Functions)。

之后,我们可以安装所需的依赖项

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

安装git-lfs以用于模型上传。

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

要在SageMaker上运行训练,我们需要创建一个sagemaker会话并提供一个具有正确权限的IAM角色。这个IAM角色将后续附加到TrainingJob,使其能够下载数据,例如从Amazon S3。

import sagemaker

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

print(f"用于运行训练的IAM角色ARN:{role}")
print(f"用于存储工件的S3存储桶:{sess.default_bucket()}")

🤗 Transformers存储库包含多个用于在任务上微调模型的examples/脚本,从language-modelingtoken-classification。在我们的案例中,我们使用seq2seq/示例中的run_summarization.py

注意:您可以直接使用本教程在不同的示例脚本上训练您的模型。

由于HuggingFace Estimator内置了git支持,我们可以将存储在GitHub存储库中的训练脚本指定为entry_pointsource_dir

我们将使用transformers 4.4.2 DLC,这意味着我们需要将v4.4.2配置为拉取兼容示例脚本的分支。

#git_config = {'repo': 'https://github.com/huggingface/transformers.git','branch': 'v4.4.2'} # v4.4.2 is referring to the `transformers_version you use in the estimator.
# used due an missing package in v4.4.2 
git_config = {'repo': 'https://github.com/philschmid/transformers.git','branch': 'master'} # v4.4.2 is referring to the `transformers_version you use in the estimator.

配置分布式训练和超参数

接下来,我们将定义我们的hyperparameters并配置我们的分布式训练策略。作为超参数,我们可以定义任何Seq2SeqTrainingArguments和在run_summarization.py中定义的超参数。

# 传递给训练作业的超参数
hyperparameters={
    '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,
}

# 配置在smdistributed Data Parallel上运行训练
distribution = {'smdistributed':{'dataparallel':{ 'enabled': True }}}

由于我们使用SageMaker数据并行处理,我们的total_batch_size将是per_device_train_batch_size * n_gpus


创建一个HuggingFace estimator并开始训练

在训练之前的最后一步是创建一个HuggingFace estimator。Estimator处理完整的Amazon SageMaker训练流程。我们定义应使用哪个微调脚本作为entry_point,应使用哪个instance_type,以及传递哪些hyperparameters

from sagemaker.huggingface import HuggingFace

# 创建Estimator
huggingface_estimator = HuggingFace(
      entry_point='run_summarization.py', # 脚本
      source_dir='./examples/seq2seq', # 示例的相对路径
      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 = hyperparameters,
      distribution = distribution
)

作为instance_type,我们使用ml.p3dn.24xlarge,其中包含8个NVIDIA A100,instance_count为2。这意味着我们将在16个GPU上进行训练,并且total_batch_size为16 * 4 = 64。我们将训练一个拥有4亿个参数的模型,total_batch_size为64,这真是太棒了。要开始训练,我们调用.fit()方法。

# 开始训练工作
huggingface_estimator.fit()

2021-04-01 13:00:35 开始 - 开始训练工作...
2021-04-01 13:01:03 开始 - 启动所请求的 ML 实例ProfilerReport-1617282031:进行中
2021-04-01 13:02:23 开始 - 准备实例进行训练......
2021-04-01 13:03:25 下载中 - 下载输入数据...
2021-04-01 13:04:04 训练中 - 正在下载训练图像...............
2021-04-01 13:06:33 训练中 - 训练图像下载完成。训练进行中
....
....
2021-04-01 13:16:47 上传中 - 上传生成的训练模型
2021-04-01 13:27:49 完成 - 训练工作已完成
训练时间(秒):2882
计费时间(秒):2882

训练时间为2882秒,因为乘以了实例的数量。如果我们计算2882/2=1441,则是从“下载训练图像”到“训练工作已完成”的持续时间。换算成真实货币,我们使用16个NVIDIA Tesla V100-GPU训练一个最先进的摘要模型,费用约为28美元。


将微调模型上传到huggingface.co

由于我们的模型取得了相当不错的得分,我们将把它上传到huggingface.co,并创建一个model_card,并使用托管推理小部件进行测试。要上传模型,您需要在此处创建一个帐户。

我们可以使用以下代码片段从Amazon S3下载并解压缩我们的模型。

import os
import tarfile
from sagemaker.s3 import S3Downloader

local_path = 'my_bart_model'

os.makedirs(local_path, exist_ok = True)

# 从S3下载模型
S3Downloader.download(
    s3_uri=huggingface_estimator.model_data, # 训练模型所在的S3 URI
    local_path=local_path, # 将保存*.tar.gz文件的本地路径
    sagemaker_session=sess # 用于训练模型的SageMaker会话
)

# 解压缩模型
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")

在将模型上传到huggingface.co之前,我们需要创建一个model_cardmodel_card描述了模型,并包括超参数、结果以及用于训练的数据集的详细信息。为了创建model_card,我们在local_path中创建一个README.md文件。

# 读取评估和测试结果
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"]

在提取我们想要包含的所有指标后,我们将创建我们的README.md。除了自动生成结果表之外,我们还将手动将指标添加到模型卡片的metadata下。

import json

MODEL_CARD_TEMPLATE = """
---
language: en
tags:
- sagemaker
- bart
- summarization
license: apache-2.0
datasets:
- samsum
model-index:
- name: {model_name}
  results:
  - task: 
      name: Abstractive Text Summarization
      type: abstractive-text-summarization
    dataset:
      name: "SAMSum Corpus: A Human-annotated Dialogue Dataset for Abstractive Summarization" 
      type: samsum
    metrics:
       - name: Validation ROGUE-1
         type: rogue-1
         value: 42.621
       - name: Validation ROGUE-2
         type: rogue-2
         value: 21.9825
       - name: Validation ROGUE-L
         type: rogue-l
         value: 33.034
       - name: Test ROGUE-1
         type: rogue-1
         value: 41.3174
       - name: Test ROGUE-2
         type: rogue-2
         value: 20.8716
       - name: Test ROGUE-L
         type: rogue-l
         value: 32.1337
widget:
- text: | 
    Jeff: Can I train a 🤗 Transformers model on Amazon SageMaker? 
    Philipp: Sure you can use the new Hugging Face Deep Learning Container. 
    Jeff: ok.
    Jeff: and how can I get started? 
    Jeff: where can I find documentation? 
    Philipp: ok, ok you can find everything here. https://huggingface.co/blog/the-partnership-amazon-sagemaker-and-hugging-face 
---

## `{model_name}`

This model was trained using Amazon SageMaker and the new Hugging Face Deep Learning container.

For more information look at:
- [🤗 Transformers Documentation: Amazon SageMaker](https://huggingface.co/transformers/sagemaker.html)
- [Example Notebooks](https://github.com/huggingface/notebooks/tree/master/sagemaker)
- [Amazon SageMaker documentation for Hugging Face](https://docs.aws.amazon.com/sagemaker/latest/dg/hugging-face.html)
- [Python SDK SageMaker documentation for 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)

## 超参数

    {hyperparameters}


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

    conversation = '''Jeff: Can I train a 🤗 Transformers model on Amazon SageMaker? 
    Philipp: Sure you can use the new Hugging Face Deep Learning Container. 
    Jeff: ok.
    Jeff: and how can I get started? 
    Jeff: where can I find documentation? 
    Philipp: ok, ok you can find everything here. https://huggingface.co/blog/the-partnership-amazon-sagemaker-and-hugging-face                                           
    '''
    nlp(conversation)

## 结果

| key | value |
| --- | ----- |
{eval_table}
{test_table}



"""

# 生成模型卡片(待办:从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)

在我们将解压的模型和模型卡片放在 my_bart_model 目录后,我们可以使用 huggingface_hub SDK 创建一个仓库并将其上传到 huggingface.co,或者只需访问 https://huggingface.co/new 创建一个新的仓库并上传。

from getpass import getpass
from huggingface_hub import HfApi, Repository

hf_username = "philschmid" # 在 huggingface.co 上的用户名
hf_email = "philipp@huggingface.co" # 提交所用的电子邮件
repository_name = f"{hyperparameters['model_name_or_path'].split('/')[1]}-{hyperparameters['dataset_name']}" # 在 huggingface.co 上的仓库名
password = getpass("输入您的密码:") # 创建输入密码的提示

# 获取 hf token
token = HfApi().login(username=hf_username, password=password)

# 创建仓库
repo_url = HfApi().create_repo(token=token, name=repository_name, exist_ok=True)

# 创建一个 Repository 实例
model_repo = Repository(use_auth_token=token,
                        clone_from=repo_url,
                        local_dir=local_path,
                        git_user=hf_username,
                        git_email=hf_email)

# 推送模型到 hub
model_repo.push_to_hub()

测试推理

在我们上传模型后,我们可以通过 https://huggingface.co/{hf_username}/{repository_name} 访问它。

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

并使用“Hosted Inference API”小部件来测试它。

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

分布式训练:使用🤗 Transformers和Amazon SageMaker训练BART/T5进行摘要 四海 第3张

Leave a Reply

Your email address will not be published. Required fields are marked *