使用AutoNLP和Prodigy进行主动学习
使用AutoNLP和Prodigy的主动学习
机器学习中的主动学习是一个迭代过程,其中您会反复添加已标记的数据,重新训练模型并提供给最终用户。这是一个无穷无尽的过程,需要人类进行交互以进行标记/创建数据。在本文中,我们将讨论如何使用AutoNLP和Prodigy构建一个主动学习流水线。
AutoNLP
AutoNLP是由Hugging Face开发的一个框架,可以帮助您在自己的数据集上构建自己的最先进的深度学习模型,几乎不需要编码。 AutoNLP是建立在Hugging Face的transformers、datasets、inference-api和许多其他工具的基础上的。
使用AutoNLP,您可以在自己的自定义数据集上训练SOTA transformer模型,对它们进行微调(自动化)并提供给最终用户。所有使用AutoNLP训练的模型都是最先进的,可以直接投入生产。
在撰写本文时,AutoNLP支持二元分类、回归、多类分类、标记分类(如命名实体识别或词性标注)、问答、摘要等任务。您可以在这里找到所有支持的任务列表。AutoNLP支持英语、法语、德语、西班牙语、印地语、荷兰语、瑞典语等多种语言。还支持使用自定义的模型和自定义的分词器(如果AutoNLP不支持您的语言)。
Prodigy
Prodigy是由Explosion(spaCy的制造商)开发的一个注释工具。它是一个基于Web的工具,可以实时为数据进行注释。Prodigy支持诸如命名实体识别(NER)和文本分类等自然语言处理任务,但不仅限于自然语言处理!它还支持计算机视觉任务,甚至可以创建自己的任务!您可以在这里尝试Prodigy演示。
请注意,Prodigy是一款商业工具。您可以在这里了解更多信息。
我们选择Prodigy是因为它是最受欢迎的标记数据工具之一,而且可以进行无限定制。而且它的设置和使用也非常简单。
数据集
现在开始本文最有趣的部分。经过查看大量数据集和不同类型的问题,我们在Kaggle上找到了BBC新闻分类数据集。该数据集用于课堂竞赛,可以在这里访问。
让我们来看一下这个数据集:
正如我们所看到的,这是一个分类数据集。有一个Text
列,其中包含新闻文章的文本,还有一个Category
列,其中包含文章的类别。总共有5个不同的类别:business
,entertainment
,politics
,sport
和tech
。
使用AutoNLP在这个数据集上训练一个多类分类模型是小菜一碟。
步骤1:下载数据集。
步骤2:打开AutoNLP并创建一个新项目。
步骤3:上传训练数据集并选择自动切分。
步骤4:接受定价并训练您的模型。
请注意,在上面的示例中,我们正在训练15个不同的多类分类模型。AutoNLP的定价可以低至每个模型10美元。AutoNLP将为您选择最佳模型,并自动进行超参数调整。因此,现在,我们需要做的就是坐下来,放松一下,等待结果。
大约15分钟后,所有模型都训练完成,结果已经准备好了。最好的模型似乎获得了98.67%的准确率!
因此,我们现在能够以98.67%的准确率对数据集中的文章进行分类!但是等等,我们之前谈论的主动学习和Prodigy呢?它们发生了什么?🤔我们确实使用了Prodigy,很快就会看到。我们使用它为命名实体识别任务对该数据集进行了标注。在开始标注部分之前,我们认为在一个项目中不仅能够检测新闻文章中的实体,还可以对其进行分类是很酷的。这就是为什么我们在现有标签上构建了这个分类模型。
主动学习
我们使用的数据集有类别,但没有实体识别的标签。因此,我们决定使用 Prodigy 为另一个任务(命名实体识别)标记数据集。
一旦您安装了 Prodigy,您可以简单地运行以下命令:
$ prodigy ner.manual bbc blank:en BBC_News_Train.csv --label PERSON,ORG,PRODUCT,LOCATION
让我们看看不同的值:
bbc
是由 Prodigy 创建的数据集。blank:en
是使用的spaCy
分词器。BBC_News_Train.csv
是用于标记的数据集。PERSON,ORG,PRODUCT,LOCATION
是用于标记的标签列表。
运行以上命令后,您可以转到 Prodigy Web 界面(通常位于 localhost:8080)并开始标记数据集。Prodigy 界面非常简单、直观且易于使用。界面如下所示:
您只需选择要标记的实体(PERSON、ORG、PRODUCT、LOCATION),然后选择属于该实体的文本。完成一个文档后,您可以点击绿色按钮,Prodigy 将自动为您提供下一个未标记的文档。
使用 Prodigy,我们开始标记数据集。当我们有大约20个样本时,我们使用 AutoNLP 训练了一个模型。Prodigy 不以 AutoNLP 格式导出数据,因此我们编写了一个快速简单的脚本将数据转换为 AutoNLP 格式:
import json
import spacy
from prodigy.components.db import connect
db = connect()
prodigy_annotations = db.get_dataset("bbc")
examples = ((eg["text"], eg) for eg in prodigy_annotations)
nlp = spacy.blank("en")
dataset = []
for doc, eg in nlp.pipe(examples, as_tuples=True):
try:
doc.ents = [doc.char_span(s["start"], s["end"], s["label"]) for s in eg["spans"]]
iob_tags = [f"{t.ent_iob_}-{t.ent_type_}" if t.ent_iob_ else "O" for t in doc]
iob_tags = [t.strip("-") for t in iob_tags]
tokens = [str(t) for t in doc]
temp_data = {
"tokens": tokens,
"tags": iob_tags
}
dataset.append(temp_data)
except:
pass
with open('data.jsonl', 'w') as outfile:
for entry in dataset:
json.dump(entry, outfile)
outfile.write('\n')
这将为我们提供一个可以用于使用 AutoNLP 训练模型的 JSONL
文件。步骤与之前相同,只是在创建 AutoNLP 项目时选择 Token Classification
任务。使用我们最初的数据,我们使用 AutoNLP 训练了一个模型。最好的模型在准确率方面达到了约86%,但精确度和召回率均为0。我们知道模型没有学到任何东西。很明显,我们只有大约20个样本。
在标记了大约70个样本后,我们开始获得一些结果。准确率提高到92%,精确度为0.52,召回率约为0.42。我们开始得到一些结果,但仍然不令人满意。在下面的图片中,我们可以看到该模型在一个未见过的样本上的表现。
如您所见,模型在努力中。但比以前好多了!以前,模型甚至无法预测相同文本中的任何内容。至少现在,它能够确定 Bruce
和 David
是名字。
因此,我们继续标记了一些样本。
请注意,每次迭代中,我们的数据集都会变得更大。我们所做的只是将新数据集上传到 AutoNLP,然后让它完成剩下的工作。
在标记了大约150个样本之后,我们开始得到了一些不错的结果。准确率提高到了95.7%,精确度为0.64,召回率约为0.76。
让我们来看看这个模型在同样的未知样本上的表现。
哇!这太神奇了!正如你所看到的,模型现在表现得非常好!它能够在同一段文本中检测到许多实体。精确度和召回率仍然有点低,因此我们继续标注更多的数据。在标注了大约250个样本之后,我们在精确度和召回率方面获得了最佳结果。准确率提高到了约95.9%,精确度和召回率分别为0.73和0.79。在这一点上,我们决定停止标注并结束实验过程。下面的图表显示了随着我们向数据集中添加更多样本,最佳模型的准确性如何提高:
嗯,众所周知,更相关的数据将导致更好的模型,从而获得更好的结果。通过这次实验,我们成功地创建了一个不仅可以对新闻文章中的实体进行分类,还可以对其进行分类的模型。使用像Prodigy和AutoNLP这样的工具,我们只需要投入时间和精力来标注数据集(即使这也由Prodigy提供的界面使其更简单)。AutoNLP为我们节省了大量的时间和精力:我们不需要弄清楚要使用哪些模型,如何训练它们,如何评估它们,如何调整参数,使用哪个优化器和调度器,预处理,后处理等等。我们只需要标注数据集,然后让AutoNLP处理其他所有事情。
我们相信,借助AutoNLP和Prodigy等工具,创建数据和最先进的模型非常容易。而且,由于整个过程几乎不需要编码,即使没有编码背景的人也可以创建一般公众无法获得的数据集,使用AutoNLP训练自己的模型,并与社区中的其他人分享模型(或仅用于他们自己的研究/业务)。
我们已经通过这个过程开源了最佳模型。你可以在这里尝试它。标记的数据集也可以在这里下载。
模型之所以是最先进的,是因为它们所训练的数据。