在自然语言处理领域,文本分类是最基础也最广泛的应用场景之一。但当我们面对真实业务需求时,尤其是需要同时识别多个标签的多标签分类任务时,挑战会显著增加。本文将手把手带你构建一个针对生物科技新闻的多标签分类模型,使用当前最先进的DeBERTa模型作为基础,在包含31个类别、3140条标注数据的专业数据集上进行微调。
提示:多标签分类与传统的单标签分类不同,一个样本可能同时属于多个类别。例如一篇生物科技新闻可能同时涉及"监管批准"和"高管声明"两个标签。
DeBERTa(Decoding-enhanced BERT with disentangled attention)是微软研究院提出的Transformer模型改进版本,在多项NLP基准测试中表现优异。相比原始BERT模型,它具有三大优势:
在我们的生物科技新闻分类任务中,这些特性尤为重要——专业术语的准确理解、长文档中关键信息的定位,都需要模型具备强大的语义理解能力。
开始前,请确保已安装以下Python库:
bash复制pip install datasets transformers evaluate sentencepiece accelerate
各库的作用如下:
datasets: Hugging Face提供的数据集加载和处理库transformers: 包含DeBERTa等预训练模型的NLP库evaluate: 模型评估指标计算工具sentencepiece: DeBERTa使用的分词器依赖accelerate: 分布式训练支持库我们使用Knowledgator团队开源的生物科技事件分类数据集:
python复制from datasets import load_dataset
dataset = load_dataset('knowledgator/events_classification_biotech')
该数据集包含以下关键特征:
典型的标签包括:
首先需要将文本标签转换为模型可处理的数字形式:
python复制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的tokenizer处理文本数据:
python复制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)
预处理函数完成以下工作:
注意:多标签分类使用sigmoid激活函数而非softmax,因此标签向量中可以有多个1。
为提升训练效率,我们使用动态填充策略:
python复制from transformers import DataCollatorWithPadding
data_collator = DataCollatorWithPadding(tokenizer=tokenizer)
动态填充只在每个batch内填充到最长样本长度,而非整个数据集的最大长度,能显著减少显存占用。
多标签分类需要特殊设计的评估指标:
python复制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)
)
这里我们组合了四个关键指标:
加载DeBERTa模型并配置多标签分类任务:
python复制from transformers import AutoModelForSequenceClassification
model = AutoModelForSequenceClassification.from_pretrained(
model_path,
num_labels=len(classes),
id2label=id2class,
label2id=class2id,
problem_type="multi_label_classification"
)
关键参数说明:
num_labels: 标签类别总数problem_type: 明确指定为多标签分类id2label/label2id: 提供标签映射关系python复制from transformers import TrainingArguments, Trainer
training_args = TrainingArguments(
output_dir="biotech_classifier",
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()
训练关键设置:
训练完成后,可以使用pipeline进行预测:
python复制from transformers import pipeline
classifier = pipeline(
"text-classification",
model=model,
tokenizer=tokenizer,
device=0, # 使用GPU
function_to_apply='sigmoid',
top_k=None # 返回所有标签概率
)
text = "BioTech Inc. announced today that CEO John Smith will speak at the upcoming Healthcare Summit in New York."
results = classifier(text)
# 过滤出概率大于0.5的标签
predicted_labels = [
(id2class[int(item['label'].split('_')[-1])], item['score'])
for item in results[0]
if item['score'] > 0.5
]
批次大小调整:
学习率调度:
类别不平衡处理:
问题1:验证集指标波动大
问题2:模型过拟合
问题3:某些类别识别率低
虽然本教程使用生物科技新闻数据,但方法可迁移到其他领域:
为提升推理速度,可考虑:
python复制from transformers import AutoModelForSequenceClassification
quantized_model = AutoModelForSequenceClassification.from_pretrained(
"biotech_classifier",
torch_dtype=torch.float16 # 半精度量化
)
python复制from transformers import convert_graph_to_onnx
convert_graph_to_onnx.convert(
pipeline=classifier,
output_path="model.onnx",
opset=12
)
为持续提升模型性能,可建立主动学习循环:
我在实际项目中发现,这种迭代方法能显著减少标注工作量,通常经过3-4轮迭代后模型性能就能达到业务要求。
理解二者的区别至关重要:
| 特性 | 多类别分类 | 多标签分类 |
|---|---|---|
| 输出 | 单一类别 | 多个类别 |
| 激活函数 | softmax | sigmoid |
| 损失函数 | 交叉熵 | 二元交叉熵 |
| 评估指标 | 分类准确率 | 按样本/按标签的准确率 |
多标签分类需要为每个标签设置阈值,常见方法:
高级技巧:利用标签间相关性提升性能:
在实际生物科技新闻分类中,我们发现"监管批准"和"产品发布"标签间存在强相关性,利用这种先验知识可以提升3-5%的F1分数。
高质量标注数据是关键,建议:
生产环境部署后:
针对不同场景的资源选择:
| 场景 | 推荐配置 | 预估训练时间 |
|---|---|---|
| 实验阶段 | T4 GPU (16GB) | 2小时 |
| 生产微调 | A100 (40GB) | 30分钟 |
| CPU推理 | 8核CPU | 50ms/样本 |
对于长期运行的服务,建议使用Triton推理服务器实现高效模型部署和动态批处理。
通过本教程,我们系统性地构建了一个生物科技新闻多标签分类模型。从数据准备、模型选择到训练优化和部署考量,每个环节都有其独特挑战和解决方案。在实际业务场景中应用时,还需要考虑领域特异性、计算成本与性能的平衡等因素。