使用 🤗 AutoTrain SpaceRunner 对 NER 数据集上的 Flair 模型进行微调
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 论文)
使用 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_model
和 widget_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)
模型卡展示
现在是时候展示上传的模型卡了!
模型卡头
TensorBoard 指标
推理小部件
结果部分
总结
在这篇博文中,我们展示了如何将 Flair 与 🤗 AutoTrain 库结合 SpaceRunner 功能,在德国 MobIE NER 数据集上进行基本超参数搜索,从而微调模型。
此外,我们还使用了 🤗 Hub 客户端库自动上传了美观且包含有用信息的模型卡。
附加资源
autotrain-flair-mobie
仓库,包含所有代码- 微调模型的集合
- 🤗 AutoTrain 库
- @abhishek 的 SpaceRunner 功能
- 🤗 Hub 客户端库文档