阅读摘要
目前流行的第四大范式Prompt的主流思路是PVP,即Pattern-Verbalizer-Pair,主打的就是Pattern(模板)与Verbalizer(标签映射器)。
本文基于PVP,提出PET与iPET,但是关注点在利用半监督扩充自己的数据集,让最终模型学习很多样本,从而达到好效果。
PET: Pattern Exploiting Training ,是一种半监督学习方法,应用于 few-shot learning ,流程为:
1、训练PVP模型(prompt,supervised):对每一种 prompt pattern,使用单独的 PLM 在 有标签数据集 上微调得到多个「PVP模型」。
2、在这个过程中,Task Description(textual explanation) 可以让模型了解任务,利用预训练得到的先验知识和mlm参数,所以更加适合小样本学习。
3、样本扩充:使用得到「PVP集成模型」 给 无标注数据集 打标,生成对应的 soft label,组成完整的有标注数据。
iPET: iterative variant of PET,一种PET的迭代变体,用于迭代式扩充「prompt模型」的训练集,来增加模型效果。
[0] 摘要
GPT可以通过提供带有自然语言“任务描述”的输入,以完全无监督的方式解决一些问题,但是它没有有监督的方法效果好。基于此,论文引入了PET,先用无监督给数据答标签,再用有监督学习最终分类模型,这是一种半监督的训练过程,将输入转化为完形填空任务的形式。
[1] 介绍
标准的监督学习方法,比如预训练+微调,直接应用在小数据集上通常表现很差;只看少量样本,让模型去抓住任务的重点是很难的。论文举例了情感分类任务的三个句子:
T1:这是我吃过最好吃的披萨。
T2:你可以半价获得更好的寿司。
T3:披萨一般。不值得这个价钱。
如果T1和T2分别是标签A和B,现在问T3的标签。仅仅基于这俩样本进行判断几乎不可能,因为貌似正例的判断在T1、T2中都能找到(best better),然而如果我们提前知道此任务是讨论关于价格的,我们很轻易地可以给T3赋个B。这证明了当任务只有少量样本时,我们可以使用任务描述来使事情更加容易。
PET情感分类工作流程:1.准备许多模板/任务描述,这些模板将训练文本转化为完形填空;对于每一个模板,微调一个独立的预训练模型;2.集成上一步的所有模型,对无标签数据进行标注,得到softlabel;3.在这些带soft label的数据上训练标准分类器;
论文也发明了iPET,一个迭代的PET变体,iPET使用不断增加的训练数据集重复上述过程;在众多任务里面,给定小到中等规模的标注数据集,PET和iPE都大大超过了无监督方法、有监督方法和强的半监督baseline;
[2] 相关工作
GPT启发了PLM的零样本学习。
已经有使用完形填空任务的论文证明PLM具有成熟的知识量。
其它关于NLP中few-shot learning的工作包括探索与任务相关的数据,如数据增强。
iPET背后的思想是,训练很多版本的模型,当前模型使用的标注数据是之前版本模型标注的,类似于自训练和自助法。
[3] PET
首先介绍了一下PVP模式的基本流程,可以参考KPT论文笔记的3.1小节的解释。
辅助语言模型
小样本在训练时可能会发生灾难遗忘,因为预训练模型的微调本质还是一个语言模型,因此我们使用语言模型作为辅助任务。论文实际的操作是:1)计算MLM任务里[MASK]位置的交叉熵损失,为 ;2)计算整个MLM任务的损失,为 ;3)最后加权相加。源码如下:
def mlm_train_step(self, labeled_batch: Dict[str, torch.Tensor], unlabeled_batch: Optional[Dict[str, torch.Tensor]] = None, lm_training: bool = False, alpha: float = 0, **_) -> torch.Tensor: """Perform a MLM training step.""" inputs = self.generate_default_inputs(labeled_batch) mlm_labels, labels = labeled_batch['mlm_labels'], labeled_batch['labels'] outputs = self.model(**inputs) prediction_scores = self.preprocessor.pvp.convert_mlm_logits_to_cls_logits(mlm_labels, outputs[0]) # 计算[MASK]位置上的交叉熵损失 loss = nn.CrossEntropyLoss()(prediction_scores.view(-1, len(self.config.label_list)), labels.view(-1)) if lm_training: lm_inputs = self.generate_default_inputs(unlabeled_batch) lm_inputs['masked_lm_labels'] = unlabeled_batch['mlm_labels'] # 计算MLM任务的交叉熵损失 lm_loss = self.model(**lm_inputs)[0] # 加权相加 loss = alpha * loss + (1 - alpha) * lm_loss return loss
PVPs组合
一个比较大的挑战是没有较大的验证集,所以很难判断哪些PVP表现更好;思路有点像知识蒸馏(学习集成模型的软label就是蒸馏的思想),把多个Pattern的模型结合起来。
模板结合过程,3步,参考上图(1)(2)(3):
1.为每个模板(PVP)微调一个单独的预训练模型,这个成本很低;
2.通过加权的方式,集成1中所有模型,对无标注样本打softlabel ;Z为归一化因子,w为每个PVP的权重,w要么全设置为1,要么设置为1中训练集的acc,分别命名为uniform和weighted使用softmax归一上面的score,这里的softmax带温度T,T=2(知识蒸馏里经常这么干)。
3.基于2中的产生的伪标签样本微调预训练模型C。
iPET
有些模板表现很差,可能会导致Tc中有很多误标的样本;可以让(1)中的M相互学习,克服上述问题;iPET的核心是不断增加数据量,训练多个版本的模型;训练集扩大d倍,同时保持正负类别比例保持不变;
iPET过程:
(a)对于任意一个模型,其它模型对无监督数据集D的一个子集进行标注,产生的样本被扩充到T,然后用来在(b)中训练当前模型;(相互学习)M02和M03标注了一部分D,再加上T,得到T11,T11用来在(b)中训练M11(b)如上所述,基于新的被扩充的数据集,再训练模型;(c)重复(a)(b)k次,每次数据集扩充d倍;
[4] 实验
5个数据集。所有实验都使用RoBERTa large模型。因为没有足量验证集来调参,所以参数的设置依赖以前的经验。
1、2行中的unsupervised表示直接构建好PVP进行预测,没有经过任何训练,avg表示取所有PVP的均值,max表示取PVP中在测试集表现最好的。可以看到,不同PVP之间的差距是很大的
4、5、6行显示,只使用了10个示例进行标准微调,效果非常差,使用PET可以获得最大60%的提升,iPET还可以进一步提升性能。
7-12行显示:增加训练集大小,PET和iPET的性能增益变小,但对于50和100个示例,PET还是明显优于标准监督训练(行8 vs行7,行11 vs行10),iPET(行9,行12)也优于PET。
13~14行显示,当训练样本更大,1000份时,PET相对于直接监督微调提升没有那么明显,但仍然可能会有一些提升。
PVP集成方面的消融实验:10个样本下,最好的、最差的模板指标情况分布如前两行;蒸馏能够提升一些效果,同时也能较大地降低模型sizeuniform和weighted的集成区别不大,weighted更好一些。