HuggingFace课程笔记:使用BERT进行Token分类任务详解
course The Hugging Face course on Transformers 项目地址: https://gitcode.com/gh_mirrors/cou/course
什么是Token分类任务
Token分类是自然语言处理中的一项基础任务,它要求模型为输入文本中的每个token分配一个类别标签。这类任务在实际应用中非常广泛,主要包括以下几种典型场景:
- 命名实体识别(NER):识别文本中的人名、地名、组织机构名等实体
- 词性标注(POS):标注每个词的语法类别(名词、动词、形容词等)
- 组块分析(Chunking):识别文本中的短语组块
这些任务虽然具体目标不同,但都可以抽象为"为每个token分配标签"的问题框架。本文将基于HuggingFace课程内容,详细介绍如何使用BERT模型在NER任务上进行微调。
数据集准备:CoNLL-2003
我们使用经典的CoNLL-2003数据集,它包含新闻文本,已经标注了命名实体标签。数据集的特点包括:
- 文本以单词列表形式提供(已预分词)
- 包含三种标注:NER、POS和组块分析
- 训练集14,041条,验证集3,250条,测试集3,453条
NER标签采用BIO标注方案:
O
:非实体词B-PER
/I-PER
:人名开始/内部B-ORG
/I-ORG
:组织名开始/内部B-LOC
/I-LOC
:地名开始/内部B-MISC
/I-MISC
:其他实体开始/内部
数据处理关键步骤
1. Tokenizer的特殊处理
由于数据集已经预分词,我们需要特别注意:
- 使用
is_split_into_words=True
参数告诉tokenizer输入已分词 - 处理子词分词带来的标签对齐问题
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("bert-base-cased")
inputs = tokenizer(raw_datasets["train"][0]["tokens"], is_split_into_words=True)
2. 标签对齐策略
当单词被分成子词时,我们需要调整标签:
- 特殊token([CLS]、[SEP])标记为-100(损失计算时忽略)
- 子词继承原单词的标签
- 对于B-开头的内部子词,改为I-前缀
def align_labels_with_tokens(labels, word_ids):
new_labels = []
current_word = None
for word_id in word_ids:
if word_id != current_word:
current_word = word_id
label = -100 if word_id is None else labels[word_id]
new_labels.append(label)
elif word_id is None:
new_labels.append(-100)
else:
label = labels[word_id]
if label % 2 == 1: # B-标签转为I-
label += 1
new_labels.append(label)
return new_labels
3. 批量处理数据集
使用Dataset.map()方法高效处理整个数据集:
def tokenize_and_align_labels(examples):
tokenized_inputs = tokenizer(
examples["tokens"], truncation=True, is_split_into_words=True
)
all_labels = examples["ner_tags"]
new_labels = []
for i, labels in enumerate(all_labels):
word_ids = tokenized_inputs.word_ids(i)
new_labels.append(align_labels_with_tokens(labels, word_ids))
tokenized_inputs["labels"] = new_labels
return tokenized_inputs
tokenized_datasets = raw_datasets.map(
tokenize_and_align_labels,
batched=True,
remove_columns=raw_datasets["train"].column_names,
)
模型训练准备
数据收集器(Data Collator)
不同于普通任务,我们需要专门的数据收集器来处理标签填充:
from transformers import DataCollatorForTokenClassification
data_collator = DataCollatorForTokenClassification(tokenizer=tokenizer)
该收集器会:
- 动态填充每个batch到最长序列长度
- 对标签进行与输入相同的填充处理(使用-100)
训练技巧与注意事项
- 评估指标:通常使用精确率、召回率和F1值,特别是对实体级别的评估
- 长序列处理:注意模型的最大长度限制(BERT通常为512)
- 类别不平衡:实体词远少于普通词,可能需要调整损失权重
- 子词影响:长实体被切分为多个子词可能影响识别效果
总结
本文详细介绍了使用HuggingFace生态系统进行Token分类任务的全流程,重点解决了预分词数据与子词tokenizer的兼容性问题。通过合理的标签对齐策略和专门的数据处理工具,我们可以有效利用预训练模型如BERT来解决NER等序列标注任务。这种方法不仅适用于CoNLL-2003数据集,也可以方便地迁移到其他自定义的Token分类任务中。
course The Hugging Face course on Transformers 项目地址: https://gitcode.com/gh_mirrors/cou/course
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考