了解Transformer模型结构后,对于LLM模型文本生成过程是有些疑问:
-
一段长句子作为输入,编码后也会得到多个token对应的embedding,那么哪个embedding用于预测下一个token?
-
预测到下一个token的概率后,LLM模型是怎么生成完整回答的?
-
为什么相同的输入会有不同的回答,这种随机性是如何实现的?
上半部分主要介绍模型推理生成和Huggingface库常用的一些参数原理,下半部分介绍采样解码策略,以及不同解码策略对文本生成的随机性和多样性的影响。
1.模型推理预测过程
以ChatGLM3为例,输入一个词say,经过模型最终预测出下一个词为goodbye。具体预测过程下面分步进行解释。
text:
say
inputs_tokenizer:
{'input_ids': tensor([[64790, 64792, 1105]]), 'attention_mask': tensor([[1, 1, 1]]), 'position_ids': tensor([[0, 1, 2]])}
input_ids:
[ ]
Logits Shape:
3, 65024])
logits:
-5.9922, 0.5942, ..., -5.9922, -5.9922, -5.9922],
-3.1309, 2.7383, ..., -3.1309, -3.1309, -3.1309],
-1.5791, 9.4688, ..., -1.5801, -1.5791, -1.5801]]],
dtype=torch.float16, grad_fn=<ToCopyBackward0>)
logits tensor max value:
5.3477, 15.9766], dtype=torch.float16,
grad_fn=<MaxBackward0>)
logits tensor max index:
30930, 25330])
next_token:
25330
next_word:
goodbye
2.模型文本生成策略
先回答之前的疑问:
-
“say goodbye”作为输入,编码后也会得到四个token对应的embedding。那么哪个embedding用于预测下一个token?
答:根据上文可知,LLM模型在推理时,根据当前输入序列最后一个token对应的embedding预测下一个token。因为Transformer模型结构使用masked attention,每个token在编码时都只会和他前面的token交互。那么最后一个token自然就包括了当前序列的所有信息,因此用于预测下一个token是最合理的。
-
预测到下一个token的概率后,LLM模型是怎么生成完整回答的?为什么相同的输入会有不同的回答?这种随机性是如何实现的?
答:LLM模型不是直接使用贪心解码策略(greedy decoding),即选择概率最大的那个token作为输出。因为使用贪心解码策略,对于相同的输入序列LLM模型每次都会给出一样的回答,推理模式下所有参数都固定,不存在随机性。
3.常用参数说明
3.1 temperature
temperature参数用于控制生成文本的随机性和多样性,调整模型输出的logits张量的概率分布。
logits张量维度大小为[1, 4],将logits输入到softmax函数中,分别计算没有temperature,以及temperature为0.5和temperature为2的情况下的概率分布:
-
temperature较高接近1时,归一化后的概率分布越均匀,导致生成的文本更具随机性和多样性;
-
temperature较低接近0时,归一化后的概率分布越陡峭,倾向于选择概率最高的token,导致生成的文本更加确定和集中。
-
temperature大于1时,则随机性增大,有效信息降低,0则相当于只是用argmax/max贪心解码策略 ,inf则相当于均匀采样。
3.2 top-k
top-k参数,用于生成下一个token时,限制LLM模型只能考虑前k个概率最高的token,可以降低模型生成无意义或重复的输出的概率,同时提高模型的生成速度和效率。
当top_k为2时,只取概率值前2的参与采样。
3.3 top-p
top-p也是一个用于控制生成文本多样性的参数。这个参数的全名是"top probability",通常用一个介于 0 到 1 之间的值来表示,在生成下一个token时,概率分布中选择的最高概率累积阈值。
当top_p较高时,比如 0.9,这意味着前 90% 的概率的token会被考虑在采样中,会有更多的token参与采样,增加生成文本的多样性。
当top_p较低时,只有前 10% 最高概率的token会被考虑在采样中。
如下图,当top_p为0.1时,只有1个概率值参与采样预测,这样会限制生成文本的可能性,使生成的文本更加确定和集中。
当top-p设置非常小时,累加的概率没超过top-p,一般会强制至少选出一个token。
3.4 num_beams
num_beams参数是用于束搜索策略(beam search),控制生成的候选句子的数量,该参数控制的是每个生成步要保留的生成结果的数量,用于在生成过程中增加多样性或生成多个可能的结果。
束搜索策略(beam search)本质上也是一个贪心解码策略 (greedy decoding) ,所以无法保证一定可以得到最好的结果。
步骤如下:
-
在每个生成步骤中,都保留着 top K(K 即 num_beams 参数的值) 个可能的候选单词。
-
这 K 个单词都做下一步 decoding,分别选出 top K,然后对这 K^2 个候选句子再保留前 K 个最可能的结果。
-
如果已经生成了结束符,则将其对应的结果保留下来。
-
重复上述过程直到生成所有的结果或达到最大长度。
例如,当num_beams等于5时,生成5个不同的结果。
3.5 num_beam_groups
num_beam_groups参数其实是一种束搜索(beam search)算法的改进,叫做Diverse Beam Search (DBS).
束搜索(beam search)生成的结果还是会过于相似的,DBS做了一些改进,核心就是分组机制。
例如,当 num_beams=2,num_beam_groups=2,分成2个组,每个组里的beam可以相似,但组和组之间要有足够的多样性。
3.6 num_return_sequences
num_return_sequences参数是模型返回不同的文本序列的数量,要和num_beams值一致。
例如,当num_beams等于5,num_return_sequences也等于5时,生成5个不同的结果。
注:在贪心解码策略 (greedy decoding) 中,num_return_sequences只能为1,默认也为1。
3.7 do_sample
do_sample参数控制对模型计算出来的概率,是否进行多项式采样。
多项式采样(Multinomial Sampling)是一种用于从一个具有多个可能结果的离散概率分布中进行随机抽样的方法,多项式采样的步骤如下:
-
首根据概率分布对应的概率,为每个可能结果分配一个抽样概率。这些抽样概率之和必须为1。
-
会生成一个随机数,然后根据抽样概率选择结果。抽样概率越高的结果,被选中的概率也就越大。
-
最终,被选中的结果就是这次抽样的输出。
多项式采样概率高的结果更有可能被选中,但不同于确定性的选择,每个结果仍然有一定的概率被选中。
这使得模型在生成文本时具有一定的随机性,但又受到概率的控制,以便生成更加多样且符合概率分布的文本。
例如,使用多项式采样(Multinomial Sampling)后,下一个token为0.6439对应的索引3。
这个do_sample参数通过多样式采样会有一定的随机性,这种随机性导致了生成的文本更加多样化,因为模型有机会选择概率较低但仍然可能的词,这种方法可以产生丰富、有趣、创新的文本,但可能会牺牲一些文本的准确性。
4. 其他参数说明
max_length
生成的token的最大长度。它是输入prompt的长度加上max_new_tokens的值。如果同时设置了max_new_tokens,则会覆盖此参数,默认为20。
max_new_tokens
生成的最大token的数量,不考虑输入prompt中的token数,默认无设置。
min_length
生成的token的最小长度。它是输入prompt的长度加上min_new_tokens的值。如果同时设置了min_new_tokens,则会覆盖此参数,默认为0。
min_new_tokens
生成的最小token的数量,不考虑输入prompt中的token数,默认无设置。
bad_words_ids
包含词汇id的列表,这个参数用于指定不允许在生成文本中出现的词汇,如果生成的文本包含任何在这个列表中的词汇,它们将被被替换或排除在最终生成的文本之外。
force_words_ids
包含词汇id的列表,用于指定必须包含在生成文本中的词汇,如果给定一个列表,生成的文本将包含这些词汇。
diversity_penalty
多样性惩罚diversity_penalty参数,只有在启用了“num_beam_groups”(组束搜索)时才有效,在这些组之间应用多样性惩罚,以确保每个组生成的内容尽可能不同。
constraints
constraints参数为自定义约束条件,可以指定约束条件,这些约束条件可以是必须出现的关键词、短语、特定术语或其他文本元素,和force_words_ids是在代码实现是一样的。
length_penalty
长度惩罚(length_penalty)参数也是用于束搜索(beam search)过程中,在束搜索(beam search)的生成中,候选序列的得分通过对数似然估计计算得到,即得分是负对数似然。
length_penalty参数的作用是将生成序列的长度应用于得分的分母,从而影响候选序列的得分。
-
当length_penalty > 1.0时,较长的序列得到更大的惩罚,鼓励生成较短的序列;
-
当length_penalty < 1.0时,较短的序列得到更大的惩罚,鼓励生成较长的序列;
-
当length_penalty = 1.0时,不受惩罚,默认为1。
early_stopping
控制基于束搜索(beam search)等方法的停止条件:
-
True:生成会在出现 num_beams 个完整候选项时停止。
-
False:应用启发式方法,当很不可能找到更好的候选项时停止生成。
-
never:只有当不能找到更好的候选项时,束搜索过程才会停止(经典的束搜索算法)。
默认为False。
repetition_penalty
repetition_penalty参数用于重复惩罚,通过修改生成文本时的概率分布来实现,目标是在这个概率分布中对先前重复生成过的token进行惩罚(降低概率),以减少生成文本中的重复性。一般repetition_penalty参数是惩罚,概率值 * (1/repetition_penalty)。
no_repeat_ngram_size
no_repeat_ngram_size参数设为大于0的整数时,生成的文本中不会出现指定大小的重复n-gram(n个连续的token),可以使生成的文本更加多样化,避免出现重复的短语或句子结构。实现原理和上述repetition_penalty的相似,只不过这里是n个连续的token。
注,默认不设置。
use_cache
use_cache参数设置为True时,模型会利用之前计算得到的注意力权重(key/values attentions)的缓存,这些注意力权重是在模型生成文本的过程中,根据输入上下文和已生成部分文本,计算出来的
当下一个token需要被生成时,模型可以通过缓存的注意力权重来重用之前计算的信息,而不需要重新计算一次,有效地跳过重复计算的步骤,从而减少计算负担,提高生成速度和效率。
reference
https://github.com/Glanvery/LLM-Travel
https://huggingface.co/docs/transformers/main/en/main_classes/text_generation#transformers.GenerationConfig
https://github.com/yxuansu/SimCTG
https://codingling.gitbook.io/study/basic-know/language-model/yu-yan-mo-xing-jie-ma-cai-yang-ce-lve
https://mp.weixin.qq.com/s/BuvLXx0ZItOvhno4XAUpTg
原文始发于微信公众号(TahirSec):AI | LLM模型推理生成与采样解码策略(一)
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论