从零开始构建多标签分类模型:分步教程

社区文章 发布于2024年1月8日

教程摘要

本教程将指导您完成创建高效的多标签文本分类机器学习模型的每一步。我们将使用DeBERTa作为基础模型,它目前是编码器模型的最佳选择,并根据我们的数据集进行微调。该数据集包含3140个生物技术行业重要商业事件的精心验证训练样本。尽管这是一个特定主题,但该数据集具有普遍性,对于各种商业数据分类任务都非常有益。我们的团队开源了该数据集,旨在超越现有基准的局限性,这些基准更偏重学术而非实践。通过本教程,您将获得一个可操作的模型,其性能超越该领域大多数流行解决方案。

问题

文本分类是自然语言处理(NLP)中最广泛需要的任务。尽管其表述简单,但对于大多数实际业务用例而言,它是一个复杂的任务,需要专业知识才能同时收集高质量数据集并训练性能良好且准确的模型。多标签分类甚至更为复杂和棘手。这个研究领域在机器学习社区中明显不足,公开数据集过于简单,无法训练出可操作的模型。此外,工程师们经常对情感分析和其他相对简单的任务模型进行基准测试,这些任务并不能代表模型的实际问题解决能力。在这篇博客中,我们将在我们团队收集的开源数据集上训练一个多标签分类模型,以证明每个人都可以开发出更好的解决方案。

要求:

在开始项目之前,请确保您已安装以下软件包:

!pip install datasets transformers evaluate sentencepiece accelerate
  1. Datasets:是一个强大的工具,它提供统一且易于使用的界面,用于访问和处理自然语言处理研究和应用中常用的各种数据集。
  2. Transformers:用于处理自然语言处理中预训练模型的库,它提供了大量最先进的模型,用于文本生成、翻译、情感分析等任务。
  3. Evaluate:一个用于轻松评估机器学习模型和数据集的库。
  4. Sentencepiece:一种无监督文本分词器和反分词器,主要用于基于神经网络的文本生成系统,其中词汇量在神经网络模型训练之前已预先确定。
  5. Accelerate:一个提供分布式训练高级接口的库,使研究人员和实践者更容易在多个 GPU 或机器上扩展其深度学习工作流程。

数据集

最近,我们开源了一个专门为生物技术新闻领域量身定制的数据集,旨在超越现有基准的局限性。该数据集富含复杂内容,包含数千篇涵盖各种重要商业事件的生物技术新闻文章,从而为信息提取挑战提供了更细致的视角。

数据集包含31个类别,其中包括一个“无”类别,以涵盖各种事件和信息类型,例如事件组织、高管声明、监管批准、招聘公告等。

关键方面

  • 事件提取;
  • 多类别分类;
  • 生物技术新闻领域;
  • 31个类别;
  • 总共3140个示例;

标签

  • 事件组织 - 组织或参与会议、展览等活动。
  • 高管声明 - 公司高管的声明或引语。
  • 监管批准 - 产品、服务、试验等获得监管机构批准。
  • 招聘 - 公布公司新聘用或任命。
  • 基金会 - 成立新的慈善基金会。
  • 关闭 - 关闭设施/办公室/部门或停止某项计划。
  • 合作与联盟 - 与其他公司建立合作关系或战略联盟。
  • 行业扩张 - 扩展到新的行业或市场。
  • 新倡议或计划 - 宣布新的倡议、计划或活动。
  • 并购 - 合并、收购或剥离。

以及另外21个!

在我们的文章中查看有关数据集的更多详细信息。

指南

首先,让我们初始化数据集并对类别进行预处理

from datasets import load_dataset
    
dataset = load_dataset('knowledgator/events_classification_biotech') 
    
classes = [class_ for class_ in dataset['train'].features['label 1'].names if class_]
class2id = {class_:id for id, class_ in enumerate(classes)}
id2class = {id:class_ for class_, id in class2id.items()}

之后,我们对数据集进行分词,并为多标签分类处理标签。首先,我们将初始化分词器。在本教程中,我们将使用 DeBERTa 模型,它目前是编码器模型中的最佳选择。

from transformers import AutoTokenizer

model_path = 'microsoft/deberta-v3-small'

tokenizer = AutoTokenizer.from_pretrained(model_path)

然后,我们对数据集进行标记化并处理标签以进行多标签分类

def preprocess_function(example):
   text = f"{example['title']}.\n{example['content']}"
   all_labels = example['all_labels'].split(', ')
   labels = [0. for i in range(len(classes))]
   for label in all_labels:
       label_id = class2id[label]
       labels[label_id] = 1.
  
   example = tokenizer(text, truncation=True)
   example['labels'] = labels
   return example

tokenized_dataset = dataset.map(preprocess_function)

之后,我们初始化 DataCollatorWithPadding。在整理过程中,将批次中的句子动态填充到最长长度,比将整个数据集填充到最大长度更有效。

from transformers import DataCollatorWithPadding

data_collator = DataCollatorWithPadding(tokenizer=tokenizer)

在训练期间实现指标对于监控模型性能随时间变化非常有帮助。它可以帮助避免过拟合并构建更通用的模型。

import evaluate
import numpy as np

clf_metrics = evaluate.combine(["accuracy", "f1", "precision", "recall"])

def sigmoid(x):
   return 1/(1 + np.exp(-x))

def compute_metrics(eval_pred):

   predictions, labels = eval_pred
   predictions = sigmoid(predictions)
   predictions = (predictions > 0.5).astype(int).reshape(-1)
   return clf_metrics.compute(predictions=predictions, references=labels.astype(int).reshape(-1))
references=labels.astype(int).reshape(-1))

让我们初始化我们的模型,并传入所有关于分类任务的必要细节,例如标签数量、类别名称及其 ID,以及分类类型。

from transformers import AutoModelForSequenceClassification, TrainingArguments, Trainer

model = AutoModelForSequenceClassification.from_pretrained(

   model_path, num_labels=len(classes),
           id2label=id2class, label2id=class2id,
                       problem_type = "multi_label_classification"

接下来,我们必须配置训练参数,然后就可以开始训练过程了。

training_args = TrainingArguments(

   output_dir="my_awesome_model",
   learning_rate=2e-5,
   per_device_train_batch_size=3,
   per_device_eval_batch_size=3,
   num_train_epochs=2,
   weight_decay=0.01,
   evaluation_strategy="epoch",
   save_strategy="epoch",
   load_best_model_at_end=True,
)

trainer = Trainer(

   model=model,
   args=training_args,
   train_dataset=tokenized_dataset["train"],
   eval_dataset=tokenized_dataset["test"],
   tokenizer=tokenizer,	`
   data_collator=data_collator,
   compute_metrics=compute_metrics,
)

trainer.train()

如果您仔细遵循了本指南的每个步骤,您现在就拥有了一个高效的工具。训练过程简单,并产生了显著的结果。我们完全使用开源解决方案构建了它,并取得了出色的成果。

如果您对如何进一步简化流程和提高结果有任何疑问或建议,请随时留言!

或者加入Discord 社区,我们会在那里与大家积极交流!

结论

在本文中,我们演示了如何使用 Transformers 和 Datasets 从头开始构建一个多标签文本分类器。我们利用了 DeBERTa 编码器模型,并在包含 31 个标签的自定义生物技术新闻数据集上对其进行了微调。在对文本进行分词并对多热标签进行编码后,我们设置了训练循环,并附带了有用的指标进行监控。该模型现在能够准确地将生物技术新闻文章分类到多个相关类别中。这种端到端的工作流程展示了如何准备新的数据集并将其馈送到 DeBERTa 等强大的预训练模型中,从而为实际应用创建定制且功能强大的文本分类器。现在,您可以添加更多数据和标签,根据您的具体要求训练模型,并实现您的专业目标。我们很乐意为您的研发工作提供帮助!

常见问题

  1. 什么是零样本学习?
    零样本学习指的是机器学习模型识别和分类其在训练期间从未见过的数据的能力。在此背景下,“零样本”意味着模型能够对任务或类别进行正确预测,而无需对其进行明确的训练。这通过利用在不同但相关任务或类别上训练期间获得的知识来实现。模型利用这些学习到的信息来推断和泛化到新的、未见的情况。在本文的背景下,您的机器学习模型将能够处理除了它经过微调的31个类别之外的新标签。例如,它可能会识别“购买房产”或“新咨询委员会成员”类别。
  2. 什么是模型微调?
    机器学习中的微调是一个过程,其中预训练模型(已在大型数据集上训练过的模型)会使用更小的特定数据集进行进一步训练或调整。此过程有助于模型专门化并更好地执行与新数据集相关的任务。微调本质上是定制一个通用模型,使其更符合特定需求或数据集。在我们的示例中,DeBerta 是一个预训练模型,它在大规模文本语料库上进行了训练,并进一步在生物技术新闻数据集上进行了微调,以便能够以更高的准确性执行特定任务。
  3. 什么是多标签分类?
    多标签分类是一种机器学习问题,其中每个实例(如图像、文本等)可以同时属于多个类别或类别,就像我们的示例一样。与二元或多类别分类不同,多标签分类中,一个实例只被分配到一个类别,而在多标签分类中,它可以同时与多个不同的标签或类别相关联。这种方法在需要将要分类的项目自然地归入多个类别的场景中很有用。例如,一篇新闻文章可能同时与“体育”和“经济”相关。

社区

它需要任何标签平衡技术吗?

在指标评估的代码块中有一个错别字。
references=labels.astype(int).reshape(-1)) 部分重复了两次。

在 AutoModelForSequenceClassification.from_pretrained 之后也缺少一个 ')',并且 Trainer 中有一个多余的 '。

真的有人测试过这些例子吗?

在“process_function”函数中,该行应直接使用 all_labels(删除 split)或使用 all_labels_cat
正确:all_labels = example['all_labels']all_labels = example['all_labels_concat'].split(', ')
错误:all_labels = example['all_labels'].split(', ')

注册登录 以发表评论