ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Transformers Token 分类实战:基于 run_ner.py 微调 GermEval 2014 与 WNUT‘17 NER 模型

Transformers Token 分类实战:基于 run_ner.py 微调 GermEval 2014 与 WNUT‘17 NER 模型 推理引擎大模型【免费下载链接】FlexGenRunning large language models on a single GPU for throughput-oriented scenarios.项目地址https://gitcode.com/gh_mirrors/fl/FlexGen点击查看免费下载导读本文以 Hugging Face Transformers 遗留示例目录中的 token 分类实战指南为主体围绕run_ner.py脚本完整演示如何在两个经典命名实体识别NER数据集上完成数据下载、清洗、预处理、标签生成与模型微调德语 GermEval 2014 与英语 WNUT17Emerging and Rare Entities。读完本文你将掌握基于 CoNLL 格式数据的 token 分类微调全流程、命令行参数与 JSON 配置两种启动方式、PyTorch 与 TensorFlow 2 双版本训练以及 GermEval 特有的脏数据过滤与长句切分方案并可复用该流程到 Chunk组块分析、POS词性标注等同类 token 级任务。一、示例概览与文件结构本指南对应的完整示例位于仓库的examples/legacy/token-classification目录其核心文件与职责如下文件作用run_ner.pyPyTorch 版 NER 微调主脚本支持命令行参数与 JSON 配置文件两种方式run_tf_ner.pyTensorFlow 2 版 NER 微调主脚本utils_ner.py数据读取、特征InputFeatures转换、TokenClassificationDataset/TFTokenClassificationDataset数据集封装tasks.py任务类型定义NER、Chunk继承自 NER取倒数第二列标签、POSscripts/preprocess.py数据预处理脚本过滤空 token 行、按 max subtoken 长度切分长句run.shGermEval 2014 一键下载、预处理与训练脚本run_chunk.sh/run_pos.shCoNLL-2003 Chunk、UD POS 任务的示例脚本示例覆盖两个数据集GermEval 2014德语 NER标签规模远大于 CoNLL-2002/2003需要自定义labels.txtWNUT17英语 NER聚焦新兴与罕见实体识别难度显著高于传统 NER 基准。二、GermEval 2014德语 NER数据集微调2.1 数据下载与预处理GermEval 2014 数据需从共享任务页面获取原始数据格式包含四列制表符分隔预处理时只提取两列token 与外层 span 的 NER 标注。仓库run.sh中给出了对应的下载命令curl -L https://drive.google.com/uc?exportdownloadid1Jjhbal535VVz2ap4v4r_rN1UEHTdLK5P \ | grep -v ^# | cut -f 2,3 | tr \t train.txt.tmp curl -L https://drive.google.com/uc?exportdownloadid1ZfRcQThdtAR5PPRjIDtrVP7BtXSCUBbm \ | grep -v ^# | cut -f 2,3 | tr \t dev.txt.tmp curl -L https://drive.google.com/uc?exportdownloadid1u9mb7kNJHWQCWyweMDRMuTFoOHOfeBTH \ | grep -v ^# | cut -f 2,3 | tr \t test.txt.tmp其中grep -v ^#跳过以#开头的注释行cut -f 2,3只保留 token 与标注两列tr \t 将制表符统一为空格输出即为 CoNLL 风格的两列格式。为什么必须做预处理GermEval 2014 数据中含有奇怪的控制字符 token例如\x96、\u200e、\x95、\xad、\x80。BertTokenizer对这类 token 会返回空结果导致InputExample中词与标签错位。因此需要用preprocess.py完成两件事过滤空 token 行——若某个 token 经分词器切分后子词数量为 0直接跳过整行长句切分——当累计子词长度超过最大长度时插入空行把句子拆开保证每条样本都在 max_seq_length 之内。先定义预处理与训练所需的变量export MAX_LENGTH128 export BERT_MODELbert-base-multilingual-cased对 train、dev、test 三个数据文件依次执行预处理python3 scripts/preprocess.py train.txt.tmp $BERT_MODEL $MAX_LENGTH train.txt python3 scripts/preprocess.py dev.txt.tmp $BERT_MODEL $MAX_LENGTH dev.txt python3 scripts/preprocess.py test.txt.tmp $BERT_MODEL $MAX_LENGTH test.txt深入源码preprocess.py 的切分逻辑preprocess.py的核心逻辑非常简洁其三个命令行参数依次为数据集路径、模型名用于加载分词器与最大长度tokenizer AutoTokenizer.from_pretrained(model_name_or_path) max_len - tokenizer.num_special_tokens_to_add()关键点在于max_len - tokenizer.num_special_tokens_to_add()由于[CLS]、[SEP]等特殊 token 也会占用序列长度脚本把MAX_LENGTH预先扣除特殊 token 数量得到实际可容纳的子词上限。随后逐行读取数据current_subwords_len len(tokenizer.tokenize(token)) # Token contains strange control characters like \x96 or \x95 # Just filter out the complete line if current_subwords_len 0: continue if (subword_len_counter current_subwords_len) max_len: print() print(line) subword_len_counter current_subwords_len continue当累计子词数加上当前 token 的子词数超过上限时先输出一个空行分隔句子再输出当前行并重置计数器。这与utils_ner.py中convert_examples_to_features以空行划分句子的约定保持一致——空行是 CoNLL 格式的天然句子分隔符。2.2 生成自定义标签集GermEval 2014 的标签远多于 CoNLL-2002/2003后者仅O/B-XXX/I-XXX八种因此必须从数据中自动提取完整标签集cat train.txt dev.txt test.txt | cut -d -f 2 | grep -v ^$| sort | uniq labels.txt该命令取每行第二列标签、剔除空行、排序去重后写入labels.txt。若不给--labelstasks.py中的NER.get_labels会回退到 CoNLL-2003 默认标签集[O, B-MISC, I-MISC, B-PER, I-PER, B-ORG, I-ORG, B-LOC, I-LOC]并从文件加载的标签集中保证O位于列表首位。2.3 准备训练环境变量export OUTPUT_DIRgermeval-model export BATCH_SIZE32 export NUM_EPOCHS3 export SAVE_STEPS750 export SEED12.4 运行 PyTorch 版本训练python3 run_ner.py --data_dir ./ \ --labels ./labels.txt \ --model_name_or_path $BERT_MODEL \ --output_dir $OUTPUT_DIR \ --max_seq_length $MAX_LENGTH \ --num_train_epochs $NUM_EPOCHS \ --per_device_train_batch_size $BATCH_SIZE \ --save_steps $SAVE_STEPS \ --seed $SEED \ --do_train \ --do_eval \ --do_predict如果你的 GPU 支持半精度训练加上--fp16即可。训练结束后模型会在开发集与测试集上分别评估。注意仓库run.sh中使用的批大小参数名为--per_gpu_train_batch_size这是旧版TrainingArguments的参数名而本文档README与新版脚本使用--per_device_train_batch_size。若按当前run_ner.py基于HfArgumentParserTrainingArguments运行应以--per_device_train_batch_size为准。2.5 使用 JSON 配置文件除了命令行传参run_ner.py还支持从 JSON 文件读取全部参数。其实现位于run_ner.py当且仅当命令行只传入一个参数且以.json结尾时走parser.parse_json_file(json_file...)分支否则解析命令行参数。配置示例{ data_dir: ., labels: ./labels.txt, model_name_or_path: bert-base-multilingual-cased, output_dir: germeval-model, max_seq_length: 128, num_train_epochs: 3, per_device_train_batch_size: 32, save_steps: 750, seed: 1, do_train: true, do_eval: true, do_predict: true }文件必须以.json扩展名保存然后运行python3 run_ner.py config.json即可。2.6 PyTorch 版本评估结果开发集dev上的评估输出10/04/2019 00:42:06 - INFO - __main__ - ***** Eval results ***** 10/04/2019 00:42:06 - INFO - __main__ - f1 0.8623348017621146 10/04/2019 00:42:06 - INFO - __main__ - loss 0.07183869666975543 10/04/2019 00:42:06 - INFO - __main__ - precision 0.8467916366258111 10/04/2019 00:42:06 - INFO - __main__ - recall 0.8784592370979806测试集test上的评估输出10/04/2019 00:42:42 - INFO - __main__ - ***** Eval results ***** 10/04/2019 00:42:42 - INFO - __main__ - f1 0.8614389652384803 10/04/2019 00:42:42 - INFO - __main__ - loss 0.07064602487454782 10/04/2019 00:42:42 - INFO - __main__ - precision 0.8604651162790697 10/04/2019 00:42:42 - INFO - __main__ - recall 0.8624150210424085指标precision / recall / f1 / accuracy由seqeval库计算见run_ner.py的compute_metrics。2.7 运行 TensorFlow 2 版本训练TensorFlow 2 版本由run_tf_ner.py提供训练命令与 PyTorch 版几乎一致python3 run_tf_ner.py --data_dir ./ \ --labels ./labels.txt \ --model_name_or_path $BERT_MODEL \ --output_dir $OUTPUT_DIR \ --max_seq_length $MAX_LENGTH \ --num_train_epochs $NUM_EPOCHS \ --per_device_train_batch_size $BATCH_SIZE \ --save_steps $SAVE_STEPS \ --seed $SEED \ --do_train \ --do_eval \ --do_predict与 PyTorch 版本相同若 GPU 支持半精度训练加上--fp16即可。训练结束后同样会在开发集与测试集上评估。2.8 TensorFlow 2 版本评估结果开发集dev按标签细分的分类报告precision recall f1-score support LOCderiv 0.7619 0.6154 0.6809 52 PERpart 0.8724 0.8997 0.8858 4057 OTHpart 0.9360 0.9466 0.9413 711 ORGpart 0.7015 0.6989 0.7002 269 LOCpart 0.7668 0.8488 0.8057 496 LOC 0.8745 0.9191 0.8963 235 ORGderiv 0.7723 0.8571 0.8125 91 OTHderiv 0.4800 0.6667 0.5581 18 OTH 0.5789 0.6875 0.6286 16 PERderiv 0.5385 0.3889 0.4516 18 PER 0.5000 0.5000 0.5000 2 ORG 0.0000 0.0000 0.0000 3 micro avg 0.8574 0.8862 0.8715 5968 macro avg 0.8575 0.8862 0.8713 5968测试集test的分类报告precision recall f1-score support PERpart 0.8847 0.8944 0.8896 9397 OTHpart 0.9376 0.9353 0.9365 1639 ORGpart 0.7307 0.7044 0.7173 697 LOC 0.9133 0.9394 0.9262 561 LOCpart 0.8058 0.8157 0.8107 1150 ORG 0.0000 0.0000 0.0000 8 OTHderiv 0.5882 0.4762 0.5263 42 PERderiv 0.6571 0.5227 0.5823 44 OTH 0.4906 0.6667 0.5652 39 ORGderiv 0.7016 0.7791 0.7383 172 LOCderiv 0.8256 0.6514 0.7282 109 PER 0.0000 0.0000 0.0000 11 micro avg 0.8722 0.8774 0.8748 13869 macro avg 0.8712 0.8774 0.8740 13869值得注意的是表中LOC、ORG、PER等完整 span标签的支持数support很小如 dev 中ORG仅 3 条而PERpart、LOCpart这类部件级标签占绝大多数体现了 GermEval 2014 标注体系细粒度、类别不均衡的特点。三、Emerging and Rare EntitiesWNUT17英语 NER数据集3.1 任务背景WNUT17 共享任务聚焦于识别新兴讨论语境中不常见、前所未见的实体。官方任务描述指出命名实体是现代许多下游任务如事件聚类、摘要的基础但在含噪文本中对这些实体的召回率是真实难题——即使标注者之间也是如此。这种下降往往源于新出现的实体及其表面形式。该数据集提供六种标签任务难度显著高于传统 NER 基准这从后文的评估指标可以直观看出。3.2 数据下载与预处理创建数据目录并从官方数据仓库下载三个数据文件mkdir -p data_wnut_17 curl -L https://github.com/leondz/emerging_entities_17/raw/master/wnut17train.conll | tr \t data_wnut_17/train.txt.tmp curl -L https://github.com/leondz/emerging_entities_17/raw/master/emerging.dev.conll | tr \t data_wnut_17/dev.txt.tmp curl -L https://raw.githubusercontent.com/leondz/emerging_entities_17/master/emerging.test.annotated | tr \t data_wnut_17/test.txt.tmp此处只用tr \t 做制表符到空格的转换不需要像 GermEval 那样提取指定列数据本身就是两列格式。定义预处理变量——WNUT17 使用英文模型export MAX_LENGTH128 export BERT_MODELbert-large-cased这里选用英语 BERT large 模型进行微调。preprocess.py同样负责将过长句子按最大子词长度切分python3 scripts/preprocess.py data_wnut_17/train.txt.tmp $BERT_MODEL $MAX_LENGTH data_wnut_17/train.txt python3 scripts/preprocess.py data_wnut_17/dev.txt.tmp $BERT_MODEL $MAX_LENGTH data_wnut_17/dev.txt python3 scripts/preprocess.py data_wnut_17/test.txt.tmp $BERT_MODEL $MAX_LENGTH data_wnut_17/test.txt最后生成labels.txt逻辑与 GermEval 一致cat data_wnut_17/train.txt data_wnut_17/dev.txt data_wnut_17/test.txt | cut -d -f 2 | grep -v ^$| sort | uniq data_wnut_17/labels.txt3.3 使用 JSON 配置运行 PyTorch 版本WNUT17 示例采用 JSON 配置文件方式启动微调配置文件内容如下{ data_dir: ./data_wnut_17, labels: ./data_wnut_17/labels.txt, model_name_or_path: bert-large-cased, output_dir: wnut-17-model-1, max_seq_length: 128, num_train_epochs: 3, per_device_train_batch_size: 32, save_steps: 425, seed: 1, do_train: true, do_eval: true, do_predict: true, fp16: false }如果 GPU 支持半精度训练把fp16设为true。将配置保存为wnut_17.json后运行python3 run_ner_old.py wnut_17.json3.4 WNUT17 评估结果开发集dev评估输出05/29/2020 23:33:44 - INFO - __main__ - ***** Eval results ***** 05/29/2020 23:33:44 - INFO - __main__ - eval_loss 0.26505235286212275 05/29/2020 23:33:44 - INFO - __main__ - eval_precision 0.7008264462809918 05/29/2020 23:33:44 - INFO - __main__ - eval_recall 0.507177033492823 05/29/2020 23:33:44 - INFO - __main__ - eval_f1 0.5884802220680084 05/29/2020 23:33:44 - INFO - __main__ - epoch 3.0测试集test评估输出05/29/2020 23:33:44 - INFO - transformers.trainer - ***** Running Prediction ***** 05/29/2020 23:34:02 - INFO - __main__ - eval_loss 0.30948806500973547 05/29/2020 23:34:02 - INFO - __main__ - eval_precision 0.5840108401084011 05/29/2020 23:34:02 - INFO - __main__ - eval_recall 0.3994439295644115 05/29/2020 23:34:02 - INFO - __main__ - eval_f1 0.47440836543753434对比可见测试集上的 precision/recall/f1约 0.470.58明显低于开发集约 0.590.70说明 WNUT17 测试集中新兴、罕见实体的占比更高任务难度很大。四、源码机制深入run_ner.py 的完整执行链路理解了实操之后再回到源码层面看run_ner.py的关键设计可以让调参与排障事半功倍。4.1 参数解析与输出目录保护脚本用HfArgumentParser组合三类参数ModelArguments模型/分词器/配置名、task_type、use_fast、cache_dir、DataTrainingArgumentsdata_dir、labels、max_seq_length、overwrite_cache与TrainingArguments。训练前会检查output_dir是否已存在且非空若do_train为真且未指定--overwrite_output_dir直接抛出 ValueError 防止覆盖。4.2 任务类型动态分发task_type默认NER通过import_module(tasks)动态查找tasks.py中对应的TokenClassificationTask子类。除NER外还内置了Chunk与POSChunk(NER)将label_idx设为-2即取 CoNLL-2003 倒数第二列chunk 标注默认标签集为O加各类B-ADVP/I-ADVP等 21 种POS使用conllu库的parse_incr解析 UD 格式读取每 token 的词性标注。因此同一套run_ner.py配合--task_type即可复用于 chunking、POS 等任务run_chunk.sh即展示了--task_type Chunk的用法。4.3 标签对齐与 padding 标签Token 分类的关键在于子词与标签的对齐。utils_ner.py的convert_examples_to_features对每个词做tokenizer.tokenize(word)将词的首个子词赋予真实标签 id其余子词赋予pad_token_label_id。该值在 PyTorch 数据集中为nn.CrossEntropyLoss().ignore_index即 -100在 TF 数据集中为 -100从而保证只有真实标签参与损失计算label_ids.extend([label_map[label]] [pad_token_label_id] * (len(word_tokens) - 1))序列组装时遵循 BERT 约定[CLS] 词片 [SEP]对超出max_seq_length - special_tokens_count的部分截断再统一 padding 到max_seq_length见utils_ner.py。对于 XLNet 这类cls_token_at_end的模型[CLS]会放到序列末尾cls_token_segment_id取 2。数据集还通过FileLock将特征缓存到cached_{train,dev,test}_{TokenizerClass}_{max_seq_length}文件overwrite_cache可强制重建缓存。4.4 预测对齐与结果落盘评估与预测时align_predictions对每个位置取np.argmax并利用 -100 padding 标签过滤掉非真实位置得到与真实标签一一对应的预测序列。compute_metrics调用seqeval的accuracy_score / precision_score / recall_score / f1_score计算整体指标见run_ner.py。训练与评估的输出文件约定模型权重与 tokenizer 保存到output_dirtrainer.save_model()与tokenizer.save_pretrained()开发集指标写入output_dir/eval_results.txt测试集指标写入output_dir/test_results.txt逐 token 的预测结果由token_classification_task.write_predictions_to_file写回output_dir/test_predictions.txt保留原文件的行结构空行、-DOCSTART-标记便于直接比对。4.5 半精度训练与数据整理--fp16开启时DataCollatorWithPadding(tokenizer, pad_to_multiple_of8)会按 8 的倍数对齐序列长度以适配 fp16 运算的对齐要求同时日志会打印n_gpu、local_rank、fp16等信息分布式训练多卡/TPU通过_mp_fn与xla_spawn支持。五、可复用经验与注意事项脏数据清洗是 NER 微调的前置步骤GermEval 的不可见控制字符会让BertTokenizer返回空 token 并破坏词-标签对齐preprocess.py中len(tokenizer.tokenize(token)) 0的过滤逻辑可直接复用到任何含噪 CoNLL 数据。长句切分以子词为准而非词数preprocess.py用tokenizer.tokenize统计子词数量并预先扣除特殊 token保证切分后的句子一定能在max_seq_length内完成编码避免运行时截断导致的信息丢失。标签集必须与数据一致labels.txt由 train/dev/test 三份数据的标签列合并去重生成且get_labels会确保O排在首位换数据集时必须重新生成否则id2label映射错位会直接导致指标异常。参数入口有两种、写法需留意命令行参数与 JSON 配置等价批大小参数在旧版脚本为--per_gpu_train_batch_size当前run_ner.py基于新版TrainingArguments使用--per_device_train_batch_size。一脚本多任务通过--task_type切换NER/Chunk/POS再配合tasks.py自定义任务类同一套训练管线可覆盖绝大多数 token 级分类任务。WNUT17 难度提示由于数据集强调新兴与罕见实体测试集 F1 通常在 0.5 以下属于正常现象评估时应以 micro/macro F1 为准并留意稀有标签如ORG、PER完整 span的小样本支撑数。赞分享推理引擎大模型【免费下载链接】FlexGenRunning large language models on a single GPU for throughput-oriented scenarios.项目地址https://gitcode.com/gh_mirrors/fl/FlexGen点击查看免费下载相关推荐Nexa SDK实用指南一条命令本地跑AI模型NPU/GPU/CPU三种后端任选Nexa SDK实用指南一条命令本地跑AI模型NPU/GPU/CPU三种后端任选 想在设备上本地跑AI模型又不想折腾环境Nexa SDK 把模型下载、格人工智能大模型推理引擎本地部署多模态Transformers 视频分类实战指南基于 VideoMAE 微调与推理Transformers 视频分类实战指南基于 VideoMAE 微调与推理 导读 本文以 Hugging Face Transformers 仓库为核心完人工智能深度学习机器学习预训练微调NLP计算机视觉语音多模态BrewUI测试失败诊断截图自动记录机制全解BrewUI测试失败诊断截图自动记录机制全解 BrewUI 是 Homebrew 官方推出的 macOS GUI 应用它把 brew 命令行包管理变成了可视桌面应用开发工具上一篇算法可视化平台的用户获取渠道algorithm-visualizer推广效果分析下一篇苹果平方字体6种字重2种格式的跨平台中文显示解决方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表