【自然语言处理】【文本生成】Transformers中使用约束Beam Search指导文本生成
Transformers中使用约束Beam Search指导文本生成
原文地址:https://huggingface.co/blog/constrained-beam-search
相关博客
【自然语言处理】【ChatGPT系列】InstructGPT:遵循人类反馈指令来训练语言模型
【自然语言处理】【ChatGPT系列】大模型的涌现能力
【自然语言处理】【文本生成】CRINEG Loss:学习什么语言不建模
【自然语言处理】【文本生成】使用Transformers中的BART进行文本摘要
【自然语言处理】【文本生成】Transformers中使用约束Beam Search指导文本生成
【自然语言处理】【文本生成】Transformers中用于语言生成的不同解码方法
【自然语言处理】【文本生成】BART:用于自然语言生成、翻译和理解的降噪Sequence-to-Sequence预训练
【自然语言处理】【文本生成】UniLM:用于自然语言理解和生成的统一语言模型预训练
【自然语言处理】【多模态】OFA:通过简单的sequence-to-sequence学习框架统一架构、任务和模态
一、简介
不同于普通的beam search
,约束beam search
允许对文本生成的输出施加约束。这很有用,因为有时是确切知道在输出中需要什么。举例来说,在神经机器翻译中,可以知道哪些单词必须包含在最终的翻译中的。有时,由于特定的上下文,对于语言模型来说很有可能生成不满足用于期望的非结构。这两种情况都能够通过用户告诉模型输出结果中必须包含的单词来解决。
二、为什么困难
然而,这并不是一个简单的问题。这是因为该任务需要在生成过程中的某些位置上强制生成确定的子序列。
举例来说,若希望生成一个必须包含短语p1={t1,t2}p_1=\{t_1,t_2\}p1={t1,t2}的句子SSS。定义一个期望句子SSS为:
Sexpected={s1,s2,…,t1,t2,sk+1,…,sn}S_{expected}=\{s_1,s_2,\dots,t_1,t_2,s_{k+1},\dots,s_n\} Sexpected={s1,s2,…,t1,t2,sk+1,…,sn}
问题是beam search
生成序列是token-by-token
的。虽然不完全准确,可以将beam search
看作是函数B(s0:i)=si+1B(\textbf{s}_{0:i})=s_{i+1}B(s0:i)=si+1,其基于已经生成的0
到i
的token
序列来预测i+1
的下一个单词。但是该函数如何才能知道,在一个任意的步骤i<ki<ki<k,token
必须在未来的步骤kkk上生成特定的token
?或者当其在时间步i=ki=ki=k时,如何能够知道当前是生成token的最佳步骤,而不是未来的时间步i>ki>ki>k?
若是有不同需求的多个约束呢?若是希望强制生成短语p1={t1,t2}p_1=\{t_1,t_2\}p1={t1,t2}和p2={t3,t4,t5,t6}p_2=\{t_3,t_4,t_5,t_6\}p2={t3,t4,t5,t6}?若是希望模型在两个短语中选择呢?若是想强制生成短语p1p_1p1和短语列表{p21,p22,p23}\{p_{21},p_{22},p_{23}\}{p21,p22,p23}中的一个短语呢?
上面的例子都是非常合理的用例,正如下面展示的那样,新的约束beam search
将会解决这些用例。
三、例子一:Forcing a Word
举例来说,尝试翻译How old are you?
为德语。Wie alt bist du?
是在非正式场合会说的话,Wie alt sind Sie?
则是正式场合会说的话。更加上下文,可能需要其中的某一种形式,那么该如何告诉模型呢?
1. 传统Beam Search
from transformers import AutoTokenizer, AutoModelForSeq2SeqLMtokenizer = AutoTokenizer.from_pretrained("t5-base")
model = AutoModelForSeq2SeqLM.from_pretrained("t5-base")encoder_input_str = "translate English to German: How old are you?"input_ids = tokenizer(encoder_input_str, return_tensors="pt").input_idsoutputs = model.generate(input_ids,num_beams=10,num_return_sequences=1,no_repeat_ngram_size=1,remove_invalid_values=True,
)print("Output:\n" + 100 * '-')
print(tokenizer.decode(outputs[0], skip_special_tokens=True))
输出:
Output:
----------------------------------------------------------------------------------------------------
Wie alt bist du?
2. 约束Beam Search
若希望输出的是正式场合的表达,而不是非正式场合?若通过先验知识知道生成必须包含的内,能够把其注入至生成中吗?
下面是在model.generate()
中参数force_words_ids
来实现该功能:
tokenizer = AutoTokenizer.from_pretrained("t5-base")
model = AutoModelForSeq2SeqLM.from_pretrained("t5-base")encoder_input_str = "translate English to German: How old are you?"force_words = ["Sie"]input_ids = tokenizer(encoder_input_str, return_tensors="pt").input_ids
force_words_ids = tokenizer(force_words, add_special_tokens=False).input_idsoutputs = model.generate(input_ids,force_words_ids=force_words_ids,num_beams=5,num_return_sequences=1,no_repeat_ngram_size=1,remove_invalid_values=True,
)print("Output:\n" + 100 * '-')
print(tokenizer.decode(outputs[0], skip_special_tokens=True))
输出:
Output:
----------------------------------------------------------------------------------------------------
Wie alt sind Sie?
可以看到,能够使用先验知识来指定生成。先前,必须生成一堆可能的输出,然后过滤出满足我们需求的。现在可以在生成阶段直接进行。
四、例子二:Disjunctive Constraints
在上面的例子中,我们是知道最终想要包含的单词。该场景的例子是在神经机器翻译中使用字典查找。
但是如果不知道单词的具体形式,希望等可能的输出[raining, rained, rains,…][\text{raining, rained, rains,}\dots][raining, rained, rains,…]呢? 在更通用的场景中,总会存在一些情况不希望逐词、逐字的准确单词,并且可能需要考虑其他相关的可能。允许这种行为的约束称为Disjunctive Constraints
,其允许用户输入单词列表并指导最终的输出必须包含单词列表中的至少1个词。
下面是一个混合了两种类型约束的例子:
from transformers import GPT2LMHeadModel, GPT2Tokenizermodel = GPT2LMHeadModel.from_pretrained("gpt2")
tokenizer = GPT2Tokenizer.from_pretrained("gpt2")force_word = "scared"
force_flexible = ["scream", "screams", "screaming", "screamed"]force_words_ids = [tokenizer([force_word], add_prefix_space=True, add_special_tokens=False).input_ids,tokenizer(force_flexible, add_prefix_space=True, add_special_tokens=False).input_ids,
]starting_text = ["The soldiers", "The child"]input_ids = tokenizer(starting_text, return_tensors="pt").input_idsoutputs = model.generate(input_ids,force_words_ids=force_words_ids,num_beams=10,num_return_sequences=1,no_repeat_ngram_size=1,remove_invalid_values=True,
)print("Output:\n" + 100 * '-')
print(tokenizer.decode(outputs[0], skip_special_tokens=True))
print(tokenizer.decode(outputs[1], skip_special_tokens=True))
输出:
Output:
----------------------------------------------------------------------------------------------------
The soldiers, who were all scared and screaming at each other as they tried to get out of the
The child was taken to a local hospital where she screamed and scared for her life, police said.
可以看到,第一个输出使用了screaming
,第二个输出使用了screamed
,并且两个输出都使用了scared
。待选择的列表不一定是单词的形式,其可以是任何需要从单词列表中至少选择一个的。
五、传统Beam Search
不同于greedy search
,beam search
需要保存一个较长的hypotheses
列表。下面是在num_beams=3
的情况下,展示的beam search
第一步:
相比于greedy search
仅选择The dog
,beam search
允许进一步考虑The nice
和The car
。在下一步中,将在上个步骤的三个分支上考虑接下来可能的tokens
。
虽然最终考虑的输出远不止num_beams
,但是在最后的时间步中缩减至num_beams
。beam search
不能一直往外延伸,beams
的数量在nnn个时间步为beamsn\text{beams}^nbeamsn,其会非常快就达到非常大的情况。
对于生成的其余部分,重复上面的步骤直至满足结束标准,例如生成<eos> token
或者达到max_length
。延伸、排序、缩减、重复。
六、约束Beam Search
约束beam search
通过在每个生成步上注入期望的tokens来实现约束。
若要求在生成的输出中强制包含短语is fast
。在传统的beam search
设置中,在每个分支中寻找最可能的kkk个下一个toekens
,并且将其附近在末尾用于后续的考虑。在约束设置中,在做同样操作的同时,通过追加特定的token
来逐步实现约束。
在常见的高概率下一个词dog
和nice
上方,强制添加is
来使得更加接近实现约束is fast
。
对于下一个步骤,扩展的候选与传统的beam search
基本相同。就像上面的例子一样,约束beam search
通过在每个分支上添加约束来添加新的候选:
Banks
在讨论下一步之前,需要思考在上一步中所看到的不期望的行为。若单纯的强制在输出中包含is fast
,大多数时候仅会得到像The is fast
这样没有意义的输出。这个问题不容忽视。
Banks
通过在实现约束和创造合理输出之间取得平衡来解决这个问题。Bank n
在实现约束时已经进行了nnn步的beamns
列表。在各自对应的banks
中对所有可能的beams
进行排序,然后做循环筛选。在上面的例子中,从Bank 2
选择最可能的输出,从Bank 1
选择最可能的输出,从Bank 0
选择最可能的输出,从Bank 2
选择第二可能的输出,从Bank 1
选择第二可能的输出,以此类推。由于上面的例子中num_beams=3
,那么仅需要重复上面的过程三次就可以得到The is fast
、The dog is
和The dog and
。
通过这种方式,即使我们强制模型考虑人工添加的分支,但是仍然可以追踪其他更有意义的高概率序列。即使The is fast
完成的实现了约束,其也不是一个合理的短语。幸运的是,仍然有The dog is
和The dog and
能够在未来的时间步中使用,其在后面可能会带来更加合理的输出。
下面是该行为在第3个时间步的结果示例:
注意,The is fast
不需要人工添加任何约束token
,因为其已经实现了约束。此外,The dog is slow
或者The dog is mad
实际上在Bank 0
,虽然其包含token is
,但其必须从头开始生成is fast
。通过在is
后追加slow
,能够有效的重置进度。
盲目的追加期望的token
会导致像The is fast
这样无意义的短语。然而,从banks
中使用循环选择,最终可以摆脱无意义的输出,而选择更加合理的输出。
七、约束类和常用约束
上面的结论可以总结如下。在每个时间步,我们不断的催促模型来考虑能够实现约束的tokens
,同时跟踪不满足约束的beams
,直至最终得到包含期望短语的合理高概率序列。
因此,设计这种实现的一个准则是将每个约束表示为一个Constraint
对象,其目的是跟踪进度并告诉beam search
下一个生成的tokens
。尽管已经在model.generate()
中添加了关键字参数force_words_ids
,下面是在后端实际发生的情况:
from transformers import AutoTokenizer, AutoModelForSeq2SeqLM, PhrasalConstrainttokenizer = AutoTokenizer.from_pretrained("t5-base")
model = AutoModelForSeq2SeqLM.from_pretrained("t5-base")encoder_input_str = "translate English to German: How old are you?"constraints = [PhrasalConstraint(tokenizer("Sie", add_special_tokens=False).input_ids)
]input_ids = tokenizer(encoder_input_str, return_tensors="pt").input_idsoutputs = model.generate(input_ids,constraints=constraints,num_beams=10,num_return_sequences=1,no_repeat_ngram_size=1,remove_invalid_values=True,
)print("Output:\n" + 100 * '-')
print(tokenizer.decode(outputs[0], skip_special_tokens=True))
输出:
Output:
----------------------------------------------------------------------------------------------------
Wie alt sind Sie?
你也可以自己定义约束,并将其输入至constraints
关键字参数中。你必须创建一个Constraint
抽象接口类的子类,并遵循其要求。
一些独特的想法,包括像OrderedConstraints
、TemplateConstraints
等后续会被添加。目前,生成是通过包含输出中任何位置的序列来实现的。举例来说,先前的例子中有一个序列具有scared->screaming
和另一个序列screamed->scared
。OrderedConstraints
能够允许用户指定约束实现的顺序。
TemplateConstraints
可以允许更加小众的功能,其目标类似于:
starting_text = "The woman"
template = ["the", "", "School of", "", "in"]possible_outputs == ["The woman attended the Ross School of Business in Michigan.","The woman was the administrator for the Harvard School of Business in MA."
]
或者
starting_text = "The woman"
template = ["the", "", "", "University", "", "in"]possible_outputs == ["The woman attended the Carnegie Mellon University in Pittsburgh.",
]
impossible_outputs == ["The woman attended the Harvard University in MA."
]
【自然语言处理】【文本生成】Transformers中使用约束Beam Search指导文本生成相关推荐
- 分号的html文本,在Vue中利用v-HTML按分号将文本换行的例子_輕微_前端开发者
最近在开发的时候遇到这样一个需求,需要将一段文本按照分号(有中文分号和英文分号)进行换行操作. 如下: 换行前:雷军,2457.66万,自然人股东;洪锋,169.51万,自然人股东;黎万强,10.33 ...
- 从富文本(html字符串)中获取图片,js获取富文本中的第一张图片(正则表达式)
js获取富文本中的第一张图片url正则公式及去除字符串里面的html标签 后台发来一个富文本字符串里面可能包含了0.1.2.3-个图片标签(img),我们的任务是获取这个字符串里面第一张图片的url, ...
- 【NLP】使用 LSTM 和Beam Search进行文本自动完成
- 【自然语言处理】【文本生成】Transformers中用于语言生成的不同解码方法
Transformers中用于语言生成的不同解码方法 原文地址:https://huggingface.co/blog/how-to-generate 相关博客 [自然语言处理][ChatGPT系列] ...
- 文本生成任务之营销文本生成(Seq2seq+attention、Pointer Generator Network、Converage、Beam Search、优化技巧、文本增强)
文章目录 引言 项目任务简介 0. 数据预处理 0.1 将json文件转化成txt文件 0.2 词典处理 0.3 自定义数据集SampleDataset(Dataset类) 0.4 生成Dataloa ...
- 【CSS】文字溢出问题 ( 强制文本在一行中显示 | 隐藏文本的超出部分 | 使用省略号代替文本超出部分 )
文章目录 一.文字溢出问题 二.文字溢出处理方案 三.代码示例 一.文字溢出问题 在元素对象内部显示文字 , 如果文本过长 , 则会出现文本溢出的问题 ; 下面的示例中 , 在 150x25 像素的盒 ...
- html文本分类输出,手把手教你用 TensorFlow 实现文本分类(上)
雷锋网(公众号:雷锋网)按:本文作者张庆恒,原文载于作者个人博客,雷锋网已获授权. 由于需要学习语音识别,期间接触了深度学习的算法.利用空闲时间,想用神经网络做一个文本分类的应用, 目的是从头到尾完成 ...
- 深度学习与自然语言处理教程(8) - NLP中的卷积神经网络(NLP通关指南·完结)
作者:韩信子@ShowMeAI 教程地址:https://www.showmeai.tech/tutorials/36 本文地址:https://www.showmeai.tech/article-d ...
- 文本自动生成研究进展与趋势之图像到文本的生成
图像到文本的生成 1 国际研究现状 图像到文本的生成技术是指根据给定的图像生成描述该图像内容的自然语言文本,例如新闻图像附带的标题.医学图像附属的说明.儿童教育中常见的看图说话.以及用户在微博等互联网 ...
最新文章
- 【计算理论】计算理论总结 ( 非确定性有限自动机 NFA 转为确定性有限自动机 DFA | 示例 ) ★★
- JavaScript之手写Promise
- 利用urllib3 抓取博客列表
- 通过堡垒机登陆服务器脚本
- Java基础:等待唤醒机制、线程池
- pycharm 改成中文亲测好用
- java 编辑pdf表格_Java 生成pdf表格文档
- 关于第一次深度学习项目的总结
- 您使用的是不受支持的命令行标记 -no-sandbox
- mysql系统设计论文_毕业论文管理系统的设计与实现(MyEclipse,MySQL)
- C#根据当前时间获取周,月,季度,年度等时间段的起止时间
- 景山中学 计算机教师 创客,创客背景下中学信息技术教学的创新研究
- 万字总结复杂而奇妙的高斯过程!
- 架构与开发语言 购OA最重要的两个核心
- Word 打开WPS文档成乱码的解决方法(转)
- CSU-2220 Godsend
- 如何获得财务数据信息
- [附源码]Python计算机毕业设计SSM隆庆祥企业服装销售管理系统(程序+LW)
- android auto 能微信_OPPO手环用上Android Auto,可回复微信消息
- Unity学习笔记(四)—— 制作第三个小游戏(像模像样的)