问题生成是自动从文本段落中生成问题的任务。这样做的最直接方法是回答意识到的问题产生。在回答问题中,该模型带有答案和段落,并要求通过考虑段落上下文来为该答案产生一个问题。虽然有许多QG任务的论文,但它仍然不像QA那样主流。原因之一是大多数较早的论文都使用复杂的模型/处理管道,并且没有可用的预培训模型。最近,很少有unilm和prophetnet具有SOTA预先培训的权重,但使用情况似乎很复杂。
该项目的目的是使用直接前向的端到端方法进行的,没有太多复杂的管道,针对预训练的变压器(特别是SEQ-2-SEQ模型)进行了问题的开源研究。目的是提供简化的数据处理和培训脚本,并易于使用管道进行推理。
如下所述,使用Squeadv1数据集和T5模型进行了初始实验。
对于回答意识模型,可以通过两种方式处理输入文本。
1。预端格式:
在这里,答案简单地添加到上下文之前,并被sep令牌分开。例如
42 [SEP] 42 is the answer to life, the universe and everything.
对于T5模型,输入是这样处理的
answer: 42 context: 42 is the answer to life, the universe and everything.
2。高光格式
在这里,答案跨度在文本中突出显示,并带有特殊的高光令牌。
<hl> 42 <hl> is the answer to life, the universe and everything.
这个想法是在“问题生成的基于BERT的经常性模型”中提出的。请参阅第4.3节
由于答案意识模型需要答案来生成问题,因此我们需要一些可以从文本中提取跨度的答案。这可以使用NER,名词 - 词组缩放等各种方法来完成,但是在这里,训练了一个模型来提取跨度的答案,以查看其将如何工作。使用T5,使用文本对形式进行答案散文。
由于高光格式需要知道提取答案的位置跨度跨度跨度,因此提取的输入如下。
<hl>令牌突出显示句子。<sep>令牌加入该句子中的答案。例如,本文
Python is a programming language. Created by Guido van Rossum and first released in 1991.
将创建以下示例
输入文本: <hl> Python is a programming language. <hl> Created by Guido van Rossum and first released in 1991.
目标文本: Python <sep>
和
输入文本: Python is a programming language. <hl> Created by Guido van Rossum and first released in 1991 <hl>.
目标文本: Guido van Rossum <sep> 1991 <sep>
在推理时,文本被分为句子,每个句子都会突出显示。
对于答案的问题生成,我们通常需要3个模型,首先将提取跨越跨度的答案,第二个模型将在该答案上产生问题,第三个模型将是一个质量检查模型,它将采用问题并产生答案,然后我们可以比较两个答案,以查看生成的问题是否正确。
拥有3种单个任务模型是很复杂的,因此目标是创建一个可以完成所有这3个任务的多任务模型
如本文所述,使用任务前缀以多任务方式对T5模型进行微调。
在端到端问题生成中,该模型可以生成问题而无需提供答案。本文更详细地讨论了这些想法。在这里,T5模型经过培训,可以通过提供上下文来同时产生多个问题。这些问题被<sep>令牌分开。这是处理示例的方式
输入文本: Python is a programming language. Created by Guido van Rossum and first released in 1991.
目标文本: Who created Python ? <sep> When was python released ? <sep>
所有培训细节都可以在此WandB项目中找到
使用上述方法在Squad1.0 Dev设置上的结果。为了解码,使用num_beams 4的光束搜索,最大解码长度设置为32。
对于多任务QA-QG模型,EM和F1分数被私有为QA-EM和QA-F1。
NLG-Eval软件包用于计算指标。
| 姓名 | bleu-4 | 流星 | 胭脂-l | Qa-em | QA-F1 | QG形式 |
|---|---|---|---|---|---|---|
| T5-base-QG-HL | 21.3226 | 27.0854 | 43.5962 | - | - | 强调 |
| T5-base-QA-QG-HL | 21.0141 | 26.9113 | 43.2484 | 82.46 | 90.272 | 强调 |
| T5-SMALL-QA-QG-HL | 18.9872 | 25.2217 | 40.7893 | 76.121 | 84.904 | 强调 |
| T5-SMALL-QG-HL | 18.5921 | 24.9915 | 40.1886 | - | - | 强调 |
| t5-small-qg prepend | 18.2791 | 24.6722 | 39.958 | - | - | 预登 |
transformers==3.0.0
nltk
nlp==0.2.0 # only if you want to fine-tune.
安装nltk后
python -m nltk.downloader punkt使用模拟器管道?变形金刚管道简单推断。
管道分为3个任务
question-generation :用于单个任务问题生成模型。multitask-qa-qg :用于多任务QA,QG型号。e2e-qg :用于端到端问题生成。 from pipelines import pipeline
nlp = pipeline ( "question-generation" )
nlp ( "42 is the answer to life, the universe and everything." )
= > [{ 'answer' : '42' , 'question' : 'What is the answer to life, the universe and everything?' }]预端格式
nlp = pipeline ( "question-generation" , model = "valhalla/t5-small-qg-prepend" , qg_format = "prepend" )
nlp ( "42 is the answer to life, the universe and everything." )
= > [{ 'answer' : '42 ' , 'question' : 'What is the answer to life, the universe, and everything?' }] nlp = pipeline ( "multitask-qa-qg" )
# to generate questions simply pass the text
nlp ( "42 is the answer to life, the universe and everything." )
= > [{ 'answer' : '42' , 'question' : 'What is the answer to life, the universe and everything?' }]
# for qa pass a dict with "question" and "context"
nlp ({
"question" : "What is 42 ?" ,
"context" : "42 is the answer to life, the universe and everything."
})
= > 'the answer to life, the universe and everything' nlp = pipeline ( "e2e-qg" )
nlp ( "Python is a programming language. Created by Guido van Rossum and first released in 1991." )
= > [
'What is a programming language?' ,
'Who created Python?' ,
'When was Python first released?'
]默认情况下,这两个管道都将使用T5-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-MALL*模型通过model参数传递路径。
默认情况下, question-generation管道将以highlight光格式下载valhalla/t5-small-qg-hl型号。如果要使用预端格式,请提供预端模型的路径,并将qg_format设置为"prepend" 。为了像跨度一样提取答案,它使用valhalla/t5-small-qa-qg-hl模型,您可以通过ans_model参数提供不同的模型。
multitask-qa-qg模型适用于可以提取跨度,do QG和QA的答案的多任务模型,因此它不需要单独的ans_model 。默认情况下,Valhalla/T5-Small-QA-QG-HL模型用于highlight格式。如果要使用预端格式,请提供预端模型的路径,并将qg_format设置为"prepend"
e2e-qg管道用于端到端问题生成。这些模型可以在没有答案监督的情况下同时产生多个问题。默认情况下,它使用valhalla/t5-small-e2e-qg
为了支持不同的数据格式,培训师期望预处理的缓存数据集,因此您可以按照所需的方式处理数据。缓存__getitem__数据集应使用torch.save保存,并应返回source_ids , target_ids , attention_mask键的dict 。
source_ids :编码的源文本target_ids :编码目标文本attention_mask :源掩码source_ids T2TDataCollator负责准备正确的input_ids和labels 。它还动态修剪批次以去除过多的填充令牌,以加快训练的速度。
data/squad_multitask包含修改后的小队数据集,以进行答案问题生成(同时使用预处和突出显示格式),问题答案(文本到文本),答案提取和端到端问题生成。可以使用Awesome加载此数据集? nlp库,这使得处理非常容易。
要处理和缓存数据集使用prepare_data.py脚本。它将根据model_type参数加载正确的令牌。它将两个新的令牌<sep>和<hl>添加到令牌中,并将其保存在{model_type}_qg_tokenizer路径上。您应该将此令牌传递给微调脚本。
数据集将保存在data/目录中。您应该使用train_file_name和valid_file_name参数提供文件名。
单个任务问题生成的处理数据,亮点_qg_format
python prepare_data.py
--task qg
--model_type t5
--dataset_path data/squad_multitask/
--qg_format highlight_qg_format
--max_source_length 512
--max_target_length 32
--train_file_name train_data_qg_hl_t5.pt
--valid_file_name valid_data_qg_hl_t5.pt 多任务QA-QG的过程数据使用righlight_qg_format
valid_for_qg_only参数用于确定验证集是否应仅包含QG任务的数据。对于我的多任务实验,我仅使用QG任务使用验证数据,以便可以将评估损失曲线与其他单个任务模型进行比较
python prepare_data.py
--task multi
--valid_for_qg_only
--model_type t5
--dataset_path data/squad_multitask/
--qg_format highlight_qg_format
--max_source_length 512
--max_target_length 32
--train_file_name train_data_qa_qg_hl_t5.pt
--valid_file_name valid_data_qg_hl_t5.pt 端到端问题生成的过程数据集
python prepare_data.py
--task e2e_qg
--valid_for_qg_only
--model_type t5
--dataset_path data/squad_multitask/
--qg_format highlight_qg_format
--max_source_length 512
--max_target_length 32
--train_file_name train_data_e2e_qg_t5.pt
--valid_file_name valid_data_e2e_qg_t5.pt 使用run_qg.py脚本开始培训。它使用变形金刚Trainer课程训练模型。
python run_qg.py
--model_name_or_path t5-small
--model_type t5
--tokenizer_name_or_path t5_qg_tokenizer
--output_dir t5-small-qg-hl
--train_file_path data/train_data_qg_hl_t5.pt
--valid_file_path data/valid_data_qg_hl_t5.pt
--per_device_train_batch_size 32
--per_device_eval_batch_size 32
--gradient_accumulation_steps 8
--learning_rate 1e-4
--num_train_epochs 10
--seed 42
--do_train
--do_eval
--evaluate_during_training
--logging_steps 100或者,如果您想从脚本或笔记本上训练它,则
from run_qg import run_qg
args_dict = {
"model_name_or_path" : "t5-small" ,
"model_type" : "t5" ,
"tokenizer_name_or_path" : "t5_qg_tokenizer" ,
"output_dir" : "t5-small-qg-hl" ,
"train_file_path" : "data/train_data_qg_hl_t5.pt" ,
"valid_file_path" : "data/valid_data_qg_hl_t5.pt" ,
"per_device_train_batch_size" : 32 ,
"per_device_eval_batch_size" : 32 ,
"gradient_accumulation_steps" : 8 ,
"learning_rate" : 1e-4 ,
"num_train_epochs" : 10 ,
"seed" : 42 ,
"do_train" : True ,
"do_eval" : True ,
"evaluate_during_training" : True ,
"logging_steps" : 100
}
# start training
run_qg ( args_dict )使用eval.py脚本评估模型。
python eval.py
--model_name_or_path t5-base-qg-hl
--valid_file_path valid_data_qg_hl_t5.pt
--model_type t5
--num_beams 4
--max_decoding_length 32
--output_path hypothesis_t5-base-qg-hl.txt这将使输出将输出保存在{output_path}文件中。
计算指标安装NLG-eval软件包并运行
nlg-eval --hypothesis=hypothesis_t5-base-qg-hl.txt --references=data/references.txt --no-skipthoughts --no-glove