资讯详情

资讯详情

少样本文本分类实战:原型网络、度量学习与提示调优路线解析

少样本分类这几年在文本领域越来越常见尤其是标注成本居高不下的场景比如客服工单归类、法律文书辅助判类、舆情评论情感分级。很多团队手里只有几十条甚至十几条种子标注却想让模型覆盖上百个细分类别传统微调一上来就过拟合换大模型又面临成本和响应延迟的双重压力。我在这类项目里反复试过几种路线最后沉淀下来三个可靠方向原型网络、度量学习以及基于预训练语言模型的提示调优。这篇文章就把这三条路线的原理、选型和实操经验尽量讲透。1. 少样本文本分类的问题本质与路线全景先明确一下我们面对的任务形态。少样本文本分类通常用 N-way K-shot 来描述N 代表类别数目K 代表每个类别下只有 K 条标注样本。例如 5-way 5-shot就是 5 个类别、每个类别只有 5 条样本总共 25 条数据训练一个分类器。这个设定下传统微调几乎必崩模型会把词汇共现、标点习惯甚至样本顺序当作分类信号在训练集上表现出非常高的准确率换一批数据就原形毕露。少样本之所以难本质是经验风险最小化失效了。监督学习的核心是要求模型在有限样本上拟合出能够泛化的决策边界当样本量远小于参数数量时拟合出来的边界严重依赖训练集的偶然噪声而不是类别之间的真正语义差异。这就像让一个人只看三张照片就辨认一个物种他可能抓住的是背景色、拍摄角度这种与物种本身无关的特征。针对这个问题主流方案分三条路线。第一条是原型网络思路是把分类问题转换成“到类中心的距离”问题。每个类用支持集样本向量的均值表示查询样本根据嵌入空间中的距离归属到最近的原型。它简单直接效果稳定尤其适合类别语义相对紧凑的场景。第二条是度量学习比原型网络更进一步。原型网络假设同一类的样本在嵌入空间中呈聚类分布而度量学习通过训练一个专门的距离函数让同类样本拉近、异类样本推远不再依赖人工选择的固定距离。匹配网络、关系网络都是这条线的代表作。第三条是提示调优思路完全不一样。它不直接训练分类器而是把分类任务包装成预训练语言模型熟悉的“完形填空”形式。比如情感分类可以改写成“这部电影太棒了整体感受是 [MASK]”让语言模型用原有知识去填充答案词再映射到分类标签。三条路线并不是互斥的。我在实际项目中经常把提示调优和原型网络结合起来用也有团队把度量学习中的难样本挖掘机制搬到提示调优的训练阶段。理解各自的适用边界比盲目追求其中某一种更重要。2. 原型网络用类中心距离做分类的经典方案2.1 原型网络的核心机制与损失函数原型网络的思想可以用一句话概括在嵌入空间里每个类别由一个“原型向量”代表这个原型就是该类所有支持集样本的均值向量查询样本跟哪个原型最近就把它分到哪一类。假设第 c 类的支持集有 K 个样本记作 {(x₁, y₁), ..., (x_K, y_K)}通过编码器 f_φ 得到 K 个向量原型向量 p_c 就是对这 K 个向量求平均p_c (1/K) · Σ f_φ(x_i)查询样本 x 的嵌入向量是 f_φ(x)它到第 c 类原型的距离采用欧氏距离d(f_φ(x), p_c) ||f_φ(x) - p_c||²分类时查询样本属于哪一类取决于哪个原型距离最近。在训练阶段不直接用“距离最近”这种硬判断而是用 Softmax 把距离转换成类别概率再用交叉熵损失反向更新编码器P(y c | x) exp(-d(f_φ(x), p_c)) / Σ_c exp(-d(f_φ(x), p_c))这个设计有一个隐蔽但关键的好处欧氏距离的平方加负号恰好构成一个高斯分布的密度函数形式。换句话说原型网络假设每个类别的样本在嵌入空间中围绕原型呈球形高斯分布。这个假设在文本场景里大多数情况下是合理的因为语义相似的文本经过预训练编码器后确实倾向于形成紧凑的簇。训练方式也很特殊采用 episode 方式。每个批次随机抽取若干个类别每类抽取若干支持样本和若干查询样本模拟测试时的 N-way K-shot 情形。这种“训练时怎么采样测试时就怎么采样”的做法让模型从一开始就适应样本极少的分类格局。我在实践中发现episode 采样策略对效果的影响比很多人以为的要大后面会专门展开。2.2 编码器选型与原型质量的关系原型网络的底座是编码器 f_φ。同样是原型网络换一个编码器效果天差地别。我在实验中试过三类第一类是轻量级句向量模型比如 Sentence-BERT 系列。优点是推理速度快嵌入空间对齐了语义相似度原型本身就有意义。缺点是对领域词汇不敏感直接在法律、医疗这种术语密集的文本上跑原型质量下降明显。第二类是全量微调的 BERT 类模型。这是最推荐的做法。BERT 作为编码器在 episode 训练中跟着优化嵌入空间会专门针对当前任务做形变把与分类相关的维度拉开。代价是训练显存占用高batch size 不能开太大需要配合梯度累积。第三类是冻结参数的 LLM 嵌入接口。适合零样本基线不适合少样本训练。因为 LLM 的嵌入空间非常稳定仅仅通过少量样本求均值来调整原型能够改变的非常有限。判断原型质量是否合格我在实践中有个粗糙但有效的验证方法算一下每个类的类内平均距离与类间平均距离的比值。比值如果高于 1.5说明原型的区分度偏低不管怎么调分类器都很难有质的提升这时候优先换编码器而不是堆训练技巧。2.3 适用边界原型网络擅长什么、不擅长什么原型网络最适合类别边界清晰、类内语义集中的任务。一个典型例子是电商售后工单的一级分类比如“退款”、“换货”、“物流”、“发票”四个方向每个类的表述虽然多样但核心意图非常明确支持集 5 到 10 条就能形成还不错的原型。不适合的场景有两类。一类是类别之间存在大量语义重叠比如舆情标签“愤怒”和“失望”边界模糊原型之间距离近查询样本稍偏一点就容易误判。另一类是细粒度分类比如区分几十种不同型号产品的故障描述类内差异大于类间差异均值原型会把关键判别性信息平均掉。针对这些缺陷有一个改进方向非常实用就是用语义聚类替代简单均值。把支持集样本先做聚类取最大簇的均值作为原型或者按置信度加权而不是算术平均能过滤掉离群样本的干扰。我在脏数据较多的工单场景里试过效果提升约 3 到 5 个点。3. 度量学习把“相似”这件事本身也学出来3.1 为什么固定距离不够用从孪生网络到匹配网络原型网络用欧氏距离时隐含一个假设嵌入空间中各向同性即每个方向对分类的贡献一样。但真实文本语义空间不是这样的往往只有少数几个维度携带判别信息大部分维度是共有的语法特征、句式特征。欧氏距离会把不相关信息也计入距离计算从而干扰分类。度量学习的思路是把“怎么衡量相似”也变成一个可学习的部分。最早的孪生网络很简单两个样本共享编码器距离函数提前定好比如余弦相似度或者欧氏距离训练目标是让同类的距离小、异类的距离大。这个方案在图像领域效果还行但在文本上表现一般因为句子结构复杂两句话语义相近不一定体现在表面的词面重合上。匹配网络是孪生网络的重要升级它引入了注意力机制。查询样本的最终表示不再是编码器的直接输出而是它与每个支持集样本的相关性加权求和f̂(x_query) Σ_i a(x_query, x_i) · f(x_i)其中权重 a 是查询样本与每个支持样本的相似度经过 Softmax 归一化。注意力机制让查询样本可以根据当前任务动态调整自己的表示更关注和哪些支持样本有关联。这在样本非常少的时候很有用相当于放宽了“每个类只需要一个原型”的限制保留了每个支持样本的独立信息。3.2 关系网络把距离变成一个神经网络关系网络比匹配网络走得更远它连距离函数都用神经网络来学。结构分两部分嵌入模块 g_φ 负责将样本映射为向量关系模块 r_ψ 负责计算查询样本与每个支持样本的“关系分数”。对于一对组合查询样本 x_j支持样本 x_i先把两个向量拼接送入关系模块r_ij r_ψ([g_φ(x_j); g_φ(x_i)])关系模块的输出是一个标量分数代表二者的匹配程度。训练时让同类组合的分数趋近 1异类组合的分数趋近 0用均方误差回归来优化。我最初觉得关系网络没必要距离就是距离为什么还专门学后来在真实场景里试过一次就理解了。固定距离函数比较的是向量之间的几何关系比如余弦是看夹角欧氏是看直线长度。但语义匹配经常不是简单的几何关系两句话有关联可能是因为它们共同指向某一个特征而这个特征在原始向量空间里是隐性的。关系网络相当于额外学了一个“匹配解释器”从这个角度确实能捕捉到非线性的语义关联。代价是训练难度上升。关系网络对嵌入模块和关系模块的联合调整敏感关系模块太强会变成记忆支持集样本出现严重的过拟合。我的经验是关系模块不要设计太深两层全连接加 ReLU 就够了。3.3 难样本挖掘少样本训练里最容易忽略的细节度量学习训练中有一个关键问题随机抽样的样本对大部分是容易区分的模型学不到什么。比如从 10 个类别里随机选一对样本A样本B大概率完全不像损失很小梯度没有信号。为了更高效的训练需要主动挑选难样本。难样本指的是那些当前模型最容易混淆的负样本对比如语义接近但类别不同的文本。把它们放进训练才能逼着度量空间朝着更有判别力的方向形变。图片领域有成熟的难样本采样方法比如“最难正样本 最难负样本”策略。文本场景我用过一个简单版本每个 episode 训练迭代中先正常计算所有样本对的相似度矩阵把每个锚点样本的负样本按相似度降序排列选相似度最高的若干负样本最难负样本参与损失计算。实现上其实比想象中简单多一个排序索引操作成本完全可以接受。难样本挖掘还有一个副作用它能够削弱类别不均衡问题。少样本任务里各类别的样本数往往并不均衡有的类别 5 条有的只有 2 条。随机采样会让大类别主导梯度方向难样本挖潜会让分类器把注意力集中在那些难以区分的类别上而不是被多数类带偏。3.4 三种度量方案的横向对比与选型建议方案核心机制训练复杂度文本场景表现适用情况孪生网络固定距离 共享编码器低较差简单二分类、向量相似检索匹配网络注意力加权表示中良好支持集样本差异较大的任务关系网络可学习距离函数中高良好语义匹配非线性较强的任务我之前做过一个实验用同一组数据跑三种方案关系网络在准确率上略低于匹配网络但是在类别间相似度高的小类上比匹配网络多抓回来约 6% 的召回。这说明关系网络虽然整体优势不明显但对“难分”样本的容忍度更好。如果你的业务恰好需要兜住那些偏门、模棱两可的类别关系网络值得投入。反之如果整体准确率优先匹配网络性价比更高。4. 提示调优借预训练语言模型的先验知识做分类4.1 从 [MASK] 到分类标签模板构造与答案映射提示调优的核心思路是绕开“训练一个全新分类器”这个思路把分类任务改造成预训练语言模型的完形填空任务。语言模型在海量语料上见过大量“前提 结论”的文本模式通过设计模板可以把任务装进它熟悉的形式里让它已有的语言知识参与判断。具体分三步。第一步设计模板比如情感分类的模板可以设计成“这部电影让我感到[MASK]”第二步定义答案词比如“好”映射“正面”、“差”映射“负面”第三步把文本套入模板让模型预测 [MASK] 位置对应的词再根据答案词映射回原始标签。PET 是这条路线的奠基工作它提出了基于人工模板的少样本微调框架。但 PET 对模板质量极度敏感换一个模板可能差十几个点。例如情感分类模板“整体感受是[MASK]”与“这部电影的观感[MASK]”答案词分布相差很大选择什么样的答案词对结果影响也非常明显。我用过一个很朴素的技巧不用单个模板而是设计 8 个模板每个模板独立预测然后对预测结果做加权投票。每个模板的表现权重用它在验证集上的置信度计算。这个方法比调单个模板更省力且稳定。模板数量不在于多关键要让模板之间差异大比如一个侧重整体评价一个侧重细节感受投票才有效果。4.2 连续提示把模板也变成参数人工模板要人去猜语言模型的偏好这件事非常蛋疼。连续提示Continuous Prompt干脆把模板的位置替换成一组可学习的向量让模型自己决定“前缀”应该是什么。具体做法是在输入序列前面拼接若干组可学习的高维向量例如 20 个 768 维的向量这些向量初始化为随机值或者用预训练模型的嵌入表初始化。微调时只更新这些前缀参数冻结大模型本身的权重。这个方案的实际效果是自动搜索模板确实有效训练后学到的前缀向量比人工模板通常高 2 到 5 个点。这里想指出一个重要区别PET 仍属于全量微调或大部分参数微调而连续提示属于参数高效微调更新参数量远远小于前者。我实测下来连续提示在显存受限的场景下是最好用的方案。因为不需要更新模型主体也就不需要保存大量优化器状态一个普通的消费级显卡就能跑。当然代价也是明显的就是学出来的前缀参数很难迁移到新任务每个任务都要重新训练一组。4.3 结合原型思想提示调优中的均值原型提示调优和原型思想可以混合这种混合方案在实践中表现令人满意。思路是这样的先给每个类别生成一个“提示原型”这个原型不是简单的嵌入均值而是在提示模板条件下的类别语义表示。比如对类别“物流”使用模板“与物流相关的问题是[MASK]”来生成各支持集样本的嵌入再取平均作为该类的原型。查询时也用相同的提示模板生成嵌入和各类原型算距离。这个做法的核心差异在于普通原型网络直接对原始文本编码求均值而提示原型把类别信息通过模板注入到嵌入过程里让原型向量更聚焦于分类目标。我在某客服项目上对比过提示原型比普通原型提升了接近 7 个百分点原因是原始文本中有大量与业务无关的寒暄话术模板把这些噪音对原型的干扰过滤掉了。4.4 人工模板设计的几条实操经验关于模板设计我踩过不少坑分享几条判断标准。模板要足够自然。语言模型是按自然语言训练出来的太机械的模板不能激活它的语言知识。判断方式很简单把模板拿给同事读一下如果对方需要思考才能理解那模型大概率也理解不好。[MASK] 的位置很讲究。放在句尾通常比放在句中对答案词的约束力更强但也有例外。如果放句尾模型会倾向根据上下文风格选择词放句中模型会更多地依赖局部语义两者对应不同的答案词分布可以针对性选择。答案词的选择需要权衡。太具体的答案词比如“喜爱”和“厌恶”虽然判别力强但语言模型的预测概率偏低容易受到噪声影响。太通用的答案词比如“好”和“差”预测概率高但类别间区分度反而下降。我的建议是每个类别准备 3 到 5 个候选答案词预测时取这组词的分数总和作为该类的得分而不是只靠单个词。5. 三条路线的选型对比与组合实践5.1 核心场景对照什么时候用哪种方案条件推荐方案理由每条样本都很短类别边界清晰原型网络简单直接运算开销低效果稳类别多且相似度高匹配网络/关系网络注意力机制和可学习距离能捕捉细粒度差异有大规模预训练模型可用提示调优语言知识参与决策少样本下泛化更强显存受限、只有消费级显卡连续提示只训少量参数日程可跑领域术语密集、通用语义空间不够原型网络 领域微调编码器原型质量依赖编码器领域适配优先5.2 一个实用的混合方案提示原型 度量精调我把实践中效果最稳定的混合方案拆解一下。第一步用连续提示初始化一组模板前缀在支持集上微调一小段时间让模板适应当前任务。第二步用这组带提示的编码器生成所有支持集样本的嵌入按类别求均值得到原型。第三步设计一个额外的可学习线性层或小型关系网络将“查询嵌入与原型拼接”作为输入输出类别得分用查询集样本训练这个小网络。这样做的好处是微调时只更新前缀参数不容易过拟合关系网络只学如何根据提示嵌入做最终判断复杂度低收敛快。我在 5-way 5-shot 的多组数据上跑过整体比单一方案高 3 到 8 个点而且训练时间增加不多。5.3 Effect 的关键训练与推理时的数据分布一致性无论选哪条路线有一个原则必须守住训练时构造的 N-way K-shot 分布要和推理时保持一致。举例来说训练时每个 episode 随机抽 5 类每类 5 条支持样本若干查询样本那么推理时也要配置同样的大小。如果业务上某类只有 4 条标注就不能硬套 5-shot 的训练配置而应该把这类单独处理否则模型完全没有适应这个 shot 数的能力。另外一个容易被忽视的问题是类别集合的一致性。测试阶段如果出现训练时未曾见过的类别所有基于支持集构建分类器的方法都会失效因为原型里根本没有对应向量。这种情况下只能重新构建原型或在构造训练 episode 时故意引入“类别采样随机化”让模型见过足够多样的类别组合方式。6. 少样本分类的坑与排查实录6.1 查询集泄漏最隐蔽的错误来源少样本训练实验里最常见的错误就是查询集泄漏。一种情况是同一篇文章被拆成多个句子后有些进了支持集有些进了查询集。模型在实际预测时会对和训练样本高度相似的句子给出偏高的置信度导致指标虚高。另一种情况是预处理阶段做了数据增强增强出来的样本和原始样本混在一起没有做去重也可能造成评估失真。我在项目里订了一条死规矩episode 划分前先对文本做去重重复样本只保留一条然后确保同一文本的任何变体不会横跨支持集和查询集。排查泄漏的方法是训练结束后做一个邻近检索把查询集样本和支持集样本对比找到距离最近的对人工检查是否有语义重复。这一步虽然糙但很有效。6.2 原型过于平滑均值操作抹掉了关键特征原型网络看似简单但在某些任务上会出现“原型变成了四不像”的情况。原因在于均值操作会把类别内所有样本的模式平均在一起而那些真正区分不同类别的特征可能在每个样本上占比都很小被共有的语言风格稀释掉。针对这种情况我用过两个有效手段。一是原型加权对支持集样本用模型自身的置信度作为权重置信度高的样本权重大低置信度的离群样本权重小。二是把支持集样本先做一次聚类取最大簇内样本的均值作为原型效果比较明显。第二种做法在支持集样本数量稍多比如 10 条以上时效果更明显。6.3 提示调优模板不生效先检查数据预处理使用提示调优时如果发现模板预测结果和随机猜测差不多通常不是模型的问题而是文本预处理和模型分词不一致造成的。中文场景尤其明显BERT 类模型使用 WordPiece 分词某些罕见词会被拆成若干子词导致模板中的词和文本中的词无法对齐。排查方法很直接把带模板的完整输入序列打印出来人工查看 [MASK] 附近的分词结果看看关键词语是否被切分了。另一个常见坑是模板和文本拼接时用了“”之类的标点模型分布上标点也会占据 token 位置影响对 [MASK] 附近语义的感知。我的经验是模板里尽量少用标点符号用空格或换行符分隔即可。6.4 常见问题速查表现象可能原因排查方向训练损失下降但验证准确率低episode 划分泄漏检查查询集与支持集文本重复原型网络各类别准确率差异大部分类原型被离群样本污染尝试聚类取最大簇均值提示调优所有类别输出同一个答案词模板与输入拼接方式有问题检查分词、标点、模板自然度度量学习效果重复性差难样本采样随机性过大固定随机种子增加负样本池连续提示训练不收敛前缀初始化范围不合理改用预训练嵌入表初始化调小学习率6.5 关于训练细节的三个小补充第一少样本场景下学习率要非常小。BERT 类模型的微调建议在 2e-5 左右连续提示建议更低比如 5e-6 到 1e-5学习率太大会导致灾难性遗忘模型原有的语言知识被冲掉。第二批量大小不要贪大少样本下大 batch 反而容易让模型陷入局部最优一个类别的样本可能在一个 batch 内被过度加权。第三早停要基于验证集而不是训练集少样本训练集上 loss 无论如何都会下降只有验证集上的变化才反映泛化能力。7. 少样本分类的后续扩展方向文本增强在前面的内容里多次被提到这里展开说两句。对于少样本文本分类简单的同义词替换、回译、随机删除都能提供一定帮助但要注意增强样本不能和原始样本形成完全相等的文本否则会加剧过拟合。我更推荐“伪标签”风格的方法用训练好的原型网络对无标注池做预测把置信度高的样本选出来加入支持集。这个策略在数据分布比较集中时收益显著但需要控制每轮新增样本数量防止噪声堆积。少样本分类结合主动学习也值得尝试。原型网络天然能给出置信度信息可以优先挑选模型最不确定的样本让人工标注。我有一个项目先用原型网络在无标注池里筛出 500 条模型最不确定的文本人工标注后加入支持集再重新训练相比随机标注等量样本准确率提升明显。这种方法可以显著降低标注成本。不过也要提醒一点少样本分类不是万能的。当类别数量超过 100、支持集数量接近 0 时再强的算法和策略都不如找一个像样的外部数据源做预训练或者在真实场景允许的情况下直接走人工规则。算法解决的是“标注不够但任务边界清楚”的问题而不是“完全没有数据”的问题。回到我自己的实践体会少样本文本分类的核心把握好两件事效果就不会太差。第一是用对评测方式不要拿着训练指标沾沾自喜要在独立的验证集上反复验注意 episode 划分的公平性。第二是愿意做“混合”越是少样本越要把不同思路的组件组合在一起。原型网络提供稳定的框架度量学习提升判别能力提示调优注入语言先验三者结合往往比单独押注某一条路线更稳健。先跑通一个最简单的原型网络基线再逐步往上叠加手段是我反复使用的稳妥路径。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →