AdaLM 领域自适应实战:增量 BPE 词表扩展与下游任务微调

AdaLM 领域自适应实战:增量 BPE 词表扩展与下游任务微调 AdaLM 领域自适应实战增量 BPE 词表扩展与下游任务微调【免费下载链接】unilmLarge-scale Self-supervised Pre-training Across Tasks, Languages, and Modalities项目地址: https://gitcode.com/GitHub_Trending/un/unilm本指南围绕 unilm 仓库中的 AdaLM 模块展开系统讲解Adapt-and-Distill适应与蒸馏方法如何在领域Domain、语言Language与任务Task三个维度上对预训练语言模型进行自适应。你将掌握两条核心实操链路一是使用增量算法为特定领域如生物医学、计算机科学自动扩展 BERT 词表incr_bpe二是基于扩展后的领域词表与模型 checkpoint在分类任务与 NER 任务上完成端到端微调finetune并复现论文报告的 Biomedical / Computer Science 基准成绩。一、背景为什么需要适应 蒸馏通用预训练模型如 BERT在海量通用语料上学习到的是通识能力但在生物医学、计算机科学等专业领域文本中充满领域专属术语如化学物质名、基因名、论文结构实体而这些词在通用词表中往往被切碎成多个 subword 甚至退化为[UNK]导致下游任务效果受损。AdaLM 对应的论文为Adapt-and-Distill: Developing Small, Fast and Effective Pretrained Language Models for DomainsYunzhi Yao, Shaohan Huang, Wenhui Wang, Li Dong, Furu WeiACL 2021核心思路是Adapt适应在领域语料上对通用预训练模型做自适应其中关键一步是用增量 BPE 算法为领域扩展词表让领域术语成为完整 tokenDistill蒸馏把领域自适应后的模型蒸馏成Small 版本更小的层数与隐藏维度获得小而快且有效的领域模型。本仓库提供了该流程的两部分工程实现生成领域增量词表的 incr_bpe以及在领域模型上做下游任务微调的 finetune。二、发布的自适应领域预训练模型仓库 AdaLM README 发布了四个领域自适应模型 checkpoint均基于 BERT 架构可直接用于下游微调模型层数隐藏维度头数参数量AdaLM-bio-base1276812132MAdaLM-bio-small63841234MAdaLM-cs-base1276812124MAdaLM-cs-small63841230M其中bio对应生物医学领域cs对应计算机科学领域base为原始体量模型small为蒸馏压缩后的模型。这些 checkpoint 是本文后续微调示例中CKPT_PATH的直接输入。三、增量 BPE 词表扩展incr_bpe领域自适应模型与通用 BERT 的一个关键区别在于词表不能直接用原始 BERT 词表而需要按论文中的增量算法把领域高频词补进词表。该模块位于 adalm/incr_bpe是对 tensor2tensor 的text_encoder_build_subword.py及其依赖的简化改造使其输出格式兼容 Google Research 开源的 BERT 项目即每行一个 token、BPE 子词以##前缀标记。3.1 环境要求根据 incr_bpe/README.md该模块开发环境为Python 3.6TensorFlow 1.11代码依赖transformers用于BertTokenizer见 vocab_extend.py与tensorflowtf.flags见 subword_builder.py实际运行时请以仓库源码中的 import 为准安装对应版本。3.2 方式一按论文增量算法自动确定词表大小推荐论文的增量算法不要求你预先指定最终词表大小而是以领域语言模型困惑度提升是否还有收益为准则自动寻找合适的扩展规模。入口脚本为 vocab_extend.pypython vocab_extend.py \ --corpus {file for the domain corpus} \ --raw_vocab {bert_raw_vocab_file} \ --output_file {the output file of the final vocabulary} \ --interval {vocab size interval} \ --threshold {threshold for P(D)} # 使用仓库自带的样例数据 python vocab_extend.py --corpus test_data/chem.txt \ --raw_vocab test_data/vocab.txt \ --output_file test_data/chem.vocab \ --interval 1000 --threshold 1参数说明依据 vocab_extend.py 的参数解析参数含义说明--corpus领域语料文件必填用于统计 token 频次与评估语言模型--raw_vocab原始 BERT 词表文件必填新词表以它为基础进行扩展--output_file最终词表输出路径必填输出兼容 BERT 格式--interval词表大小步长默认10000函数默认值见 vocab_extend.py样例中设为1000以获得更细粒度搜索--thresholdP(D) 提升的停止阈值README 示例为1函数签名默认0.01vocab_extend.py而 argparse 默认值为10000使用时建议显式传入算法核心流程对应 vocab_extend.py逐行读取语料过滤长度小于 5 的短行用 tokenizer.corpus_token_counts 统计领域语料的 token 频次corpus_max_lines4400000、split_on_newlinesTrue、do_lower_caseTrue读取原始 BERT 词表作为reserved_tokens这些 token 会被强制保留在新词表中保证原有 embedding 索引不被打乱用BertTokenizer对领域语料计算初始语言模型得分pre_lmcompute_language_model中按 token 概率的对数和取平均见 vocab_extend.py进入循环词表目标大小target_size每次增加interval调用build_target_size_vocab构建新词表重算语言模型得分当相对提升delta (pre_lm - now_lm) / pre_lm不超过threshold时停止停止后通过merge_output_file_with_bert_vocab把新扩展 token追加到原始 BERT 词表末尾生成最终词表见 vocab_extend.py。这套流程的实质是以领域语言模型困惑度作为词表收益的度量用逐步扩张 收益递减判断自动确定词表规模避免盲目堆词表大小。3.3 方式二直接指定词表大小如果你已明确需要的最终词表大小可以使用 subword_builder.pypython subword_builder.py \ --corpus_filepattern {corpus_for_vocab} \ --raw_vocab {bert_raw_vocab_file} \ --output_filename {name_of_vocab} \ --vocab_size {final vocab size} \ --do_lower_case该脚本基于 TensorFlow flagssubword_builder.py支持的主要参数参数默认值含义--output_filename/tmp/my.subword_text_encoder输出词表路径--corpus_filepattern空领域语料支持通配符--vocab_filepattern空已有 token-count 格式词表与 corpus 二选一--min_count5子词在语料中的最小频次--vocab_size30000期望的最终词表大小会产出接近该值的词表--corpus_max_linesNone最多读取语料行数--num_iterations5迭代轮数--split_on_newlinesTrue是否按行切分语料--additional_chars额外视为字母的特殊字符--max_subtoken_lengthNone子词最大长度--raw_vocabNone原始 BERT 词表提供后作为保留 token--do_lower_caseFalse是否对语料小写化脚本校验了两个硬性条件见 subword_builder.pyvocab_size必须大于原始 BERT 词表大小且必须小于语料 token 种类数否则直接报错。构建完成后同样调用merge_output_file_with_bert_vocab将新子词合并进原始词表。3.4 底层原理SubwordTextEncoder 与可逆分词器两个脚本都依赖 text_encoder.py 中的SubwordTextEncoder源自 tensor2tensorbuild_to_target_size通过递归二分查找最小 token 频次阈值使最终词表大小逼近目标值误差 1% 以内即视为可接受见 text_encoder.pybuild_from_token_counts迭代地进行切分 → 统计子串频次 → 保留高频候选 → 重组词表候选子词按频次降序排列并显式纳入字母表保证任何 token 均可编码见 text_encoder.pyBERT 兼容性改造构建完成后把以_开头的子词去掉下划线其余词首子词加##前缀new_subtoken_strings[idx] ## subtoken见 text_encoder.py从而输出与 BERT 完全一致的词表格式可逆分词器tokenizer.py负责将语料切分为 token 并统计频次保证编码可逆、标点与字母数字分离。仓库还提供了样例数据供快速验证领域语料 test_data/chem.txt生物医学文献句子与原始词表 test_data/vocab.txt30522 行的 BERT 风格词表含[PAD]、[unused0-99]等保留 token。四、下游任务微调finetune获得领域自适应模型与扩展词表后即可按原文档示例在分类与NER命名实体识别两类下游任务上微调。微调代码基于 HuggingFacetransformers仓库锁定的版本为transformers 2.10.0见 requirements.txt因此模型、配置、词表三者按model_name_or_path / config_name / tokenizer_name分离传入。4.1 环境准备# 1) 安装依赖 pip install -r requirements.txt # 2) 将项目根目录加入 PYTHONPATH脚本内部以包方式 import nlu_finetune / utils_ner export PYTHONPATH$PYTHONPATH:pwdrequirements.txt 中除transformers2.10.0外还包含numpy、boto3、requests、tqdm、regex、sacremoses、tensorboardX、scipy、seqeval、sklearn、urllib31.26.5其中seqeval用于 NER 任务的精确率/召回率/F1 计算见 run_ner.py。4.2 下游数据集生物医学任务JNLPBA、PICO、ChemProt 等可从 BLURB Leaderboard 下载计算机科学任务ACL-ARC、SCIERC 等来自 Dont Stop Pretrainingallenai相关工作发布的数据。两类数据集均按任务格式组织训练集与开发集供下方脚本的data_dir使用。4.3 微调分类任务run_classifier.py原文档给出的完整示例基于 run_classifier.py底层为BertForSequenceClassification# Set path to read training/dev dataset export DATASET_PATH/path/to/read/glue/task/data/ # Example: /path/to/downloaded-glue-data-dir/mnli/ # Set path to save the finetuned model and result score export OUTPUT_PATH/path/to/save/result_of_finetuning export TASK_NAMEchemprot # Set path to the model checkpoint you need to test export CKPT_PATH/path/to/your/model/checkpoint # Set config file export CONFIG_FILE/path/to/config/file # Set vocab file export VOCAB_FILE/path/to/vocab/file # Set path to cache train dev features (tokenized, only use for this tokenizer!) export TRAIN_CACHE${DATASET_PATH}/$TASK_NAME.bert.cache export DEV_CACHE${DATASET_PATH}/$TASK_NAME.bert.cache # Setting the hyperparameters for the run. export BSZ32 export LR1.5e-5 export EPOCH30 export WD0.1 export WM0.1 CUDA_VISIBLE_DEVICES0 python finetune/run_classifier.py \ --model_type bert --model_name_or_path $CKPT_PATH \ --config_name $CONFIG_FILE --tokenizer_name $VOCAB_FILE --do_lower_case\ --data_dir $DATASET_PATH --cached_train_file $TRAIN_CACHE --cached_dev_file $DEV_CACHE \ --do_train --do_eval --logging_steps 1000 --output_dir $OUTPUT_PATH --max_grad_norm 0 \ --max_seq_length 128 --per_gpu_train_batch_size $BSZ --learning_rate $LR \ --num_train_epochs $EPOCH --weight_decay $WD --warmup_ratio $WM \ --fp16 --fp16_opt_level O2 --seed 42 --overwrite_output_dir关键配置说明--model_type bertrun_classifier.py的MODEL_CLASSES还支持xlnet / xlm / roberta / distilbert / albert / xlm-roberta见 run_classifier.py但 AdaLM 发布模型均为 BERT 结构此处应使用bert三件套分离--model_name_or_path指向 checkpoint含pytorch_model.bin--config_name指向bert_config.json--tokenizer_name指向扩展后的词表文件--do_lower_case须与增量词表构建时do_lower_caseTrue保持一致--cached_train_file / --cached_dev_filetokenize 后的特征缓存路径原文档特别注明仅对该 tokenizer 有效——若更换词表必须重新生成缓存否则 token id 错位会导致训练失效优化器配置AdamW采用weight_decay分组bias 与 LayerNorm 不衰减学习率调度为get_linear_schedule_with_warmup其中 warmup 步数由warmup_steps t_total * args.warmup_ratio计算见 run_classifier.py因此示例中WM0.1表示前 10% 的训练步数线性预热--fp16 --fp16_opt_level O2启用 NVIDIA APEX 混合精度训练O2 优化级别需先安装 apex--max_grad_norm 0关闭梯度裁剪--seed 42固定随机种子保证可复现set_seed同时设置 python / numpy / torch / cuda 随机源见 run_classifier.py。4.4 微调 NER 任务run_ner.py / run_pico.pyNER 任务如 PICO使用 token 级分类入口为 run_ner.py底层为BertForTokenClassification指标来自seqeval。原文档说明微调 PICO 任务只需把run_ner换成run_pico——两个脚本结构一致run_pico.py针对 PICO 数据做了适配。# Set path to read training/dev dataset export DATASET_PATH/path/to/ner/task/data/ # Set path to save the finetuned model and result score export OUTPUT_PATH/path/to/save/result_of_finetuning export TASK_NAMEchemprot # Set path to the model checkpoint you need to test export CKPT_PATH/path/to/your/model/checkpoint # Set config file export CONFIG_FILE/path/to/config/file # Set vocab file export VOCAB_FILE/path/to/vocab/file # Set label file such as the BIO tag export LABEL_FILE/path/to/vocab/file # Set path to cache train dev features (tokenized, only use for this tokenizer!) export CACHE_DIR/path/to/cache # Setting the hyperparameters for the run. export BSZ16 export LR1.5e-5 export EPOCH30 export WD0.1 export WM0.1 CUDA_VISIBLE_DEVICES0 python finetune/run_ner.py \ --model_type bert --model_name_or_path $CKPT_PATH \ --config_name $CONFIG_FILE --tokenizer_name $VOCAB_FILE --do_lower_case\ --data_dir $DATASET_PATH --cache_dir $CACHE_DIR --labels $LABEL_FILE \ --do_train --do_eval --logging_steps 1000 --output_dir $OUTPUT_PATH --max_grad_norm 0 \ --max_seq_length 128 --per_gpu_train_batch_size $BSZ --learning_rate $LR \ --num_train_epochs $EPOCH --weight_decay $WD --warmup_ratio $WM \ --fp16 --fp16_opt_level O2 --seed 42 --overwrite_output_dir与分类任务相比NER 微调的两个差异点--labels指定标签文件如 BIO 标注体系中的O / B-chem / I-chem等标签集合由 utils_ner.py 中的get_labels从该文件读取--data_dir --cache_dir数据目录与特征缓存目录分离且默认per_gpu_train_batch_size更小16因 token 分类序列标注计算量更大。4.5 微调源码要点数据管线训练集经convert_examples_to_features转为特征RandomSampler单机或DistributedSampler多卡采样DataLoader加载见 run_classifier.py评价逻辑run_classifier.py使用 GLUE 兼容的glue_compute_metricsutils_for_glue.py计算指标并写入output_dir下的预测文件run_ner.py使用seqeval的precision_score / recall_score / f1_score计算 token 级指标断点续训脚本支持从已有 checkpoint 继续微调最终保存pytorch_model.bin与bert_config.json到--output_dir。五、实验基准结果仓库 README 给出了领域自适应模型在基准任务上的结果指标为 F1均为原文档报告数据此处原样继承Biomedical生物医学模型JNLPBAPICOChemProtAverageBERT78.6372.3471.8674.28BioBERT79.3573.1876.1476.22PubmedBERT80.0673.3877.2476.89AdaLM-bio-base79.4675.4778.4177.74AdaLM-bio-small79.0474.9172.0675.34Computer Science计算机科学模型ACL-ARCSCIERCAverageBERT64.9281.1473.03AdaLM-cs-base73.6181.9177.76AdaLM-cs-small68.7478.8873.81从结果可见AdaLM-bio-base 在平均分上超越了 BERT / BioBERT / PubmedBERT且在 PICO 与 ChemProt 上取得最高分AdaLM-cs-base 在两个 CS 任务上均优于 BERT 基线。同时small系列以约 1/4 的参数量34M vs 132M仍能保持接近base的性能体现了Adapt-and-Distill在保持效果的同时压缩模型体积的目标。六、复现路径总览从零开始复现 AdaLM 的完整链路为构建领域增量词表运行 vocab_extend.py 或 subword_builder.py得到合并后的领域词表样例数据见 test_data获取领域自适应 checkpoint下载 AdaLM-bio/cs 的 base 或 small 模型微调下游任务按 README 示例配置DATASET_PATH / CKPT_PATH / CONFIG_FILE / VOCAB_FILE等环境变量运行 run_classifier.py分类或 run_ner.py / run_pico.pyNER评估对比将结果与第五节基准表对比验证领域自适应与蒸馏收益。七、许可证与联系该项目遵循仓库根目录LICENSE文件中的开源许可部分源码基于 HuggingFacetransformers项目。遇到问题可提交 GitHub Issue其他沟通可联系论文作者 Shaohan Huangshaohanhmicrosoft.com与 Furu Weifuweimicrosoft.com。AdaLM 也以独立 Python 包形式提供安装配置包名adalm、描述 domain adaptation toolkit with extended vocab依赖numpy / boto3 / requests / tqdm / urllib31.26.5见 setup.py。【免费下载链接】unilmLarge-scale Self-supervised Pre-training Across Tasks, Languages, and Modalities项目地址: https://gitcode.com/GitHub_Trending/un/unilm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考