该存储库包含用于利用披肩问题的代码,以进行几种文本分类和自然语言推断,而不仅仅是大小很重要:小语言模型也很少。这些论文介绍了模式开发培训(PET),这是一种半监督的培训程序,将输入示例重新定义为固定的短语。在低资源环境中,尽管需要少99.9%的参数,但PET和IPET的表现明显胜过定期监督培训,各种半监督基线甚至GPT-3。 PET(IPET)的迭代变体训练多代模型,甚至可以在没有任何培训数据的情况下使用。
| #examples | 训练模式 | Yelp(完整) | AG的新闻 | 雅虎问题 | mnli |
|---|---|---|---|---|---|
| 0 | 无监督 | 33.8 | 69.5 | 44.0 | 39.1 |
| IPET | 56.7 | 87.5 | 70.7 | 53.6 | |
| 100 | 监督 | 53.0 | 86.0 | 62.9 | 47.9 |
| 宠物 | 61.9 | 88.3 | 69.2 | 74.7 | |
| IPET | 62.9 | 89.6 | 71.2 | 78.4 |
注意:要准确地重现上述结果,请确保使用v1.1.0( --branch v1.1.0 )。
?设置
CLI用法
API使用
?训练自己的宠物
引用
宠物的所有要求都可以在requirements.txt中找到。您可以使用pip install -r requirements.txt安装所有必需的软件包。
该存储库中的命令行界面cli.py当前支持三种不同的培训模式(PET,IPET,监督培训),两种其他评估方法(无监督和启动)以及13个不同的任务。有关Yelp评论,AG的新闻,Yahoo问题,MNLI和X-Stance,请参阅原始论文以获取更多详细信息。有关8个超级工作任务,请参见本文。
要训练和评估其中一项任务的PET模型,只需运行以下命令:
python3 cli.py
--method pet
--pattern_ids $PATTERN_IDS
--data_dir $DATA_DIR
--model_type $MODEL_TYPE
--model_name_or_path $MODEL_NAME_OR_PATH
--task_name $TASK
--output_dir $OUTPUT_DIR
--do_train
--do_eval
在哪里
$PATTERN_IDS指定要使用的PVP。例如,如果您想使用所有模式,请指定PATTERN_IDS 0 1 2 3 4以获取AG的新闻和Yahoo问题或PATTERN_IDS 0 1 2 3用于Yelp评论和MNLI。$DATA_DIR是包含火车和测试文件的目录(检查tasks.py 。$MODEL_TYPE是所使用的模型的名称,例如albert , bert或roberta 。$MODEL_NAME是验证模型的名称(例如, roberta-large或albert-xxlarge-v2 )或预算模型的路径。$TASK_NAME是要训练和评估的任务的名称。$OUTPUT_DIR是训练有素的模型和评估结果的目录名称。您还可以为对应于单个PVP(前缀--pet_ )的PET模型的集合和最终序列分类模型(前缀--sc_ )指定各种训练参数。例如,用于我们的SuperGlue评估的默认参数是:
--pet_per_gpu_eval_batch_size 8
--pet_per_gpu_train_batch_size 2
--pet_gradient_accumulation_steps 8
--pet_max_steps 250
--pet_max_seq_length 256
--pet_repetitions 3
--sc_per_gpu_train_batch_size 2
--sc_per_gpu_unlabeled_batch_size 2
--sc_gradient_accumulation_steps 8
--sc_max_steps 5000
--sc_max_seq_length 256
--sc_repetitions 1
对于每个模式$P和重复$I ,运行以上命令创建一个目录$OUTPUT_DIR/p$Pi$I ,其中包含以下文件:
pytorch_model.bin :填充模型,可能与某些模型特定文件一起(例如, spiece.model , special_tokens_map.json )wrapper_config.json :使用的模型的配置train_config.json :用于培训的配置eval_config.json :用于评估的配置logits.txt :模型对未标记数据的预测eval_logits.txt :模型对评估数据的预测results.json :json:一个包含结果的JSON文件,例如模型的最终精度predictions.jsonl :以超级插曲格式设置的评估预测文件每个重复$I的最终(蒸馏)模型可以在$OUTPUT_DIR/final/p0-i$I中找到,其中包含与上述相同的文件。
如果您的GPU在训练过程中用完了内存,则可以尝试减少pet_per_gpu_train_batch_size和sc_per_gpu_unlabeled_batch_size ,同时增加pet_gradient_accumulation_steps和sc_gradient_accumulation_steps 。
要训练和评估一个受支持的任务之一的IPET模型,只需运行与上述相同的命令,而是用--method ipet替换--method pet 。您可以修改各种其他IPET参数;所有这些都带有--ipet_ 。
对于每一代$G ,模式$P和迭代$I ,这将创建一个目录$OUTPUT_DIR/g$G/p$Pi$I该目录与常规宠物结构结构。最终(蒸馏)模型可以再次在$OUTPUT_DIR/final/p0-i$I中找到。
如果您使用零培训示例的IPET,则需要在第一代中选择每个标签的示例数量,并且需要将缩小策略更改为表示: --ipet_n_most_likely 100 --reduction mean 。
要以有监督的方式训练和评估常规序列分类器,只需运行与上述相同的命令,但用--method sequence_classifier替换--method pet 。序列分类器有各种其他参数,您可以修改。所有这些都带有--sc_ 。
为了评估使用默认的PET模式和语言器的验证语言模型,但是如果不进行微调,请删除参数--do_train and add --no_distillation ,以免执行最终的蒸馏。
如果要使用启动,请删除参数--do_train并添加参数--priming --no_distillation ,以便将所有训练示例用于启动,并且不执行最终的蒸馏。
请记住,您可能需要将最大序列长度增加到更大的值,例如--pet_max_seq_length 5000 。这仅适用于支持如此长序列的语言模型,例如xlnet。对于使用XLNET,您可以指定--model_type xlnet --model_name_or_path xlnet-large-cased --wrapper_type plm 。
您还可以直接使用命令行接口,而是可以直接使用PET API,其中大多数是在pet.modeling中定义的。通过包括import pet ,您可以访问诸如train_pet , train_ipet和train_classifier之类的方法。查看他们的文档以获取更多信息。
要使用PET进行自定义任务,您需要定义两件事:
examples/custom_task_processor.py 。examples/custom_task_pvp.py 。实现了数据po仪和PVP后,您可以使用上述命令行训练PET模型。在下面,您可以找到有关如何定义PVP的两个组成部分,语言和模式的其他信息。
语言器用于将任务标签映射到自然语言的单词。例如,在二进制情感分类任务中,您可以将正面标签( +1 )映射到good一词,而负标签( -1 )则将其映射到bad一词。通过PVP的verbalize()方法来实现语言器。定义语言器的最简单方法是使用词典:
VERBALIZER = { "+1" : [ "good" ], "-1" : [ "bad" ]}
def verbalize ( self , label ) -> List [ str ]:
return self . VERBALIZER [ label ] 重要的是,在PET的当前版本中,默认情况下,语言器仅限于基础LMS词汇中的单个令牌(用于使用多个令牌,请参见下文)。给定语言模型的令牌,您可以通过验证len(tokenizer.tokenize(word)) == 1轻松检查一个单词是否与单个令牌相对应。
您还可以为单个标签定义多个语言。例如,如果您不确定哪些单词最能代表二进制情感分类任务中的标签,则可以按以下方式定义您的口语:
VERBALIZER = { "+1" : [ "great" , "good" , "wonderful" , "perfect" ], "-1" : [ "bad" , "terrible" , "horrible" ]}模式用于使语言模型理解给定的任务;它们必须完全包含一个<MASK>令牌,该令牌必须使用Verbalizer填充。对于基于评论的摘要( <A> )和身体( <B> )的二进制情感分类,可以是<A>. <B>. Overall, it was <MASK>.模式通过PVP的get_parts()方法实现,该方法返回一对文本序列(每个序列都由字符串列表表示):
def get_parts ( self , example : InputExample ):
return [ example . text_a , '.' , example . text_b , '.' ], [ 'Overall, it was ' , self . mask ]如果您不想使用一对序列,则可以简单地将第二个序列留空:
def get_parts ( self , example : InputExample ):
return [ example . text_a , '.' , example . text_b , '. Overall, it was ' , self . mask ], []如果要定义几种模式,只需使用PVP S pattern_id属性:
def get_parts ( self , example : InputExample ):
if self . pattern_id == 1 :
return [ example . text_a , '.' , example . text_b , '.' ], [ 'Overall, it was ' , self . mask ]
elif self . pattern_id == 2 :
return [ 'It was just ' , self . mask , '!' , example . text_a , '.' , example . text_b , '.' ], []使用命令行训练模型时,请指定要使用的所有模式(例如--pattern_ids 1 2 )。
重要的是,如果序列长于基础LM的指定最大序列长度,则PET必须知道输入的哪些部分可以缩短,哪些部分不能(例如,蒙版令牌必须始终存在)。因此, PVP提供了一种shortenable()方法,以表明可以缩短一段文本:
def get_parts ( self , example : InputExample ):
text_a = self . shortenable ( example . text_a )
text_b = self . shortenable ( example . text_b )
return [ text_a , '.' , text_b , '. Overall, it was ' , self . mask ], []默认情况下,当前的PET和IPET实现仅支持一组固定的标签,这些标签在与单个令牌相对应的所有示例和语言器中共享。但是,对于某些任务,可能有必要使用与多个令牌相对应的语言器(如下所述)。为此,您只需要以下两个修改:
在任务的dataprocessor中添加以下行(请参阅examples/custom_task_processor.py ):
from pet . tasks import TASK_HELPERS
from pet . task_helpers import MultiMaskTaskHelper
TASK_HELPERS [ 'my_task' ] = MultiMaskTaskHelper 'my_task'是您任务的名称。
在您的PVP中,请确保get_parts()方法始终插入任何口头化所需的掩码令牌数量。例如,如果您的语言映射+1将“真的很棒”和-1 to“可怕”,如果将这些映射为["really", "awe", "##some"]和["terrible"] ,则您的get_parts()方法应该始终返回一个包含3个掩码标记的序列。
通过此修改,您现在可以使用由多个令牌组成的语言器:
VERBALIZER = { "+1" : [ "really good" ], "-1" : [ "just bad" ]}但是,需要考虑几个限制:
MultiMaskTaskHelper时,评估的最大批量大小为1。MultiMaskTaskHelper类是未经彻底测试的实验功能。特别是,此功能仅对PET进行了测试,而不是针对IPET进行了测试。如果您观察到奇怪的东西,请提出一个问题。为了获得更大的灵活性,您还可以编写自定义TaskHelper 。作为起点,您可以在pet/task_helpers.py中查看CopaTaskHelper , WscTaskHelper和RecordTaskHelper类。
如果您在此存储库中使用代码,请引用以下论文:
@article{schick2020exploiting,
title={Exploiting Cloze Questions for Few-Shot Text Classification and Natural Language Inference},
author={Timo Schick and Hinrich Schütze},
journal={Computing Research Repository},
volume={arXiv:2001.07676},
url={http://arxiv.org/abs/2001.07676},
year={2020}
}
@article{schick2020small,
title={It's Not Just Size That Matters: Small Language Models Are Also Few-Shot Learners},
author={Timo Schick and Hinrich Schütze},
journal={Computing Research Repository},
volume={arXiv:2009.07118},
url={http://arxiv.org/abs/2009.07118},
year={2020}
}