关于人工智能:自然语言生成任务中的5种采样方法介绍和Pytorch代码实现

3次阅读

共计 5031 个字符,预计需要花费 13 分钟才能阅读完成。

在自然语言生成工作(NLG)中,采样办法是指从生成模型中获取文本输入的一种技术。本文将介绍罕用的 5 中办法并用 Pytorch 进行实现。

1、Greedy Decoding

Greedy Decoding 在每个工夫步抉择以后条件概率最高的词语作为输入,直到生成完结。在贪心解码中,生成模型依据输出序列,一一工夫步地预测输入序列中的每个词语。在每个工夫步,模型依据以后的暗藏状态和已生成的局部序列计算每个词语的条件概率分布,模型抉择具备最高条件概率的词语作为以后工夫步的输入。这个词语成为下一个工夫步的输出,生成过程继续直到满足某种终止条件,比方生成了指定长度的序列或者生成了非凡的完结标记。

这种办法简略高效,每个工夫步只需计算以后条件概率最高的词语,因而计算速度较快。然而因为每个工夫步只思考以后条件概率最高的词语,贪心解码可能会陷入部分最优解,而无奈取得全局最优解。这可能导致生成的文本不足多样性或不精确。

只管贪心解码存在一些局限性,但它依然是许多序列生成工作中罕用的一种办法,特地是在对速度要求较高或者工作较为简单的状况下。

 defgreedy_decoding(input_ids, max_tokens=300):
     withtorch.inference_mode():
         for_inrange(max_tokens):
             outputs=model(input_ids)
             next_token_logits=outputs.logits[:, -1, :]
             next_token=torch.argmax(next_token_logits, dim=-1)
             ifnext_token==tokenizer.eos_token_id:
                 break
             input_ids=torch.cat([input_ids, rearrange(next_token, 'c -> 1 c')], dim=-1)
         generated_text=tokenizer.decode(input_ids[0])
     returngenerated_text
 

2、Beam Search

束搜寻(Beam Search)是贪心解码的一种扩大,通过在每个工夫步保留多个候选序列来克服贪心解码的部分最优问题。

在每个工夫步保留概率最高的前几个候选词语,而后在下一个工夫步基于这些候选词语持续扩大,直到生成完结。束搜寻通过思考多个候选词语门路,能够在肯定水平上减少生成文本的多样性。

在束搜寻中,模型在每个工夫步会生成多个候选序列,而不是仅抉择一个最优序列。模型会依据以后已生成的局部序列和暗藏状态,预测下一个工夫步可能的词语,并计算每个词语的条件概率分布。

上图的每一步中,只保留两条最可能的门路(依据 beam =2),而所有其余都被抛弃。此过程将持续进行,直到满足进行条件,该进行条件能够是生成序列完结令牌或达到最大序列长度的模型。最终输入将是最初一组门路中具备最高总体概率的序列。

 fromeinopsimportrearrange
 importtorch.nn.functionalasF
 
 defbeam_search(input_ids, max_tokens=100, beam_size=2):
     beam_scores=torch.zeros(beam_size).to(device)
     beam_sequences=input_ids.clone()
     active_beams=torch.ones(beam_size, dtype=torch.bool)
     forstepinrange(max_tokens):
         outputs=model(beam_sequences)
         logits=outputs.logits[:, -1, :]
         probs=F.softmax(logits, dim=-1)
         top_scores, top_indices=torch.topk(probs.flatten(), k=beam_size, sorted=False)
         beam_indices=top_indices//probs.shape[-1]
         token_indices=top_indices%probs.shape[-1]
         beam_sequences=torch.cat([beam_sequences[beam_indices],
             token_indices.unsqueeze(-1)
         ], dim=-1)
         beam_scores=top_scores
         active_beams=~(token_indices==tokenizer.eos_token_id)
         ifnotactive_beams.any():
             print("no active beams")
             break
     best_beam=beam_scores.argmax()
     best_sequence=beam_sequences[best_beam]
     generated_text=tokenizer.decode(best_sequence)
     returngenerated_text

3、Temperature Sampling

温度参数采样(Temperature Sampling)罕用于基于概率的生成模型,如语言模型。它通过引入一个称为“温度”(Temperature)的参数来调整模型输入的概率分布,从而管制生成文本的多样性。

在温度参数采样中,模型在每个工夫步生成词语时,会计算出词语的条件概率分布。而后模型将这个条件概率分布中的每个词语的概率值除以温度参数,对后果进行归一化解决,取得新的归一化概率分布。较高的温度值会使概率分布更平滑,从而减少生成文本的多样性。低概率的词语也有较高的可能性被抉择;而较低的温度值则会使概率分布更集中,更偏向于抉择高概率的词语,因而生成的文本更加确定性。最初模型依据这个新的归一化概率分布进行随机采样,抉择生成的词语。

 importtorch
 importtorch.nn.functionalasF
 
 deftemperature_sampling(logits, temperature=1.0):
     logits=logits/temperature
     probabilities=F.softmax(logits, dim=-1)
     sampled_token=torch.multinomial(probabilities, 1)
     returnsampled_token.item()

4、Top-K Sampling

Top-K 采样(在每个工夫步抉择条件概率排名前 K 的词语,而后在这 K 个词语中进行随机采样。这种办法既能放弃肯定的生成品质,又能减少文本的多样性,并且能够通过限度候选词语的数量来管制生成文本的多样性。

这个过程使得生成的文本在放弃肯定的生成品质的同时,也具备肯定的多样性,因为在候选词语中依然存在肯定的竞争性。

参数 K 管制了在每个工夫步中保留的候选词语的数量。较小的 K 值会导致更加贪心的行为,因为只有少数几个词语参加随机采样,而较大的 K 值会减少生成文本的多样性,但也会减少计算开销。

 deftop_k_sampling(input_ids, max_tokens=100, top_k=50, temperature=1.0):
    for_inrange(max_tokens):
         withtorch.inference_mode():
             outputs=model(input_ids)
             next_token_logits=outputs.logits[:, -1, :]
             top_k_logits, top_k_indices=torch.topk(next_token_logits, top_k)
             top_k_probs=F.softmax(top_k_logits/temperature, dim=-1)
             next_token_index=torch.multinomial(top_k_probs, num_samples=1)
             next_token=top_k_indices.gather(-1, next_token_index)
             input_ids=torch.cat([input_ids, next_token], dim=-1)
     generated_text=tokenizer.decode(input_ids[0])
     returngenerated_text

5、Top-P (Nucleus) Sampling:

Nucleus Sampling(核采样),也被称为 Top-p Sampling 旨在在放弃生成文本品质的同时减少多样性。这种办法能够视作是 Top-K Sampling 的一种变体,它在每个工夫步依据模型输入的概率分布抉择概率累积超过给定阈值 p 的词语汇合,而后在这个词语汇合中进行随机采样。这种办法会动静调整候选词语的数量,以放弃肯定的文本多样性。

在 Nucleus Sampling 中,模型在每个工夫步生成词语时,首先依照概率从高到低对词汇表中的所有词语进行排序,而后模型计算累积概率,并找到累积概率超过给定阈值 p 的最小词语子集,这个子集就是所谓的“核”(nucleus)。模型在这个核中进行随机采样,依据词语的概率分布来抉择最终输入的词语。这样做能够保障所选词语的总概率超过了阈值 p,同时也放弃了肯定的多样性。

参数 p 是 Nucleus Sampling 中的重要参数,它决定了所选词语的概率总和。p 的值会被设置在 (0,1] 之间,示意词语总概率的一个下界。

Nucleus Sampling 可能放弃肯定的生成品质,因为它在肯定水平上思考了概率分布。通过抉择概率总和超过给定阈值 p 的词语子集进行随机采样,Nucleus Sampling 可能减少生成文本的多样性。

 deftop_p_sampling(input_ids, max_tokens=100, top_p=0.95):
     withtorch.inference_mode():
         for_inrange(max_tokens):
                 outputs=model(input_ids)
                 next_token_logits=outputs.logits[:, -1, :]
                 sorted_logits, sorted_indices=torch.sort(next_token_logits, descending=True)
                 sorted_probabilities=F.softmax(sorted_logits, dim=-1) 
                 cumulative_probs=torch.cumsum(sorted_probabilities, dim=-1)
                 sorted_indices_to_remove=cumulative_probs>top_p
                 sorted_indices_to_remove[..., 0] =False
                 indices_to_remove=sorted_indices[sorted_indices_to_remove]
                 next_token_logits.scatter_(-1, indices_to_remove[None, :], float('-inf'))
                 probs=F.softmax(next_token_logits, dim=-1)
                 next_token=torch.multinomial(probs, num_samples=1)
                 input_ids=torch.cat([input_ids, next_token], dim=-1)
         generated_text=tokenizer.decode(input_ids[0])
     returngenerated_text

总结

自然语言生成工作中,采样办法是十分重要的。抉择适合的采样办法能够在肯定水平上影响生成文本的品质、多样性和效率。下面介绍的几种采样办法各有特点,实用于不同的利用场景和需要。

贪心解码是一种简略间接的办法,实用于速度要求较高的状况,但可能导致生成文本不足多样性。束搜寻通过保留多个候选序列来克服贪心解码的部分最优问题,生成的文本品质更高,但计算开销较大。Top-K 采样和核采样能够管制生成文本的多样性,实用于须要均衡品质和多样性的场景。温度参数采样则能够依据温度参数灵便调节生成文本的多样性,实用于须要均衡多样性和品质的工作。

https://avoid.overfit.cn/post/42c2631bc56347849d538768d84d47c2

正文完
 0