
第一次看到 BnBERT-iPET 这个项目名时我把它拆成了三块BnBERT、iPET、Lottery Ticket Pruning。拼在一起它其实是回答了一个非常现实的问题在孟加拉语这种典型低资源语言上标注样本不够、算力也有限我们能不能用少量例子的提示学习配合剪枝最终得到一个既小又还能用的稀疏模型。这个思路背后的判断很直接少样本学习不一定要靠更大的模型反而可能靠“更早地去掉冗余参数”来稳定训练和推理。这篇文章想从方法动机讲起把它拆成几个可操作的模块再谈谈实际落地的边界和坑。1. 孟加拉语少样本学习为什么是一个“真问题”1.1 资源不对称让“少样本”的标准完全不同孟加拉语是使用人口非常多的语言之一但它的 NLP 基础设施和英语完全不在一个量级。英语有大规模通用语料、成熟的预训练模型、众包标注平台和成体系的评测集而孟加拉语往往只能依赖少量新闻、社交媒体和公共语料带标签的数据还要靠人工整理。在这个背景下“少样本”不是学术论文里的几百条样例那么简单很多时候是每个类别只有几十条甚至十几条。少样本学习的理想场景是预训练模型已经掌握了大量语言知识下游任务只需要少量样本告诉它“你要提取哪类信息”。这个假设在英语上基本成立因为模型在预训练阶段见过足够多的英语语料。但低资源语言上的预训练模型本身就先天不足它可能只是在一个不大不小的孟加拉语语料上继续预训练或者从多语言模型里迁移过来。模型对语义的掌握本来就不够牢固再给它少量样本训练很容易过拟合到这几条例子的表面模式上而不是真正学会任务。所以孟加拉语少样本学习不是“把英语那套少样本方法跑一遍”而是要同时解决三层问题第一预训练模型本身对语言的理解是否够用第二少量标注样本能否启动下游任务第三最终模型是否能在有限硬件上跑得动。BnBERT-iPET 这个方向的核心价值就是把后两层放在一起考虑。1.2 直接迁移英文模板和策略往往失灵我刚接触这类任务时第一个想法是把英语里的提示模板直接翻译成孟加拉语。后来发现没那么简单。孟加拉语的词序、形态变化、后置词系统和英语差异很大直接翻译出来的模板不一定能触发语言模型的预测能力。比如 PET 类方法依赖“完形填空”式的模板模板本身如果不符合目标语言的表达习惯模型在[MASK]位置的预测会变得非常不稳定。另外多语言模型和单语言 BnBERT 对少样本任务的敏感度也不一样。多语言模型可能在英语上表现不错但到了孟加拉语tokenizer 往往把词切得很碎模板占用的 token 数变多模型需要学习的提示模式也更复杂。这会导致同一个方法在英语上有效在孟加拉语上却像“失灵”了一样。这类问题的排查思路应该按顺序来先看 tokenizer 切分是否合理再看模板在真实样本上的预测分布最后看少量训练后的验证集效果。不要一上来就怀疑模型参数不够大。很多时候问题出在输入一侧而不是模型容量。1.3 结构性问题数据和规模要一起考虑低资源语言部署还有一层现实约束就算模型任务做对了如果参数量大到无法在一个普通 GPU 或 CPU 上推理项目依然落不了地。孟加拉语相关项目往往来自学术界、小型创业团队或公共服务部门算力预算有限没有足够的资源去跑一个大模型的服务。所以“稀疏化”不是锦上添花而是低资源落地的必要条件。BnBERT-iPET 的命名把 iPET 和彩票剪枝并列说明它不是先做少样本学习、再随便压缩一下模型而是在整个学习过程中就把“最终要得到一个稀疏模型”作为目标。这个设计取舍是理解这个项目的关键。2. iPET不是简单加正则而是把“未标注数据”变成学习杠杆2.1 PET 的基本机制把分类任务转成完形填空PETPattern-Exploiting Training的思想很多人已经熟悉了与其让模型直接输出类别标签不如把输入包成一个带[MASK]的句子让模型根据原有语言建模能力去预测被遮住的词。比如一个情感分类任务可以设计成“这段评论的情绪是 [MASK]”然后让模型在“积极/消极”对应的词之间做预测。这样下游任务的训练信号不只是一个分类头而是和预训练阶段的 MLM 目标保持一致模型更容易利用预训练积累的知识。这个方法对少样本的有效性在于模型不需要从头学习语义表示只需要学会“在哪个位置、用什么词来表达类别”。标注样本只需要几组“输入 正确填空词”的例子就可以启动任务。但 PET 有一个明显的弱点单个模板和单个模型的判断可能不稳定。模板措辞的微小变化、训练样本的随机抽样都可能让结果波动很大。2.2 从 PET 到 iPET教师集合和迭代蒸馏iPET 把 PET 从“单模型单模板”扩展成“多模型多模板 迭代蒸馏”。具体思路是先用少量标注数据训练多个教师模型这些教师模型可以有不同的随机初始化、不同的模板、甚至不同的样本子集。然后让这些教师模型去给一个大规模的未标注语料打标签但打的不是硬标签而是软标签或带置信度的预测结果。再把这些伪标注数据作为训练集去训练学生模型。这个过程可以迭代多轮每一轮都可以用上一轮更可靠的学生来生成新的伪标签。这样做有两个好处。第一多教师投票可以一定程度上抵消单一模型对噪声的敏感。某个教师可能在某个类别上犯错但多个教师平均后错误方向会被稀释。第二未标注数据进入了训练循环等于把“模型自己对语言的理解”也变成了训练信号。对于孟加拉语这种标注稀缺的场景这相当于扩大了有效训练集。从工程角度看iPET 并不复杂但它对超参数更敏感。教师数量、置信度阈值、迭代轮数、未标注数据的清洗方式都会直接影响最终效果。很多人跑完一遍发现效果不如 PET往往不是方法本身的问题而是候选标签的过滤条件太宽松或太严格。2.3 软标签为什么比硬标签更适合低资源迭代硬标签的问题在于它“过于自信”。当几个教师对某条样本意见不一致时硬标签必须选一个可能选到错误的那一个而且训练信号里没有体现“不确定性”。软标签会把概率分布保留下来学生模型可以从分布中看到哪些类别之间存在模糊性。低资源场景下模型本身不确定性很高软标签的作用就更明显。它相当于告诉学生这条样本更接近 A 类但 B 类也不是完全没可能。这样学生在学习时不容易被某一条错误标注带偏。实现上并不需要额外复杂代码只要在生成伪标签时保存概率向量而不是 argmax 结果然后在损失函数里用 KL 散度或带权重的交叉熵即可。3. Lottery Ticket Pruning把大模型剪“薄”但保留少样本下的能力3.1 彩票假设的核心不是“剪掉多少”而是“从什么初始化开始”彩票假设有一个很反直觉的观察一个完整的大模型里可能存在一个较小的子网络如果从它的初始权重开始重新训练效果能和完整模型一样好甚至更好。这个子网络的权重要么接近零要么被掩码掉但关键是最初的随机初始化值被保留下来而不是重新随机初始化。这个思想放在少样本场景里尤其微妙。我们通常以为参数越多越能拟合少量样本但实际上大模型在少样本下反而更容易过拟合或者对模板和样本顺序极其敏感。剪枝在这里起到的效果有点像“强制模型不要记住所有细节只保留最关键的能力”。但前提是我们要找的这个子网络不是在训练结束后临时确定的而是要在训练过程中逐步发现并且保留它对应的初始化状态。3.2 在 BnBERT 上做剪枝的关键选择实际做 BnBERT 稀疏化时第一个问题是剪哪里。Transformer 模型可以剪注意力头、剪 FFN 中间维度、剪 embedding 矩阵或者做全局非结构化剪枝。从工程上看非结构化剪枝的稀疏度最高但需要专门稀疏算子支持结构化剪枝更容易在推理框架里加速但可能伤害能力更多。对 BnBERT 这种不算大的模型来说如果目标只是减少内存占用非结构化剪枝配合 PyTorch 的稀疏存储也有可能够用如果要真正提升推理速度就要考虑剪注意力头和 FFN 维度。第二个问题是剪枝时机。彩票假设的经典做法是“训练-剪枝-重置-再训练”即迭代剪枝。在少样本 iPET 流程里剪枝应该放在每一轮学生训练之后而不是全部迭代完成之后再一次性剪。因为每一轮训练的目标是让学生吸收上一轮教师的知识如果等到最后再剪剪枝过程可能把最近几轮学到的关键能力剪掉。更稳妥的顺序是先正常训练几个 epoch确认模型已经收敛一部分然后施加一个较小的剪枝比例比如 20% 到 30%重置到初始权重继续训练重复几轮。不过这里有一个需要注意的坑如果你是严格按照彩票假设来重置权重就要保证每个剪枝轮次之后使用的“初始权重”是同一个初始种子。如果每次都重新随机初始化那就不是彩票假设而是普通的剪枝再训练。少样本下“重新随机初始化”往往会杀死模型学到的少样本信号所以这一点会很关键。3.3 稀疏化和 iPET 的结合逻辑BnBERT-iPET 的项目名把两个方法并列我的理解是它们各有分工。iPET 解决的是“数据不够”用未标注数据补彩票剪枝解决的是“模型不匹配”用稀疏结构稳定训练并降低存储。两者组合的最大好处是在每一轮迭代中学生模型都不需要从头学一个完整大模型的全部参数而只需要学一个更稀疏、更专注的子网络。这在一定程度上也降低了教师标签噪声被“全量记忆”的风险。但组合也带来一个新的权衡教师模型应该保持稠密还是也剪枝如果教师剪得太轻学生却剪得很重学生可能学不到教师的知识如果教师也剪得很重教师自身的预测质量会下降伪标签噪声反而增加。常见做法是让教师保持相对完整或处于一个比较小的剪枝比例学生逐步走向更大的稀疏度。这样能保证伪标签的质量同时最终产出一个可部署的稀疏学生模型。4. BnBERT-iPET 的完整流程从数据到稀疏模型的落地思路4.1 前置准备基础模型、少量标注集、未标注池、模板在开始实现之前先确认四样东西一个可用的孟加拉语 BERT 类预训练模型也就是 BnBERT或者类似的多语言模型。一个数量不大但覆盖所有目标类别的标注集。少可以但要保证每个类别至少有几条。一个大规模的未标注语料池用来生成伪标签。可以是新闻、评论、百科或社交媒体文本但要注意类别分布不能和目标任务偏离太远。一套针对孟加拉语设计的模板和 verbalizer。模板是带[MASK]的输入模式verbalizer 是每个类别对应的预测词。模板设计时不要只用一个最好准备 2 到 3 个候选模板。比如对于情感分类可以分别是“这段话的情感是 [MASK]”“评论者的感受是 [MASK]”“这条内容传递的情绪是 [MASK]”。要让母语者确认这些表达是否自然因为一个在英语里很顺的模板翻译成孟加拉语后可能在语义重心上变了。4.2 第一阶段用少量标注数据训练教师集合教师集合的训练不需要太复杂。可以按不同随机种子、不同模板组合训练 3 到 5 个相同结构的 BnBERT 分类模型。每个模型只在少量标注数据上做 PET 式微调训练轮数不要太多通常 3 到 10 个 epoch 后观察验证集表现。由于标注数据极少模型很快会出现过拟合但 PET 类方法有时候在过拟合的早期反而能学到模式所以更稳妥的做法是保存每个 epoch 的 checkpoint然后在验证集上选。如果标注集实在太少连一个可靠的验证集都划分不出来可以改用交叉验证或者干脆用小规模人工检查。不要用训练集本身来选 epoch不然模型只会记住那几十条样例。4.3 第二阶段教师对未标注池生成软标签并做置信度筛选得到多个教师后让它们分别对未标注池中的每条样本进行预测。这里有几个筛选策略设置置信度阈值。比如只有概率最大值超过 0.8 的样本才进入伪训练集。设置多教师一致性要求。比如至少 3 个教师里要有 2 个预测结果相同且平均置信度超过阈值。过滤掉所有教师都“犹豫不决”的样本。阈值不是越高越好。太高会导致伪训练集太小失去扩大数据量的意义太低会让噪声标签大量混入。一个比较稳妥的做法是先看置信度分布选择累积比例在 60% 到 80% 的位置作为初始阈值再根据验证集效果调整。# 示例结构教师生成软标签并过滤 def generate_pseudo_dataset(teachers, unlabeled_pool, threshold0.7): pseudo_data [] for text in unlabeled_pool: probs average_teacher_predictions(teachers, text) max_prob probs.max() if max_prob threshold: pseudo_data.append((text, probs)) return pseudo_data这段伪代码只是示意结构实际实现时还要处理 batch、模板前缀、verbalizer 映射等细节。4.4 第三阶段迭代训练学生并逐步引入剪枝学生模型的训练可以重复多轮。每一轮学生使用上一轮生成的软标签数据作为训练集损失函数可以直接对软标签分布做 KL 散度也可以取 argmax 后做交叉熵。从低资源场景看KL 散度会更平滑因为它保留教师之间的不确定性。剪枝操作建议放在每一轮学生训练结束后进行。初始阶段可以先不剪等模型稳定后每轮剪掉 20%-30% 的低重要性权重。重要性的计算可以用权重的绝对值大小也可以用梯度信息。对 BnBERT 这种大小的模型常见做法是用全局幅度剪枝把所有需要剪的参数按绝对值排序剪掉最小的那批。这里要反复提醒如果你想保留彩票假设的收益就必须把初始权重保存在内存里并且剪枝后重置到初始权重而不是继续使用剪枝后的当前权重。很多实现写着“剪枝”实际上只是把权重置零后继续训练这也能提升稀疏度但已经脱离了彩票假设的范畴。4.5 最终评估和导出迭代结束后需要做两件事。第一在独立测试集上评估稀疏学生模型和完整学生模型、教师集合做对比。第二导出稀疏模型记录下掩码矩阵、剪枝比例和最终准确率。如果掩码是结构化产生的可以直接替换模型配置文件如果是非结构化稀疏可能需要转成支持稀疏运算的格式否则推理时无法真正提速。评估时不要只汇报平均准确率。低资源模型的方差可能很大同一个方法换一个随机种子结果可能差好几个点。更严谨的做法是跑多个种子取均值和标准差。这也是少样本学习领域常见的隐藏陷阱你以为自己找到了“最佳方法”其实只是运气好。5. 新手最容易踩的坑模板、初始化、置信度和剪枝时机5.1 模板和 verbalizer 不是“翻译”而是“重新设计”我在前面提过模板不能直译。这里再展开一下。孟加拉语的动词变化和后置词跟英语差异明显很多英文模板里的词序需要调整。更麻烦的是 verbalizer 的选择。同一个类别英语里用“positive”映射“积极”到了孟加拉语可能要用一个更常用的形容词或者一个名词形式。如果 BnBERT 的 tokenizer 把这个词切成了好几个子词那么[MASK]位置的预测会同时涉及多个 token这时候不能简单用单个 token 的预测概率要做序列概率合并。建议在正式训练前先在未标注数据上跑一次模型看看[MASK]位置实际预测出哪些词。如果预测集中在几个高频词上说明模板和 verbalizer 是合理的如果预测分布很散说明模型根本没有理解模板。这一步是排查很多少样本问题的起点。5.2 剪枝的掩码必须在“同一初始化”下反复验证彩票假设里有一个关键动作叫 rewinding也就是把权重回卷到早期训练时刻。很多复现失败的原因不是方法错而是没有保留正确的初始化状态。如果你用的是 PyTorch建议在训练前保存模型的初始 state_dict之后每次剪枝后都要用这个 state_dict 重置而不是用上一个阶段结束的 state_dict。另一个容易忽略的点是 Adam 的动量项。重置权重时优化器的状态也要重新初始化或回卷到对应的训练步。否则模型虽然权重重置了但优化器状态仍然是之前训练比较久的状态相当于没有真正实现“重新训练”。5.3 置信度阈值和迭代轮数宁缺毋滥还是宁滥毋缺很多人做 iPET 时喜欢调大置信度阈值因为过滤后的伪标签看起来准确率高模型在验证集上也会立刻变好。但这是有代价的阈值越高伪训练集越小模型越容易对少量高置信度样本过拟合。阈值太低噪声标签变多模型可能学习到错误的模式。一个实用的判断标准是每轮迭代之后看验证集效果是否还在提升。如果连续两轮验证集效果没有提升可以考虑停止迭代或者减少剪枝比例。不要盲目地迭代很多轮。从公开方法的常见表现看iPET 的收益通常在第一轮和第二轮最明显之后逐步饱和。5.4 少样本评估的排查链路当你跑了 BnBERT-iPET但结果不理想可以按下面的顺序排查先看模板模型在无训练状态下对验证集样本的[MASK]预测是否已经接近正确答案再看教师多教师之间的一致性高不高如果教师预测本身就很分裂检查模板和标注样本。再看伪标签人工抽查 20 条伪训练样本看置信度高的样本是否真的正确。再看学生训练训练损失是否在下降如果损失不变可能是软标签分布太均匀模型学不到信号。最后看剪枝逐层检查掩码比例是否过大关键层是否被剪到接近零。这个链路能覆盖大多数“模型不 work”的场景核心思路是先确认输入一侧没有问题再往模型内部排查。6. 适用边界与工程建议6.1 适合什么任务和场景BnBERT-iPET 这类组合方法最适合的还是低资源文本分类类任务。比如情感判断、新闻主题分类、评论观点识别、垃圾/正常分类等。这些任务的特点是输出空间有限类别之间可以用自然语言词描述适合 PET 的完形填空范式。同时任务需要存在一定量的未标注语料因为 iPET 的收益主要来自伪标签数据。如果你的项目里只有几百条标注数据但没有任何额外语料iPET 的价值会大打折扣。从团队条件看适合那些有基础机器学习经验、但硬件资源一般的团队。稀疏剪枝能降低模型体积让最终模型在推理机器上更容易部署。相比从头训练一个大型多语言模型这种方案的成本要低得多。6.2 不适合什么场景如果任务不是分类而是生成、抽取式问答、序列标注iPET 和完形填空模板的适配就会很别扭。比如词性标注或实体识别输出空间不是几个词而是标签序列PET 的简单模板就难以表达。如果项目对最终准确率要求极高而且你有充足的标注预算那更合理的方案是直接标注更多数据并训练完整模型而不是折腾少样本和剪枝。稀疏化在低资源下可以稳定训练但它本质上是一个“在资源受限时做取舍”的方案不能替代数据本身。此外如果你的未标注池和目标任务分布差异极大比如用新闻文本伪标签去训练一个评论情感模型那 iPET 生成的标签会带有严重的分布偏移结果可能不如只用少量标注数据训练。6.3 落地的工程建议最后给几条整理的落地建议。先用小规模未标注池跑通全流程比如 500 到 1000 条样本。等确认模板、剪枝、伪标签过滤都稳定后再扩展到大语料池。固定随机种子并且至少跑 3 个种子取平均。少样本方法的方差太大只看一次结果容易误判。保留一个从一开始就没有参与任何训练的测试集。所有阈值选择、剪枝比例调整都要在验证集上进行不要反复看测试集。记录每一轮伪标签的数量、教师一致率、学生验证集效果和剪枝比例。这些日志能帮你快速定位是数据问题、训练问题还是剪枝问题。不要把剪枝比例一开始就设到 90%。从 20% 或 30% 开始观察剪掉后验证集效果是否还能保持再逐步提高。这里有一个常见的误解需要再次说明稀疏化并不是追求越稀疏越好。真正有价值的剪枝是在模型能力不下降的前提下找到一个刚好能保持下游任务表现的稀疏结构。有时候把 BnBERT 剪到 70% 稀疏可能效果还行但 80% 时突然崩溃中间很可能没有平滑的过渡。你需要为具体任务找到那个“临界点”。最后想说的一点BnBERT-iPET 这个组合给我最大的启发是它把“数据少”和“模型大”变成了一个统一问题。过去我们习惯先处理数据再训练一个完整模型最后如果模型太大再想办法压缩。但这个项目名把 iPET 和剪枝放到同等位置暗示了正确的顺序应该是从一开始就为数据稀缺和部署限制而设计模型结构。少样本语言建模在孟加拉语这类低资源语言上从来不是一条线性流程。它需要反复检查模板是否自然、伪标签是否可信、剪枝是否破坏了关键能力。这个方法能否在你的任务上生效取决于你是否愿意多做几轮小规模验证而不是直接把参数拉满。如果你也在做低资源语言的分类任务我的建议是先别急着跑完整流程拿 20 条训练样本设计两个模板跑一个最朴素的 PET看看模型能不能学到基本规律。如果这一步都不稳定后面的 iPET 和剪枝只会放大噪声。先把最基础的一条链路走通再逐步叠加迭代和稀疏化你会发现每个环节带来的收益和代价都变得清晰可衡量。