使用 🤗 AutoTrain SpaceRunner 对 NER 数据集上的 Flair 模型进行微调

社区文章 发布于 2023 年 10 月 20 日

TLDR在这篇博文中,我们演示了如何使用强大的 🤗 AutoTrain 库和 SpaceRunner德国 MobIE NER 数据集上微调 Flair 模型。此外,我们还使用 🤗 Hub 客户端库创建了美观的模型卡。

简介

Flair 库是一个用于最先进自然语言处理的简单框架,由柏林洪堡大学及其合作者开发,并完全集成到模型中心中。

我们在这篇博文中利用 Flair 在移动领域(MobIE 数据集)的德语数据集上微调一个用于命名实体识别(NER)的模型。

这篇博文还概述了如何在 Flair 中使用此数据集以及如何进行基本的超参数搜索。

通过利用 🤗 AutoTrain 库与 SpaceRunner 功能,整个微调过程可以在 Hugging Face 生态系统中经济高效地完成。

此外,这篇博文还演示了如何自动上传精细调整的模型并创建信息丰富、美观的模型卡。

德国 MobIE 数据集

德国 MobIE 数据集由 Hennig、Truong 和 Gabryszak (2021) 在 MobIE 论文中介绍。

这是一个德语数据集,已通过人工标注了 20 种粗粒度和细粒度实体类型,并包含地理可链接实体的实体链接信息。该数据集包含 3,232 篇社交媒体文本和交通报告,总计 9.1 万个 token,其中 2.05 万个实体已标注,1.31 万个实体已链接到知识库。总共有 20 种不同的命名实体被标注。

要在 Flair 中使用此数据集,我们必须创建自己的数据集加载器,因为该数据集尚未集成到 Flair 库中

class NER_GERMAN_MOBIE(ColumnCorpus):
    def __init__(
        self,
        base_path: Optional[Union[str, Path]] = None,
        in_memory: bool = True,
        **corpusargs,
    ) -> None:
        base_path = flair.cache_root / "datasets" if not base_path else Path(base_path)
        dataset_name = self.__class__.__name__.lower()
        data_folder = base_path / dataset_name
        data_path = flair.cache_root / "datasets" / dataset_name

        columns = {0: "text", 3: "ner"}

        train_data_file = data_path / "train.conll2003"
        if not train_data_file.is_file():
            temp_file = cached_path(
                "https://github.com/DFKI-NLP/MobIE/raw/master/v1_20210811/ner_conll03_formatted.zip",
                Path("datasets") / dataset_name,
            )
            from zipfile import ZipFile

            with ZipFile(temp_file, "r") as zip_file:
                zip_file.extractall(path=data_path)

        super().__init__(
            data_folder,
            columns,
            in_memory=in_memory,
            comment_symbol=None,
            document_separator_token="-DOCSTART-",
            **corpusargs,
        )

下图显示了一个已标注的句子(取自 MobIE 论文)

image/png

使用 Flair 进行微调

我们使用最新的 Flair 版本进行微调。此外,模型采用 FLERT (Schweter 和 Akbik (2020) 方法进行训练,因为 MobIE 数据集提供了文档边界信息标记。使用 deepset/gbert-base 模型作为骨干 LM。

我们定义了对以下参数的非常基本的超参数搜索:

  • 批处理大小 = [16]
  • 学习率 = [3e-05, 5e-05]
  • 随机种子 = [1, 2, 3, 4, 5]

这意味着总共训练了 10 个模型。超参数搜索可以这样实现:

# Hyper-Parameter search definitions
batch_sizes = [16]
learning_rates = [3e-05, 5e-05]
seeds = [1, 2, 3, 4, 5]
epochs = [10]
context_sizes = [64]

# Backbone LM definitions
base_model = "deepset/gbert-base"
base_model_short = "gbert_base"

# Hugging Face Model Hub configuration
hf_token = os.environ.get("HF_TOKEN")
hf_hub_org_name = os.environ.get("HUB_ORG_NAME")

for seed in seeds:
    for batch_size in batch_sizes:
        for epoch in epochs:
            for learning_rate in learning_rates:
                for context_size in context_sizes:
                    experiment_configuration = ExperimentConfiguration(
                        batch_size=batch_size,
                        learning_rate=learning_rate,
                        epoch=epoch,
                        context_size=context_size,
                        seed=seed,
                        base_model=base_model,
                        base_model_short=base_model_short,
                    )
                    output_path = run_experiment(experiment_configuration=experiment_configuration)

run_experiment() 方法(包含完整的微调逻辑)的实现可以在此处找到。

开始使用 🤗 AutoTrain SpaceRunner 进行微调

微调过程通过使用卓越的 🤗 AutoTrain 库及其 SpaceRunner 功能启动。

这将启动一个基于 Docker 的 SpaceRunner,整个模型微调过程将在 Hugging Face 提供的硬件上进行。

我们使用 T4 Small 实例进行实验。要设置 SpaceRunner,需要两个基本文件:

  • script.py:此文件管理整个微调过程,包括实现超参数搜索和模型上传。您可以在此处找到其示例。
  • requirements.txt:此文件定义了 AutoTrain Space 中安装的所有必要依赖项。

在开始 AutoTrain 微调之前,需要创建以下环境变量:

  • HF_TOKEN:这是用户访问令牌,可以在此处获取。
  • HUB_ORG_NAME:这是创建 AutoTrain Space 的用户名或组织。

要通过命令行启动微调过程,请使用以下命令:

$ autotrain spacerunner --project-name "flair-mobie" \
  --script-path $(pwd) \
  --username stefan-it \
  --token $HF_TOKEN \
  --backend spaces-t4s\
  --env "HF_TOKEN=$HF_TOKEN;HUB_ORG_NAME=stefan-it"

此命令创建一个 Docker 空间,可以监控整个微调过程。此外,它还建立一个新的数据集仓库,所有源文件都存储在此处。

在本教程中,在 T4 small 实例上微调所有十个模型耗时 4 小时 34 分钟,总成本为 2.74 美元

模型上传

每个模型微调完成后,以下文件/文件夹将上传到模型中心(每个模型一个仓库):

  • pytorch-model.bin:Flair 在内部将所有 epoch 中最好的模型追踪为 best-model.pt。为了与模型中心兼容,best-model.pt 会自动重命名为 pytorch_model.bin
  • training.log:Flair 将训练日志存储在 training.log 中。此文件稍后用于解析开发集上的最佳 F1 分数。
  • ./runs:此文件夹中存储了 TensorBoard 日志。这使得在模型中心上可以很好地显示指标。

仓库创建和文件/文件夹上传通过出色的 🤗 Hub 客户端库完成。

# Creates repository
repo_url = api.create_repo(
    repo_id=f"{hf_hub_org_name}/{output_path}",
    token=hf_token,
    private=True,
    exist_ok=True,
)

# Upload TensorBoard logs
api.upload_folder(
    folder_path=f"{output_path}/runs",
    path_in_repo="./runs",
    repo_id=f"{hf_hub_org_name}/{output_path}",
    repo_type="model"
)

# Upload Flair's training log
api.upload_file(
    path_or_fileobj=f"{output_path}/training.log",
    path_in_repo="./training.log",
    repo_id=f"{hf_hub_org_name}/{output_path}",
    repo_type="model"
)

# Upload best model
api.upload_file(
    path_or_fileobj=f"{output_path}/best-model.pt",
    path_in_repo="./pytorch_model.bin",
    repo_id=f"{hf_hub_org_name}/{output_path}",
    repo_type="model"
)

模型卡创建

所有模型自动上传到模型中心后,我们现在希望为每个模型创建具有以下功能的模型卡:

  • 美观的模型卡,包含元数据(重要!);
  • 一个可用的推理小部件,用于尝试其他 NER 示例;
  • 结果概览。

为了自动创建模型卡,我们大量使用了 🤗 Hub 客户端库

元数据部分

我们使用以下模板定义每个模型的元数据部分

---
language: de
license: mit
tags:
- flair
- token-classification
- sequence-tagger-model
base_model: {{ base_model }}
widget:
- text: {{ widget_text }}
---

稍后,我们将 base_modelwidget_text 传递给此模板。

结果概览

结果概览部分非常重要,包括以下步骤:

  • 迭代所有微调模型并解析 training.log 文件,以获取开发集上的最佳 F1 分数
  • 构建所有超参数配置(在我们的示例中,批处理大小、epoch 数量和学习率)的结果表,以及它们在每个种子上的不同 F1 分数,包括平均 F1 分数和标准差

所有这些步骤都显示在我们的示例笔记本中。

training.log 文件中检索所有结果后,Pandas DataFrame 会显示所有种子平均并按超参数配置分组的结果

配置 种子 1 种子 2 种子 3 种子 4 种子 5 平均分 标准差
bs16-e10-lr5e-05 0.8446 0.8495 0.8455 0.8419 0.8476 0.8458 0.0029
bs16-e10-lr3e-05 0.8392 0.8445 0.8495 0.8381 0.8449 0.8432 0.0046

然而,这还不够!我们希望链接相应的模型,并在模型中心上突出显示当前查看模型的结果。最终结果表将如下所示:

配置 种子 1 种子 2 种子 3 种子 4 种子 5 平均分
bs16-e10-lr5e-05 0.8446 0.8495 0.8455 0.8419 0.8476 0.8458 ± 0.0029
bs16-e10-lr3e-05 0.8392 0.8445 0.8495 0.8381 0.8449 0.8432 ± 0.0046

PR 创建

在我们本地构建了美观的模型卡之后,我们现在希望将它们推送到所有微调模型。这是最终的代码片段,它还允许您定义一个好的提交消息和描述:

commit_message = "readme: add initial version of model card"
commit_description = "Hey,\n\nthis PR adds the initial version of model card."
create_pr = True

for model in model_infos:
    current_results_table = get_results_table(final_df, model_infos, model)
    card_data = ModelCardData()
    card = ModelCard.from_template(card_data, template_path="model_card_template.md",
                                   base_model=base_model,
                                   base_model_short=base_model_short,
                                   batch_sizes=f'[{", ".join([f"`{bs}`" for bs in batch_sizes ])}]',
                                   learning_rates=f'[{", ".join([f"`{lr}`" for lr in learning_rates ])}]',
                                   results=current_results_table,
                                   widget_text=widget_text.strip()
                                  )

    commit_url = card.push_to_hub(repo_id=model.model_id,
                                  create_pr=create_pr,
                                  commit_message=commit_message,
                                  commit_description=commit_description)
    
    print(commit_url + "\n")

一个示例 PR 可以在此处查看。

也可以将 `create_pr` 参数设置为 `False`。这意味着 PR 会在不经过审查的情况下自动合并!

等等,我的模型在哪里?

最初,模型仓库是使用 private=True 选项创建的。这意味着所有模型都尚未公开可见——但可以通过以下方式轻松将其设置为公开:

# Now make repositories publicly visible
for model in model_infos:
    print(f"Update visibility to True for repo https://huggingface.co/{model.model_id}")
    update_repo_visibility(repo_id=model.model_id, private=False)

模型卡展示

现在是时候展示上传的模型卡了!

模型卡头

image/png

TensorBoard 指标

image/png

推理小部件

image/png

结果部分

image/png

总结

在这篇博文中,我们展示了如何将 Flair 与 🤗 AutoTrain 库结合 SpaceRunner 功能,在德国 MobIE NER 数据集上进行基本超参数搜索,从而微调模型。

此外,我们还使用了 🤗 Hub 客户端库自动上传了美观且包含有用信息的模型卡。

附加资源

社区

注册登录以发表评论