ARTICLE DETAIL

资讯详情

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

预训练语言模型是NLP任务性能的关键吗?实战经验与避坑指南

预训练语言模型是NLP任务性能的关键吗?实战经验与避坑指南 预训练语言模型这几年几乎成了NLP领域的标配。不管你是做文本分类、情感分析、信息抽取还是搭一个问答系统打开任何一个技术方案十有八九第一句话就是我们基于XX预训练模型。但问题也随之而来它真的是提升NLP任务性能的关键吗还是说我们只是被一种集体惯性推着走把预训练当成了万能药我自己在这个方向上摸爬滚打了几年从最早用Word2Vec做词向量到后来Fine-tune BERT再到现在各种大模型满天飞踩过的坑不算少。这篇文章不打算给你讲教科书上的定义而是想从实际做项目的角度把预训练语言模型到底在NLP任务里扮演什么角色这件事掰开揉碎聊清楚。如果你刚入门NLP或者正在纠结要不要上预训练模型、怎么上、上了之后效果不好怎么办那这篇内容应该能帮你省下不少试错时间。1. 预训练语言模型到底解决了NLP的什么核心问题1.1 从每个任务从零训练到先学通用语言规律在预训练模型普及之前做NLP任务的基本流程是这样的收集标注数据设计网络结构从随机初始化开始训练。这个过程有个致命问题——标注数据永远不够。NLP的标注成本极高一个中等规模的情感分析数据集可能也就几万条而这几万条数据要支撑一个深度网络学到足够的语言规律几乎不可能。预训练的思路本质上是一种迁移学习的工程化落地。它先在海量无标注文本上做自监督学习让模型学会语言的基本规律——词与词的搭配、句子的语法结构、上下文的语义关联。然后你再拿这个已经懂语言的模型用少量标注数据去微调让它适应你的具体任务。这个逻辑听起来简单但背后的意义很大。它把NLP任务的门槛从你需要大量标注数据降低到了你需要少量标注数据加一个预训练模型。对于绝大多数中小团队来说这是质的变化。1.2 预训练学到的到底是什么三个层次的表征很多人把预训练模型当成一个黑盒觉得反正用了就有效果。但如果你不理解它到底学到了什么就很难在效果不好的时候做出正确判断。根据我的实践经验预训练模型学到的表征大致可以分成三个层次词汇层表征模型学会了每个词在上下文中的向量表示。和静态词向量不同预训练模型给出的词向量是动态的同一个词在不同句子里会有不同的表示。比如苹果在吃苹果和苹果发布会中的向量是完全不同的。句法层表征模型隐式地学到了句子的语法结构。你不需要显式地做依存句法分析模型在编码过程中已经捕捉到了主谓宾、修饰关系等信息。语义层表征模型学到了句子级别的语义信息包括蕴含、矛盾、相似等关系。这是很多下游任务直接受益的部分。理解这三个层次很重要因为不同任务对这三个层次的依赖程度不同。文本分类主要靠语义层序列标注更依赖词汇层和句法层而语义匹配则高度依赖语义层。当你发现预训练模型在你的任务上效果不明显时很可能是因为你的任务本身对预训练学到的表征依赖度不高。1.3 为什么不是所有NLP任务都能靠预训练一键提升这里要泼一盆冷水。预训练模型不是万能的它在以下几类任务上的提升非常有限第一类是强领域依赖的任务。比如医学命名实体识别预训练模型在通用语料上学到的语言规律和医学文本的表达方式差距很大。你直接拿一个通用预训练模型去微调效果可能还不如在领域语料上从零训练一个小模型。第二类是低资源且标注质量差的任务。预训练模型需要微调数据来对齐到你的任务上如果你的标注数据本身噪声很大微调过程反而会让模型学到错误的模式。第三类是推理链较长的任务。预训练模型擅长模式匹配但不擅长多步逻辑推理。如果你的任务需要模型做复杂的推理单纯靠预训练加微调是不够的。提示在决定是否使用预训练模型之前先问自己一个问题——我的任务核心难点是什么是语言理解不够还是领域知识不足还是推理能力欠缺只有第一个问题预训练模型才是直接答案。2. 不同NLP任务中预训练模型的真实收益差异2.1 文本分类与情感分析收益最明显的一类文本分类是预训练模型收益最直观的任务。我做过一个对比实验在一个包含5万条评论的情感分析数据集上用TextCNN从零训练准确率大概在86%左右换成BERT-base微调准确率直接到了92%。这6个百分点的提升在业务上可能意味着每天少处理几百条误判。为什么文本分类收益这么大因为分类任务本质上需要模型理解整句话的语义而预训练模型在语义层表征上的积累正好对口。你只需要在预训练模型上面加一个分类头用少量数据微调几轮就能得到不错的效果。但这里有个细节值得注意微调学习率的选择比模型选择更重要。我见过很多人直接拿BERT默认的2e-5去微调结果效果一般。实际上对于小数据集学习率应该更小1e-5甚至5e-6并且要配合warmup策略。对于大数据集可以适当放大到3e-5。这个参数对最终效果的影响有时候比换模型还大。2.2 序列标注与信息抽取收益中等但稳定性提升明显序列标注任务包括命名实体识别、词性标注、关键词抽取等。这类任务的特点是每个token都需要一个标签模型需要同时理解局部上下文和全局语义。预训练模型在这类任务上的收益不如分类任务那么夸张但有一个很重要的优势稳定性。从零训练的序列标注模型对初始化非常敏感不同随机种子跑出来的结果可能差好几个百分点。而预训练模型因为已经有了良好的初始化微调后的结果方差小很多。我在一个医疗实体识别项目里做过对比从零训练的BiLSTM-CRFF1在78到83之间波动用预训练模型微调F1稳定在86到87之间。虽然上限提升不算巨大但下限的提升对工程落地来说意义更大——你不需要反复调参碰运气了。2.3 语义匹配与问答预训练模型几乎是必需品语义匹配比如判断两个句子是否相似和问答任务对语义层表征的要求极高。这类任务如果不用预训练模型基本做不出可用的效果。原因在于这类任务需要模型理解同义不同形和同形不同义的微妙差别。比如这个手机电池很耐用和这款手机的续航表现不错字面重叠很少但语义高度相似。从零训练的模型很难学到这种抽象语义关系而预训练模型在海量语料上已经见过大量类似表达天然具备这种能力。在实际项目中我通常会用Sentence-BERT这类结构来做语义匹配。它的做法是在预训练模型之上做孪生网络微调把句子映射到一个向量空间然后用余弦相似度来衡量语义距离。这个方案在检索、去重、推荐等场景里都非常实用。2.4 生成式任务预训练是起点但不是终点文本生成摘要、翻译、对话是预训练模型另一个主战场。但和判别式任务不同生成任务对预训练模型的依赖更复杂。预训练模型给生成任务提供了一个好的起点——它让模型学会了语言的流畅性和基本语法。但生成任务的核心难点往往在于内容是否正确和风格是否匹配这些不是通用预训练能解决的。你需要做领域自适应预训练或者在微调阶段引入特定的训练目标。我做过一个法律文书摘要的项目直接用通用预训练模型做微调生成的摘要读起来很流畅但经常漏掉关键的法律条款。后来在领域语料上做了继续预训练再微调摘要的完整性才明显改善。这个经验说明生成任务里预训练模型解决的是怎么说的问题说什么还得靠领域数据。3. 预训练模型落地时最容易踩的五个坑3.1 坑一盲目追求大模型忽略推理成本这是我最常见到的误区。很多人一上来就想用最大的模型觉得参数越多效果越好。但实际项目中推理成本是一个绕不开的约束。我参与过一个线上评论审核系统最初用BERT-large离线测试F1比BERT-base高了1.5个百分点。但上线后发现单条推理延迟从15ms涨到了45msGPU显存占用翻倍导致单机并发能力下降了一半以上。最后不得不换回base版本用蒸馏技术把large的能力迁移过来才在效果和成本之间找到平衡。注意选模型的时候先算清楚你的QPS要求和延迟预算再倒推能承受的模型规模。别等到上线了才发现跑不动。3.2 坑二微调数据量太少导致灾难性遗忘预训练模型虽然强大但微调数据太少的时候会出现灾难性遗忘——模型把预训练阶段学到的通用语言知识忘掉了过拟合到少量微调数据上。我的经验是微调数据少于1000条时要特别小心。这时候可以采取以下策略冻结预训练模型的前几层只微调后几层和分类头使用更小的学习率配合更多的warmup步数在微调数据上做数据增强比如同义词替换、回译考虑用Prompt-tuning等参数高效微调方法减少对预训练权重的扰动3.3 坑三忽略tokenizer和领域词汇的匹配问题预训练模型的tokenizer是在通用语料上训练的对领域专有词汇的分词可能很不合理。比如医学领域的非小细胞肺癌通用tokenizer可能会切成非、小、细胞、肺、癌五个token这种切分丢失了词汇的整体语义。解决办法是在领域语料上重新训练tokenizer或者至少把领域高频词加入tokenizer的词表。这个操作看起来不起眼但在专业领域任务里对效果的影响可能达到2到3个百分点。3.4 坑四把预训练模型当成特征提取器不做微调有些人为了省事直接把预训练模型的输出当作固定特征后面接一个分类器。这种做法在某些场景下可行但通常比全量微调差不少。原因在于预训练模型的表征是通用的没有针对你的任务做调整。微调的过程就是让模型把通用表征倾斜到你的任务上。如果你不做微调相当于放弃了这个适配过程。当然如果你的标注数据极少比如几百条或者计算资源极其有限固定特征加浅层分类器也是一个合理的折中方案。但只要有条件还是建议做微调。3.5 坑五忽视数据质量以为预训练模型能自动纠错预训练模型确实比从零训练的模型更鲁棒但它不是噪声过滤器。如果你的标注数据里有大量错误标签微调后的模型会把这些错误也学进去。我在一个项目里遇到过这种情况标注团队把中性和正面的边界搞混了导致训练数据里这两类的标签大量互换。模型微调后在这两类上的表现一塌糊涂。后来重新清洗了标注数据效果立刻恢复正常。这个坑的教训是在预训练模型时代数据质量的重要性不是降低了而是更高了。因为模型容量大了它有能力拟合更复杂的模式包括错误的模式。4. 让预训练模型真正发挥作用的实操策略4.1 领域自适应预训练什么时候值得做领域自适应预训练DAPT是指在领域语料上继续做预训练让模型适应领域的语言分布。这个操作计算成本不低但在以下场景里非常值得领域语言和通用语言差异大医学、法律、金融你有大量领域无标注文本至少百万级token下游任务的标注数据有限需要模型从领域语料中补充知识具体操作上我通常会用领域语料在预训练模型上再跑几个epoch的MLM任务。学习率要设得很小比如1e-5避免把预训练学到的通用知识冲掉。跑完之后再在下游任务上微调。实测下来在医学NER任务上做了DAPT之后F1能提升3到5个百分点。这个提升幅度在成熟任务上已经相当可观了。4.2 参数高效微调小团队的现实选择如果你的GPU资源有限或者需要为多个任务维护多个模型参数高效微调PEFT是很好的选择。这类方法只训练少量额外参数冻结预训练模型的主体。常见的方案包括方法核心思路适用场景Adapter在每层插入小模块多任务共享底座LoRA低秩分解权重更新单任务快速适配Prefix-tuning在输入前加可学习前缀生成式任务Prompt-tuning用软提示替代硬模板少样本场景我自己最常用的是LoRA因为它实现简单效果稳定而且推理时可以把低秩矩阵合并回原权重不增加推理延迟。在一个文本分类项目里用LoRA微调的BERT和全量微调的BERT效果差距不到0.5个百分点但训练参数量只有原来的1%左右。4.3 学习率与warmup被低估的关键参数前面提过学习率的重要性这里再展开说一下。预训练模型的微调对学习率非常敏感因为预训练权重已经在一个比较好的位置上学习率太大会把权重推离这个位置太小又学不动。我的经验参数范围是BERT-base微调学习率1e-5到3e-5warmup比例0.1BERT-large微调学习率5e-6到1e-5warmup比例0.1小数据集5000条学习率取范围下限warmup比例提高到0.2大数据集10万条学习率可以取范围上限warmup比例0.05另外层数越靠前的层学习率应该越小。这是因为底层学到的是通用语言特征不需要大改顶层学到的是任务相关特征需要更多调整。有些框架支持分层学习率衰减建议开启。4.4 模型集成与蒸馏从能用到好用当你已经有一个效果不错的预训练模型想进一步提升或者部署到资源受限的环境时集成和蒸馏是两个实用手段。集成方面最简单的做法是用不同随机种子训练多个模型推理时取平均。这个操作能把效果提升1到2个百分点代价是推理成本翻倍。如果成本敏感可以用模型蒸馏用一个大模型或集成模型的输出作为软标签训练一个小模型。我在一个线上意图识别系统里用过这个方案先用BERT-large做教师模型蒸馏到一个4层的轻量模型最终效果只比教师模型低0.8个百分点但推理速度提升了4倍。这个性价比在工程上非常划算。5. 预训练模型不是终点NLP任务性能的完整拼图5.1 数据质量与标注策略的杠杆效应说了这么多预训练模型的好处和用法但我想强调一个经常被忽视的事实在NLP任务里数据质量的杠杆效应往往比模型选择更大。我做过一个粗略的估算在一个文本分类任务上把标注数据的错误率从10%降到2%带来的效果提升相当于把模型从BERT-base换成BERT-large。但清洗数据的成本远低于换模型带来的推理成本增加。所以我的建议是在纠结用哪个预训练模型之前先花时间检查你的数据。具体可以做这几件事抽样检查标注一致性看看不同标注员对同一条数据的判断是否一致分析错误案例看看有多少错误是数据问题导致的有多少是模型能力不足建立标注规范文档减少标注歧义对关键类别做数据增强缓解类别不平衡5.2 任务设计有时候改任务比换模型更有效还有一个反直觉的经验当预训练模型效果不理想时重新设计任务形式可能比换更大的模型更有效。举个例子我做过一个判断评论是否包含广告的任务最初设计成二分类。模型效果一般F1只有82左右。后来改成抽取广告片段的序列标注任务模型F1提升到了89。原因是二分类任务要求模型把整句话压缩成一个判断信息损失大而序列标注任务让模型定位到具体片段任务更聚焦。类似的思路还有把多分类改成多个二分类、把生成任务改成抽取任务、引入辅助任务做多任务学习。这些任务层面的调整有时候能带来比模型升级更大的收益。5.3 后处理与业务规则模型之外的性能来源最后一点也是很多技术方案里容易忽略的后处理和业务规则。预训练模型再强也不可能100%准确。在实际系统里合理的后处理能显著提升最终效果。比如在实体识别后加规则过滤去掉明显不合理的实体在分类结果上加置信度阈值低置信度的样本转人工利用业务知识做结果校验比如日期格式、金额范围我在一个金融信息抽取项目里模型本身的F1是91加上后处理规则后端到端的准确率到了95以上。这些规则不复杂但需要你对业务有深入理解。提示不要把所有希望都寄托在模型上。一个成熟的NLP系统模型只是其中一环数据、任务设计、后处理、业务规则同样重要。6. 回到那个问题预训练模型是关键吗6.1 分场景回答什么时候是什么时候不是绕了一圈回到标题的问题。我的答案是预训练语言模型是提升NLP任务性能的关键因素之一但不是唯一关键也不是所有场景下的第一关键。具体来说当你的任务是通用领域的语义理解任务且标注数据有限时预训练模型是最关键的提升手段。当你的任务是强领域任务且领域语料充足时领域自适应预训练比通用预训练更关键。当你的任务对推理能力要求高时预训练模型只是基础还需要在推理架构和训练目标上做文章。当你的数据质量很差时清洗数据比换任何模型都关键。所以与其问预训练模型是不是关键不如问在我的具体场景里当前最大的瓶颈是什么。找到瓶颈才能找到真正的关键。6.2 一个实用的决策清单为了方便你在实际项目中做判断我整理了一个简单的决策清单先看数据标注数据有多少质量如何类别是否平衡如果数据有问题先解决数据。再看任务任务是分类、标注、匹配还是生成不同任务对预训练模型的依赖度不同。然后看领域通用领域还是专业领域专业领域考虑领域自适应预训练。接着看资源推理延迟和显存预算多少决定用多大的模型。最后看基线先用一个简单的预训练模型跑基线再决定是否升级。这个顺序很重要因为很多人的做法是反过来的——先选模型再想数据最后发现效果不好又回头改数据浪费了大量时间。6.3 我个人在实际项目中的体会做了这么多NLP项目我最大的体会是预训练模型确实改变了NLP的游戏规则但它没有改变机器学习的基本逻辑——数据和任务定义决定了上限模型只是逼近这个上限的工具。我见过太多团队把大量精力花在尝试各种预训练模型上却不愿意花时间清洗数据、分析错误案例、优化任务设计。结果就是模型换了一茬又一茬效果始终在原地打转。反过来那些效果做得好的项目往往是在数据质量和任务设计上下了功夫预训练模型只是他们工具箱里的一件称手工具而不是救命稻草。最后分享一个小技巧如果你刚开始接触预训练模型不要一上来就追求SOTA。先用一个base模型跑通全流程把数据管道、训练流程、评估体系搭好然后再逐步优化模型。这个顺序能让你少走很多弯路也能让你更清楚地看到每个环节对最终效果的贡献。预训练语言模型是NLP任务性能提升的重要杠杆但杠杆要发挥作用还需要一个稳固的支点。这个支点就是你对数据和任务的深入理解。
返回列表