Part1配置及參數(shù)
transformers==4.28.1
源碼地址:transformers/configuration_utils.py at v4.28.1 · huggingface/transformers (github.com)
文檔地址:Generation (huggingface.co)
對(duì)于生成任務(wù)而言:text-decoder, text-to-text, speech-to-text, and vision-to-text models,有以下幾種生成的方法:
greedy decoding by calling [ ~generation.GenerationMixin.greedy_search
] ifnum_beams=1
anddo_sample=False
contrastive search by calling [ ~generation.GenerationMixin.contrastive_search
] ifpenalty_alpha>0.
andtop_k>1
multinomial sampling by calling [ ~generation.GenerationMixin.sample
] ifnum_beams=1
anddo_sample=True
beam-search decoding by calling [ ~generation.GenerationMixin.beam_search
] ifnum_beams>1
anddo_sample=False
beam-search multinomial sampling by calling [ ~generation.GenerationMixin.beam_sample
] ifnum_beams>1
anddo_sample=True
diverse beam-search decoding by calling [ ~generation.GenerationMixin.group_beam_search
], ifnum_beams>1
andnum_beam_groups>1
constrained beam-search decoding by calling [ ~generation.GenerationMixin.constrained_beam_search
], ifconstraints!=None
orforce_words_ids!=None
具體有以下參數(shù)可供選擇:
(1)控制輸出長(zhǎng)度的參數(shù)
max_length (int, optional, defaults to 20) - 生成的tokens的最大長(zhǎng)度。對(duì)應(yīng)于輸入提示的長(zhǎng)度+max_new_tokens。如果還設(shè)置了max_new_tokens,則其作用被max_new_tokens覆蓋。 max_new_tokens (int, optional) - 要生成的最大數(shù)量的tokens,忽略提示中的tokens數(shù)量。 min_length (int, optional, defaults to 0) - 要生成的序列的最小長(zhǎng)度。對(duì)應(yīng)于輸入提示的長(zhǎng)度+min_new_tokens。如果還設(shè)置了min_new_tokens,它的作用將被 min_new_tokens覆蓋。 min_new_tokens (int, optional) - 要生成的最小數(shù)量的tokens,忽略提示中的tokens數(shù)量。 early_stopping (bool or str, optional, defaults to False) - 控制基于beam-based的停止條件,比如beam-search。是否在至少生成 num_beams
個(gè)句子后停止 beam search,默認(rèn)是False。max_time(float, optional) - 你允許計(jì)算運(yùn)行的最大時(shí)間,以秒為單位。在分配的時(shí)間過(guò)后,生成仍然會(huì)完成當(dāng)前的傳遞。
(2)控制輸出策略的參數(shù)
do_sample (bool, optional, defaults to False) - 是否使用采樣,否則使用貪婪解碼 。
num_beams (int, optional, defaults to 1) - 集束搜索的集束數(shù)量。1意味著沒(méi)有集束搜索 。
num_beam_groups (int, optional, defaults to 1) - 將num_beam分成的組數(shù),以確保不同組的beams的多樣性。https://arxiv.org/pdf/1610.02424.pdf
penalty_alpha (float, optional) - 平衡模型置信度和對(duì)比搜索解碼中的退化懲罰的數(shù)值。
use_cache (bool, optional, defaults to True) - 模型是否應(yīng)該使用過(guò)去最后的鍵/值注意力(如果適用于模型)來(lái)加速解碼。
(3)控制模型輸出Logits的參數(shù)
temperature(float, optional, defaults to 1.0) - 用于調(diào)節(jié)下一個(gè)標(biāo)記概率的值。 top_k (int, optional, defaults to 50) - 為top-k過(guò)濾而保留的最高概率詞匯標(biāo)記的數(shù)量。 top_p (float, optional, defaults to 1.0) - 已知生成各個(gè)詞的總概率是1(即默認(rèn)是1.0)如果top_p小于1,則從高到低累加直到top_p,取這前N個(gè)詞作為候選。 typical_p (float, optional, defaults to 1.0) - 局部典型性度量:在給定已生成的部分文本的情況下,預(yù)測(cè)下一個(gè)目標(biāo)標(biāo)記的條件概率與預(yù)測(cè)下一個(gè)隨機(jī)標(biāo)記的預(yù)期條件概率的相似程度。如果設(shè)置為float < 1,則保留概率加起來(lái)等于typical_p或更高的最小的本地典型tokens集以供生成。https://arxiv.org/pdf/2202.00666.pdf epsilon_cutoff (float, optional, defaults to 0.0) - 如果設(shè)置為嚴(yán)格介于0和1之間的浮點(diǎn)數(shù) ,只有條件概率大于epsilon_cutoff的標(biāo)記才會(huì)被采樣。在論文中,建議的值在3e-4到 9e-4之間,取決于模型的大小。https://arxiv.org/abs/2210.15191 eta_cutoff (float, optional, defaults to 0.0) - Eta采樣是局部典型采樣和ε采樣的混合體。 如果設(shè)置為嚴(yán)格介于0和1之間的浮點(diǎn)數(shù),只有當(dāng)一個(gè)token大于eta_cutoff或 sqrt(eta_cutoff) * exp(- entropy(softmax(next_token_logits)))時(shí)才會(huì)被考 慮。后者直觀地是預(yù)期的下一個(gè)令牌概率,以sqrt(eta_cutoff)為尺度。在論文中 ,建議值從3e-4到2e-3不等,取決于模型的大小。https://arxiv.org/abs/2210.15191 diversity_penalty (float, optional, defaults to 0.0) - 如果一個(gè)beam在某一特定時(shí)間產(chǎn)生一 個(gè)與其他組的任何beam相同的標(biāo)記,這個(gè)值將從beam的分?jǐn)?shù)中減去。請(qǐng)注意,多樣性懲罰只有在group-beam-search被啟用時(shí)才有效。 repetition_penalty (float, optional, defaults to 1.0) - 重復(fù)處罰的參數(shù)。1.0意味著沒(méi)有懲罰。https://arxiv.org/pdf/1909.05858.pdf encoder_repetition_penalty (float, optional, defaults to 1.0) - encoder_repetition_penalty的參數(shù)。對(duì)不在原始輸入中的序列進(jìn)行指數(shù)式懲罰。 1.0意味著沒(méi)有懲罰。 length_penalty (float, optional, defaults to 1.0) - 對(duì)長(zhǎng)度的指數(shù)懲罰,用于beam-based的生成 。它作為指數(shù)應(yīng)用于序列的長(zhǎng)度,反過(guò)來(lái)用于劃分序列的分?jǐn)?shù)。由于分?jǐn)?shù)是序列的對(duì)數(shù) 能性(即負(fù)數(shù)),length_penalty > 0.0會(huì)促進(jìn)更長(zhǎng)的序列,而length_penalty < 0.0會(huì)鼓勵(lì)更短的序列。 no_repeat_ngram_size (int, optional, defaults to 0) - 如果設(shè)置為int > 0,所有該尺寸的 ngrams只能出現(xiàn)一次。 bad_words_ids(List[List[int]], optional) - 不允許生成的標(biāo)記ID的列表。為了獲得不 應(yīng)該出現(xiàn)在生成的文本中的詞的標(biāo)記ID,使用tokenizer(bad_words, add_prefix_space=True, add_special_tokens=False).input_ids。 force_words_ids(List[List[int]] or List[List[List[int]]], optional) - 必須生成的 token ids列表。如果給定的是List[List[int]],這將被視為一個(gè)必須包含的簡(jiǎn)單單詞列表,與bad_words_ids相反。如果給定的是List[List[List[int]]],這將觸發(fā)一個(gè) disjunctive約束,即可以允許每個(gè)詞的不同形式。https://github.com/huggingface/transformers/issues/14081 renormalize_logits (bool, optional, defaults to False) - 在應(yīng)用所有的logits處理器或 warpers(包括自定義的)之后,是否重新規(guī)范化logits。強(qiáng)烈建議將這個(gè)標(biāo)志設(shè)置為 "True",因?yàn)樗阉魉惴ㄕJ(rèn)為分?jǐn)?shù)對(duì)數(shù)是正?;?,但一些對(duì)數(shù)處理器或翹曲器會(huì)破壞正?;?/section> constraints (List[Constraint], optional) - 自定義約束,可以添加到生成中,以確保輸出將包含使用Constraint對(duì)象定義的某些標(biāo)記,以最合理的方式。 forced_bos_token_id (int, optional, defaults to model.config.forced_bos_token_id) - 強(qiáng)制作為解碼器_start_token_id之后第一個(gè)生成的令牌的id。對(duì)于像mBART這樣的多語(yǔ)言模型,第一個(gè)生成的標(biāo)記需要是目標(biāo)語(yǔ)言的標(biāo)記,這很有用。 forced_eos_token_id (Union[int, List[int]], optional, defaults to model.config.forced_eos_token_id) - 當(dāng)達(dá)到max_length時(shí),強(qiáng)制作為最后生成的令牌的id??梢赃x擇使用一個(gè)列表來(lái)設(shè)置多個(gè)序列結(jié)束的標(biāo)記。 remove_invalid_values (bool, optional, defaults to model.config.remove_invalid_values) - 是否刪除模型可能的nan和inf輸出以防 止生成方法崩潰。注意,使用remove_invalid_values會(huì)減慢生成速度。 exponential_decay_length_penalty (tuple(int, float), optional) - 這個(gè)Tuple在生成一 定數(shù)量的標(biāo)記后,增加一個(gè)指數(shù)級(jí)增長(zhǎng)的長(zhǎng)度懲罰。該元組應(yīng)包括: (start_index, decay_factor) 其中start_index表示懲罰開(kāi)始的位置, decay_factor表示指數(shù)衰減的系數(shù)。 suppress_tokens (List[int], optional) - 在生成時(shí)將被抑制的tokens列表。 SupressTokens日志處理器將把它們的日志probs設(shè)置為-inf,這樣它們就不會(huì)被采樣 了。 forced_decoder_ids (List[List[int]], optional) - 一對(duì)整數(shù)的列表,表示從生成索引到token索引的映射,在采樣前會(huì)被強(qiáng)制執(zhí)行。例如,[[1, 123]]意味著第二個(gè)生成的token將總是索引為token的令牌。
(4)定義generate
輸出變量的參數(shù)
num_return_sequences(int, optional, defaults to 1) - 批次中每個(gè)元素獨(dú)立計(jì)算的返回序列的數(shù)量。 output_attentions (bool, optional, defaults to False) - 是否返回所有注意力層的注意力張量。更多細(xì)節(jié)請(qǐng)參見(jiàn)返回的張量下的注意力。 output_hidden_states (bool, optional, defaults to False) - 是否要返回所有層的隱藏狀 態(tài)。更多細(xì)節(jié)請(qǐng)參見(jiàn)返回張量下的hidden_states。 output_scores (bool, optional, defaults to False) - 是否返回預(yù)測(cè)的分?jǐn)?shù)。更多細(xì)節(jié)請(qǐng)參見(jiàn)返回張量下的分?jǐn)?shù)。 return_dict_in_generate (bool, optional, defaults to False) - 是否返回ModelOutput而不是普通元組。 synced_gpus (bool, optional, defaults to False) - 是否繼續(xù)運(yùn)行while循環(huán)直到max_length(ZeRO第三階段需要)。
(5)可在生成時(shí)使用的特殊參數(shù)
pad_token_id (int, optional) - 填充token的ID。 bos_token_id (int, optional) - 序列開(kāi)始標(biāo)記的id。 eos_token_id (Union[int, List[int]], optional) - 序列結(jié)束標(biāo)記的id??梢赃x擇使用 一個(gè)列表來(lái)設(shè)置多個(gè)序列結(jié)束標(biāo)記。
(6)編碼器-解碼器模型獨(dú)有的生成參數(shù)
encoder_no_repeat_ngram_size (int, optional, defaults to 0) - 如果設(shè)置為int > 0,所有出現(xiàn)在encoder_input_ids中的該大小的ngrams都不能出現(xiàn)在decoder_input_ids中 。
decoder_start_token_id (int, optional) - 如果一個(gè)編碼器-解碼器模型以不同于bos的 token開(kāi)始解碼,則這就是該token的id。
Part2配置基本使用
1使用預(yù)訓(xùn)練模型定義的生成參數(shù)
我們可以這么使用、保存預(yù)訓(xùn)練模型已經(jīng)定義好的參數(shù):
from?transformers?import?AutoTokenizer,?AutoModelForCausalLM,?TextGenerationPipeline,?GenerationConfig
model_name_or_path?=?"uer/gpt2-chinese-cluecorpussmall"
tokenizer?=?AutoTokenizer.from_pretrained(model_name_or_path)
model?=?AutoModelForCausalLM.from_pretrained(model_name_or_path)
generation_config?=?model.generation_config
generation_config_dict?=?generation_config.to_dict()
generation_config_dict["num_beams"]?=?2
generation_config?=?GenerationConfig.from_dict(generation_config_dict)
print(generation_config)
generation_config.save_pretrained("./")
"""
{
??"_from_model_config":?true,
??"bos_token_id":?50256,
??"eos_token_id":?50256,
??"num_beams":?2,
??"transformers_version":?"4.28.1"
}
"""
需要注意的是,如果參數(shù)是默認(rèn)的值得話(huà),則不會(huì)顯示出來(lái)。另外,GenerationConfig類(lèi)里面有許多可用的方法,具體可以去看看源代碼。
2一般使用方法
在定義好config之后,我們可以這么使用:
from?transformers?import?AutoModelForSeq2SeqLM,?AutoTokenizer,?GenerationConfig
tokenizer?=?AutoTokenizer.from_pretrained("t5-small")
model?=?AutoModelForSeq2SeqLM.from_pretrained("t5-small")
translation_generation_config?=?GenerationConfig(
????num_beams=4,
????early_stopping=True,
????decoder_start_token_id=0,
????eos_token_id=model.config.eos_token_id,
????pad_token=model.config.pad_token_id,
)
translation_generation_config.save_pretrained("t5-small",?"translation_generation_config.json",?push_to_hub=True)
#?You?could?then?use?the?named?generation?config?file?to?parameterize?generation
#?可以加載我們自己本地保存的generation_config
generation_config?=?GenerationConfig.from_pretrained("t5-small",?"translation_generation_config.json")
inputs?=?tokenizer("translate?English?to?French:?Configuration?files?are?easy?to?use!",?return_tensors="pt")
outputs?=?model.generate(**inputs,?generation_config=generation_config)
print(tokenizer.batch_decode(outputs,?skip_special_tokens=True))
Part3生成結(jié)果
使用transformers庫(kù)的生成模型生成結(jié)果有三種方式,暫時(shí)不要在意參數(shù):
3pipeline
指定為text-generation
from?transformers?import?pipeline
generator?=?pipeline(
????'text-generation',?
????model="uer/gpt2-chinese-cluecorpussmall",
????)
text_inputs?=?["昨天已經(jīng)過(guò)去,"]
generator(text_inputs,?max_length=100)
4TextGenerationPipeline
from?transformers?import?AutoTokenizer,?AutoModelForCausalLM,?TextGenerationPipeline
tokenizer?=?AutoTokenizer.from_pretrained("uer/gpt2-chinese-cluecorpussmall")
model?=?AutoModelForCausalLM.from_pretrained("uer/gpt2-chinese-cluecorpussmall")
text_generator?=?TextGenerationPipeline(model,?tokenizer)
text_inputs?=?["昨天已經(jīng)過(guò)去,"]
text_generator(text_inputs,?max_length=100)
5model.generate()
from?transformers?import?AutoTokenizer,?AutoModelForCausalLM
import?torch,?os
tokenizer?=?AutoTokenizer.from_pretrained("uer/gpt2-chinese-cluecorpussmall")
model?=?AutoModelForCausalLM.from_pretrained("uer/gpt2-chinese-cluecorpussmall")
device?=?'cuda'?if?torch.cuda.is_available()?else?'cpu'
model?=?model.to(device)
texts?=?["昨天已經(jīng)過(guò)去,"]
#用batch輸入的時(shí)候一定要設(shè)置padding
encoding?=?tokenizer(texts,?return_tensors='pt',?padding=True).to(device)
model.eval()
with?torch.no_grad():
????generated_ids?=?model.generate(**encoding,?max_length=100)?
?generated_texts?=?tokenizer.batch_decode(generated_ids,?skip_special_tokens=True)
for?text?in?generated_texts:
??print(text)
我們捋一捋它們之間的關(guān)系:最基礎(chǔ)的還是model.generate(),而TextGenerationPipeline在_forward里面調(diào)用了model.generate(),pipeline實(shí)際上是對(duì)TextGenerationPipeline的進(jìn)一步封裝:
????"text-generation":?{
????????"impl":?TextGenerationPipeline,
????????"tf":?TFAutoModelForCausalLM?if?is_tf_available()?else?None,
????????"pt":?AutoModelForCausalLM?if?is_torch_available()?else?None,
????????"default":?{"model":?{"pt":?"gpt2",?"tf":?"gpt2"}},
????},
6流式打印
在介紹不同的生成方法之前,先介紹下流式打印。使用過(guò)ChatGPT的玩家都知道,在生成結(jié)果的時(shí)候,它是一部分一部分的返回生成的文本并展示的,transformers該版本也有這個(gè)功能,我們接下來(lái)看。
from?transformers?import?AutoModelForCausalLM,?AutoTokenizer,?TextStreamer
tokenizer?=?AutoTokenizer.from_pretrained("uer/gpt2-chinese-cluecorpussmall")
model?=?AutoModelForCausalLM.from_pretrained("uer/gpt2-chinese-cluecorpussmall")
input_text?=?"昨天已經(jīng)過(guò)去,"
inputs?=?tokenizer([input_text],?return_tensors="pt",?add_special_tokens=False)
streamer?=?TextStreamer(tokenizer)
#?Despite?returning?the?usual?output,?the?streamer?will?also?print?the?generated?text?to?stdout.
_?=?model.generate(**inputs,?streamer=streamer,?max_new_tokens=86)
如果想要一次性返回結(jié)果再打印,則是這樣的:
from?transformers?import?AutoModelForCausalLM,?AutoTokenizer,?TextIteratorStreamer
from?threading?import?Thread
tokenizer?=?AutoTokenizer.from_pretrained("uer/gpt2-chinese-cluecorpussmall")
model?=?AutoModelForCausalLM.from_pretrained("uer/gpt2-chinese-cluecorpussmall")
input_text?=?"昨天已經(jīng)過(guò)去,"
inputs?=?tokenizer([input_text],?return_tensors="pt",?add_special_tokens=False)
streamer?=?TextIteratorStreamer(tokenizer)
#?Run?the?generation?in?a?separate?thread,?so?that?we?can?fetch?the?generated?text?in?a?non-blocking?way.
generation_kwargs?=?dict(inputs,?streamer=streamer,?max_new_tokens=100)
thread?=?Thread(target=model.generate,?kwargs=generation_kwargs)
thread.start()
generated_text?=?""
for?new_text?in?streamer:
????generated_text?+=?new_text
generated_text
Part4多種生成方式
接下來(lái)將以之前訓(xùn)練好的觀點(diǎn)評(píng)論生成的GPT來(lái)生成不同的結(jié)果,我們每次都使用三種方式對(duì)比看看結(jié)果。
7Greedy Search
generate默認(rèn)使用貪婪的搜索解碼,所以你不需要傳遞任何參數(shù)來(lái)啟用它。這意味著參數(shù)num_beams被設(shè)置為1,do_sample=False。
如圖上所屬,每次選擇概率值最高的詞。貪心搜索的主要缺點(diǎn)是它錯(cuò)過(guò)了隱藏在低概率詞后面的高概率詞,比如has=0.9不會(huì)被選擇到。
from?transformers?import?AutoTokenizer,?AutoModelForCausalLM,?TextGenerationPipeline,?pipeline
tokenizer?=?AutoTokenizer.from_pretrained("./gpt2-chinese")
model?=?AutoModelForCausalLM.from_pretrained("./gpt2-chinese")
from?datasets?import?load_dataset
data_file?=?"./ChnSentiCorp_htl_all.csv"
dataset?=?load_dataset("csv",?data_files=data_file)
dataset?=?dataset.filter(lambda?x:?x["review"]?is?not?None)
dataset?=?dataset["train"].train_test_split(0.2,?seed=123)
import?random
example?=?random.choice(dataset["train"])
text?=?example["review"]
input_text?=?text[:10]
print(input_text)
#?greedy?search
model.eval()
with?torch.no_grad():
??encoding?=?tokenizer(input_text,?
??????????????return_tensors='pt',?
??????????????padding=False,?
??????????????add_special_tokens=False,
??????????????return_token_type_ids=False,
??????????????return_attention_mask=False,)
??
??generated_ids?=?model.generate(**encoding,?
????????????????????max_length=100,?
????????????????????eos_token_id=0,?
????????????????????pad_token_id=0,?
????????????????????num_beams=1,?
????????????????????do_sample=False)?
??generated_texts?=?tokenizer.batch_decode(generated_ids,?skip_special_tokens=True)
??print(generated_texts)
text_generator?=?TextGenerationPipeline(model,?tokenizer)??
print(text_generator(input_text,?
???????????max_length=100,?
???????????eos_token_id=0,?
???????????num_beams=1,?
???????????do_sample=False,
???????????pad_token_id=0))
generator?=?pipeline("text-generation",?model=model,?tokenizer=tokenizer)
generation_config?=?{
??"max_length":?100,
??"eos_token_id":?0,
??"pad_token_id":?0,
??"num_beams":?1,?
??"do_sample":?False,
}
print(generator(input_text,?**generation_config))
"""
雖然說(shuō)是4星級(jí),不過(guò)
['雖?然?說(shuō)?是?4?星?級(jí)?,?不?過(guò)?感?覺(jué)?和?3?星?沒(méi)?什?么?兩?樣?,?只?是?服?務(wù)?水?準(zhǔn)?差?了?點(diǎn)?而?已']
[{'generated_text':?'雖然說(shuō)是4星級(jí),不過(guò)?感?覺(jué)?和?3?星?沒(méi)?什?么?兩?樣?,?只?是?服?務(wù)?水?準(zhǔn)?差?了?點(diǎn)?而?已'}]
[{'generated_text':?'雖然說(shuō)是4星級(jí),不過(guò)?感?覺(jué)?和?3?星?沒(méi)?什?么?兩?樣?,?只?是?服?務(wù)?水?準(zhǔn)?差?了?點(diǎn)?而?已'}]
"""
答案是一致的,和我們之前的推測(cè)一樣,但需要注意的是model.gneerate()對(duì)單條預(yù)測(cè)的時(shí)候我們?cè)趖okenizer的時(shí)候設(shè)置padding為False了,如果設(shè)置為T(mén)rue,則得不到相同的結(jié)果。
8Contrastive search
對(duì)比搜索解碼策略是在2022年的論文A Contrastive Framework for Neural Text Generation https://arxiv.org/abs/2202.06417中提出的。它展示了生成非重復(fù)但連貫的長(zhǎng)輸出的優(yōu)越結(jié)果。要了解對(duì)比性搜索的工作原理,請(qǐng)查看這篇博文https://huggingface.co/blog/introducing-csearch。啟用和控制對(duì)比性搜索行為的兩個(gè)主要參數(shù)是punice_alpha和top_k:
from?transformers?import?AutoTokenizer,?AutoModelForCausalLM,?TextGenerationPipeline,?pipeline
tokenizer?=?AutoTokenizer.from_pretrained("./gpt2-chinese")
model?=?AutoModelForCausalLM.from_pretrained("./gpt2-chinese")
from?datasets?import?load_dataset
data_file?=?"./ChnSentiCorp_htl_all.csv"
dataset?=?load_dataset("csv",?data_files=data_file)
dataset?=?dataset.filter(lambda?x:?x["review"]?is?not?None)
dataset?=?dataset["train"].train_test_split(0.2,?seed=123)
import?random
example?=?random.choice(dataset["train"])
#?text?=?dataset["train"][0]
text?=?example["review"]
input_text?=?text[:10]
print(input_text)
#?greedy?search
model.eval()
with?torch.no_grad():
??encoding?=?tokenizer(input_text,?
??????????????return_tensors='pt',?
??????????????padding=False,?
??????????????add_special_tokens=False,
??????????????return_token_type_ids=False,
??????????????return_attention_mask=False,)
??
??generated_ids?=?model.generate(**encoding,?
????????????????????max_length=100,?
????????????????????eos_token_id=0,?
????????????????????pad_token_id=0,
????????????????????do_sample=False,
????????????????????num_beams=1,?
????????????????????penalty_alpha=0.6,?
????????????????????top_k=4)?
??generated_texts?=?tokenizer.batch_decode(generated_ids,?skip_special_tokens=True)
??print(generated_texts)
text_generator?=?TextGenerationPipeline(model,?tokenizer)??
print(text_generator(input_text,?
???????????max_length=100,?
???????????eos_token_id=0,?
???????????num_beams=1,?
???????????do_sample=False,
???????????pad_token_id=0,
???????????penalty_alpha=0.6,?
???????????top_k=4
???????????))
generator?=?pipeline("text-generation",?model=model,?tokenizer=tokenizer)
generation_config?=?{
??"max_length":?100,
??"eos_token_id":?0,
??"pad_token_id":?0,
??"num_beams":?1,?
??"do_sample":?False,
??#?"penalty_alpha":0.6,?
??#?"top_k":4,
}
print(generator(input_text,?**generation_config))
"""
['極?差?!?停?車(chē)?收?十?元?錢(qián)?!?窮?則?思?變?!?房?間?潮?濕?得?不?得?了?,?晚?上?居?然?停?了?一?個(gè)?多?小?時(shí)?,?上?網(wǎng)?一?會(huì)?有?信?號(hào)?一?會(huì)?沒(méi)?有?。?電?視?遙?控?器?不?管?用?,?打?電?話(huà)?給?客?房?中?心?,?得?到?的?回?復(fù)?居?然?是?壞?的?房?間?在?維?修?,?不?知?道']
[{'generated_text':?'極差!停車(chē)收十元錢(qián)!?窮?則?思?變?!?房?間?潮?濕?得?不?得?了?,?晚?上?居?然?停?了?一?個(gè)?多?小?時(shí)?,?上?網(wǎng)?一?會(huì)?有?信?號(hào)?一?會(huì)?沒(méi)?有?。?電?視?遙?控?器?不?管?用?,?打?電?話(huà)?給?客?房?中?心?,?得?到?的?回?復(fù)?居?然?是?壞?的?房?間?在?維?修?,?不?知?道'}]
[{'generated_text':?'極差!停車(chē)收十元錢(qián)!?窮?則?思?變?!?房?間?設(shè)?施?差?就?一?個(gè)?招?待?所?,?最?多?三?星?級(jí)?!'}]
"""
可以對(duì)比和貪婪解碼看一下結(jié)果。
9Multinomial sampling
與總是選擇概率最高的標(biāo)記作為下一個(gè)標(biāo)記的貪婪搜索相反,多項(xiàng)式抽樣(也稱(chēng)為祖先抽樣)根據(jù)模型給出的整個(gè)詞匯的概率分布來(lái)隨機(jī)選擇下一個(gè)標(biāo)記。每個(gè)概率不為零的符號(hào)都有機(jī)會(huì)被選中,從而減少了重復(fù)的風(fēng)險(xiǎn)。
from?transformers?import?AutoTokenizer,?AutoModelForCausalLM,?TextGenerationPipeline,?pipeline
tokenizer?=?AutoTokenizer.from_pretrained("./gpt2-chinese")
model?=?AutoModelForCausalLM.from_pretrained("./gpt2-chinese")
from?datasets?import?load_dataset
data_file?=?"./ChnSentiCorp_htl_all.csv"
dataset?=?load_dataset("csv",?data_files=data_file)
dataset?=?dataset.filter(lambda?x:?x["review"]?is?not?None)
dataset?=?dataset["train"].train_test_split(0.2,?seed=123)
import?random
example?=?random.choice(dataset["train"])
#?text?=?dataset["train"][0]
text?=?example["review"]
input_text?=?text[:10]
print(input_text)
#?greedy?search
model.eval()
with?torch.no_grad():
??encoding?=?tokenizer(input_text,?
??????????????return_tensors='pt',?
??????????????padding=False,?
??????????????add_special_tokens=False,
??????????????return_token_type_ids=False,
??????????????return_attention_mask=False,)
??
??generated_ids?=?model.generate(**encoding,?
????????????????????max_length=100,?
????????????????????eos_token_id=0,?
????????????????????pad_token_id=0,
????????????????????do_sample=True,
????????????????????num_beams=1,?
????????????????????)?
??generated_texts?=?tokenizer.batch_decode(generated_ids,?skip_special_tokens=True)
??print(generated_texts)
text_generator?=?TextGenerationPipeline(model,?tokenizer)??
print(text_generator(input_text,?
???????????max_length=100,?
???????????eos_token_id=0,?
???????????num_beams=1,?
???????????do_sample=True,
???????????pad_token_id=0,
???????????))
generator?=?pipeline("text-generation",?model=model,?tokenizer=tokenizer)
generation_config?=?{
??"max_length":?100,
??"eos_token_id":?0,
??"pad_token_id":?0,
??"num_beams":?1,?
??"do_sample":?True,
}
print(generator(input_text,?**generation_config))
"""
['房?間?:?建?筑?風(fēng)?格?比?較?獨(dú)?特?,?但?不?顯?現(xiàn)?空?間?特?色?。?地?理?位?置?不?是?很?好?,?離?九?華?山?比?較?遠(yuǎn)?,?出?租?車(chē)?還?比?較?難?找?。?門(mén)?童?服?務(wù)?蠻?好?,?門(mén)?口?迎?賓?也?很?熱?情?。?房?間?設(shè)?施?:?住?9?樓?標(biāo)?房?,?朝?西?,?馬?路?上?的?喧?囂?比?較']
[{'generated_text':?'房間:建筑風(fēng)格比較獨(dú)?特?,?墻?壁?由?黑?色?為?主?,?給?人?一?種?溫?馨?的?感?覺(jué)?,?房?間?內(nèi)?少?點(diǎn)?什?么?裝?飾?,?總?體?還?算?可?以?。?交?通?:?訂?一?輛?出?租?車(chē)?,?一?天?之?內(nèi)?送?完?了?,?一?天?后?再?打?車(chē)?,?車(chē)?子?要?走?到?春?熙?路?,?十?分?方?便'}]
[{'generated_text':?'房間:建筑風(fēng)格比較獨(dú)?特?,?比?較?特?別?的?是?窗?外?的?自?然?環(huán)?境?,?很?漂?亮?,?房?間?內(nèi)?的?設(shè)?施?也?不?錯(cuò)?,?有?獨(dú)?立?的?陽(yáng)?臺(tái)?,?所?謂?的?山?景?房?看?風(fēng)?景?也?能?看?到?大?草?坪?和?遠(yuǎn)?處?的?大?海?。?服?務(wù)?:?因?為?我?和?的?朋?友?預(yù)?定?的?是?山'}]
"""
10Beam-search decoding
與貪婪搜索不同的是,集束搜索解碼在每個(gè)時(shí)間步驟中保留幾個(gè)假設(shè),并最終選擇對(duì)整個(gè)序列具有最高概率的假設(shè)。這具有識(shí)別高概率序列的優(yōu)勢(shì),這些序列從較低概率的初始標(biāo)記開(kāi)始,會(huì)被貪婪搜索所忽略。
要啟用這種解碼策略,需要指定num_beams(又稱(chēng)要跟蹤的假說(shuō)數(shù)量)大于1。集束搜索通過(guò)在每個(gè)時(shí)間步保留最可能的 num_beams
個(gè)詞,并從中最終選擇出概率最高的序列來(lái)降低丟失潛在的高概率序列的風(fēng)險(xiǎn)。以 num_beams=2
為例:
最終得到:the dog has (0.4+0.9) > the nice woman (0.5+0.4)。
缺點(diǎn):雖然結(jié)果比貪心搜索更流暢,但輸出中仍然包含重復(fù)。
from?transformers?import?AutoTokenizer,?AutoModelForCausalLM,?TextGenerationPipeline,?pipeline
tokenizer?=?AutoTokenizer.from_pretrained("./gpt2-chinese")
model?=?AutoModelForCausalLM.from_pretrained("./gpt2-chinese")
from?datasets?import?load_dataset
data_file?=?"./ChnSentiCorp_htl_all.csv"
dataset?=?load_dataset("csv",?data_files=data_file)
dataset?=?dataset.filter(lambda?x:?x["review"]?is?not?None)
dataset?=?dataset["train"].train_test_split(0.2,?seed=123)
import?random
example?=?random.choice(dataset["train"])
#?text?=?dataset["train"][0]
text?=?example["review"]
input_text?=?text[:10]
print(input_text)
#?greedy?search
model.eval()
with?torch.no_grad():
??encoding?=?tokenizer(input_text,?
??????????????return_tensors='pt',?
??????????????padding=False,?
??????????????add_special_tokens=False,
??????????????return_token_type_ids=False,
??????????????return_attention_mask=False,)
??
??generated_ids?=?model.generate(**encoding,?
????????????????????max_length=100,?
????????????????????eos_token_id=0,?
????????????????????pad_token_id=0,
????????????????????do_sample=False,
????????????????????num_beams=4,?
????????????????????)?
??generated_texts?=?tokenizer.batch_decode(generated_ids,?skip_special_tokens=True)
??print(generated_texts)
text_generator?=?TextGenerationPipeline(model,?tokenizer)??
print(text_generator(input_text,?
???????????max_length=100,?
???????????eos_token_id=0,?
???????????num_beams=4,?
???????????do_sample=False,
???????????pad_token_id=0,
???????????))
generator?=?pipeline("text-generation",?model=model,?tokenizer=tokenizer)
generation_config?=?{
??"max_length":?100,
??"eos_token_id":?0,
??"pad_token_id":?0,
??"num_beams":?4,?
??"do_sample":?False,
}
print(generator(input_text,?**generation_config))
"""
酒店的整體服務(wù)意識(shí)相
['酒?店?的?整?體?服?務(wù)?意?識(shí)?相?當(dāng)?好?,?對(duì)?于?未?按?照?預(yù)?訂?時(shí)?間?到?達(dá)?的?客?戶(hù)?,?還?能?夠?保?留?預(yù)?訂?,?但?是?溝?通?技?巧?不?是?很?好?,?還?有?對(duì)?于?未?按?預(yù)?訂?時(shí)?間?到?達(dá)?的?客?戶(hù)?,?還?要?給?攜?程?的?工?作?帶?來(lái)?很?大?麻?煩?。']
[{'generated_text':?'酒店的整體服務(wù)意識(shí)相?當(dāng)?好?,?對(duì)?于?未?按?照?預(yù)?訂?時(shí)?間?到?達(dá)?的?客?戶(hù)?,?還?能?夠?保?留?預(yù)?訂?,?但?是?溝?通?技?巧?不?是?很?好?,?還?有?對(duì)?于?未?按?預(yù)?訂?時(shí)?間?到?達(dá)?的?客?戶(hù)?,?還?要?給?攜?程?的?工?作?帶?來(lái)?很?大?麻?煩?。'}]
[{'generated_text':?'酒店的整體服務(wù)意識(shí)相?當(dāng)?好?,?對(duì)?于?未?按?照?預(yù)?訂?時(shí)?間?到?達(dá)?的?客?戶(hù)?,?還?能?夠?保?留?預(yù)?訂?,?但?是?溝?通?技?巧?不?是?很?好?,?還?有?對(duì)?于?未?按?預(yù)?訂?時(shí)?間?到?達(dá)?的?客?戶(hù)?,?還?要?給?攜?程?的?工?作?帶?來(lái)?很?大?麻?煩?。'}]
"""
11Beam-search multinomial sampling
顧名思義,這種解碼策略結(jié)合了集束搜索和多指標(biāo)采樣。你需要指定num_beams大于1,并設(shè)置do_sample=True來(lái)使用這種解碼策略。
from?transformers?import?AutoTokenizer,?AutoModelForCausalLM,?TextGenerationPipeline,?pipeline
tokenizer?=?AutoTokenizer.from_pretrained("./gpt2-chinese")
model?=?AutoModelForCausalLM.from_pretrained("./gpt2-chinese")
from?datasets?import?load_dataset
data_file?=?"./ChnSentiCorp_htl_all.csv"
dataset?=?load_dataset("csv",?data_files=data_file)
dataset?=?dataset.filter(lambda?x:?x["review"]?is?not?None)
dataset?=?dataset["train"].train_test_split(0.2,?seed=123)
import?random
example?=?random.choice(dataset["train"])
#?text?=?dataset["train"][0]
text?=?example["review"]
input_text?=?text[:10]
print(input_text)
#?greedy?search
model.eval()
with?torch.no_grad():
??encoding?=?tokenizer(input_text,?
??????????????return_tensors='pt',?
??????????????padding=False,?
??????????????add_special_tokens=False,
??????????????return_token_type_ids=False,
??????????????return_attention_mask=False,)
??
??generated_ids?=?model.generate(**encoding,?
????????????????????max_length=100,?
????????????????????eos_token_id=0,?
????????????????????pad_token_id=0,
????????????????????do_sample=True,
????????????????????num_beams=4,?
????????????????????)?
??generated_texts?=?tokenizer.batch_decode(generated_ids,?skip_special_tokens=True)
??print(generated_texts)
text_generator?=?TextGenerationPipeline(model,?tokenizer)??
print(text_generator(input_text,?
???????????max_length=100,?
???????????eos_token_id=0,?
???????????num_beams=4,?
???????????do_sample=True,
???????????pad_token_id=0,
???????????))
generator?=?pipeline("text-generation",?model=model,?tokenizer=tokenizer)
generation_config?=?{
??"max_length":?100,
??"eos_token_id":?0,
??"pad_token_id":?0,
??"num_beams":?4,?
??"do_sample":?True,
}
print(generator(input_text,?**generation_config))
"""
['酒?店?在?肇?慶?鬧?市?區(qū)?,?但?交?通?非?常?方?便?,?酒?店?服?務(wù)?員?態(tài)?度?非?常?好?,?酒?店?硬?件?條?件?還?可?以?,?就?是?房?間?隔?音?效?果?非?常?不?好?,?隔?壁?的?電?視?聲?音?、?走?廊?人?說(shuō)?話(huà)?聲?等?清?清?楚?楚?,?住?在?一?樓?還?能?聽(tīng)?到?隔?壁?房?間?的?電']
[{'generated_text':?'酒店在肇慶鬧市區(qū),但?交?通?非?常?方?便?,?酒?店?服?務(wù)?態(tài)?度?很?好?,?房?間?干?凈?整?潔?,?下?次?去?肇?慶?還?會(huì)?選?擇?該?酒?店?。'}]
[{'generated_text':?'酒店在肇慶鬧市區(qū),但?交?通?非?常?方?便?,?酒?店?環(huán)?境?不?錯(cuò)?,?房?間?比?較?干?凈?,?服?務(wù)?員?態(tài)?度?也?很?好?,?總?的?來(lái)?說(shuō)?是?一?家?不?錯(cuò)?的?酒?店?。'}]
"""
12Diverse beam search decoding
多樣化集束搜索解碼策略是對(duì)集束搜索策略的擴(kuò)展,可以生成更多樣化的集束序列供人們選擇。要了解它的工作原理,請(qǐng)參考《多樣化集束搜索》https://arxiv.org/pdf/1610.02424.pdf: 從神經(jīng)序列模型解碼多樣化的解決方案。這種方法有兩個(gè)主要參數(shù):num_beams和num_beam_groups。組的選擇是為了確保它們與其他組相比有足夠的區(qū)別,并在每個(gè)組內(nèi)使用常規(guī)集束搜索。
from?transformers?import?AutoTokenizer,?AutoModelForCausalLM,?TextGenerationPipeline,?pipeline
tokenizer?=?AutoTokenizer.from_pretrained("./gpt2-chinese")
model?=?AutoModelForCausalLM.from_pretrained("./gpt2-chinese")
from?datasets?import?load_dataset
data_file?=?"./ChnSentiCorp_htl_all.csv"
dataset?=?load_dataset("csv",?data_files=data_file)
dataset?=?dataset.filter(lambda?x:?x["review"]?is?not?None)
dataset?=?dataset["train"].train_test_split(0.2,?seed=123)
import?random
example?=?random.choice(dataset["train"])
#?text?=?dataset["train"][0]
text?=?example["review"]
input_text?=?text[:10]
print(input_text)
#?greedy?search
model.eval()
with?torch.no_grad():
??encoding?=?tokenizer(input_text,?
??????????????return_tensors='pt',?
??????????????padding=False,?
??????????????add_special_tokens=False,
??????????????return_token_type_ids=False,
??????????????return_attention_mask=False,)
??
??generated_ids?=?model.generate(**encoding,?
????????????????????max_length=100,?
????????????????????eos_token_id=0,?
????????????????????pad_token_id=0,
????????????????????do_sample=False,
????????????????????num_beams=4,?
????????????????????num_beam_groups=4,
????????????????????)?
??generated_texts?=?tokenizer.batch_decode(generated_ids,?skip_special_tokens=True)
??print(generated_texts)
text_generator?=?TextGenerationPipeline(model,?tokenizer)??
print(text_generator(input_text,?
???????????max_length=100,?
???????????eos_token_id=0,?
???????????num_beams=4,?
???????????do_sample=False,
???????????pad_token_id=0,
???????????num_beam_groups=4,
???????????))
generator?=?pipeline("text-generation",?model=model,?tokenizer=tokenizer)
generation_config?=?{
??"max_length":?100,
??"eos_token_id":?0,
??"pad_token_id":?0,
??"num_beams":?4,?
??"do_sample":?False,
??"num_beam_groups":?4,
}
print(generator(input_text,?**generation_config))
"""
住過(guò)如此之多的如家酒
['住?過(guò)?如?此?之?多?的?如?家?酒?店?,?這?一?家?是?最?差?的?,?服?務(wù)?差?,?房?間?老?舊?,?而?且?價(jià)?格?還?不?低?。?下?次?不?會(huì)?再?住?了?。']
[{'generated_text':?'住過(guò)如此之多的如家酒?店?,?這?一?家?是?最?差?的?,?服?務(wù)?差?,?房?間?老?舊?,?而?且?價(jià)?格?還?不?低?。?下?次?不?會(huì)?再?住?了?。'}]
[{'generated_text':?'住過(guò)如此之多的如家酒?店?,?這?一?家?是?最?差?的?,?服?務(wù)?差?,?房?間?老?舊?,?而?且?價(jià)?格?還?不?低?。?下?次?不?會(huì)?再?住?了?。'}]
"""
Part5補(bǔ)充
13常用的一些參數(shù):
no_repeat_ngram_size:限制任意 N-gram 不會(huì)出現(xiàn)兩次。但是, n-gram 懲罰使用時(shí)必須謹(jǐn)慎,如一篇關(guān)于 紐約 這個(gè)城市的文章就不應(yīng)使用 2-gram 懲罰,否則,城市名稱(chēng)在整個(gè)文本中將只出現(xiàn)一次! num_return_sequences :選擇返回句子的數(shù)量,記得確保 num_return_sequences <= num_beams
top_p top_k temperature repetition_penalty
14采樣
采樣意味著根據(jù)當(dāng)前條件概率分布隨機(jī)選擇輸出詞 ,使用采樣方法時(shí)文本生成本身不再是確定性的。對(duì)單詞序列進(jìn)行采樣時(shí)的大問(wèn)題: 模型通常會(huì)產(chǎn)生不連貫的亂碼??梢栽O(shè)置top_k=0關(guān)閉采樣。緩解這一問(wèn)題的一個(gè)技巧是通過(guò)降低所謂的 softmax 的“溫度”使分布 更陡峭。而降低“溫度”,本質(zhì)上是增加高概率單詞的似然并降低低概率單詞的似然。
將溫度應(yīng)用到于我們的例子中后,結(jié)果如下圖所示。
時(shí)刻單詞的條件分布變得更加陡峭,幾乎沒(méi)有機(jī)會(huì)選擇單詞 “car” 了。雖然溫度可以使分布的隨機(jī)性降低,但極限條件下,當(dāng)“溫度”設(shè)置為 0 時(shí),溫度縮放采樣就退化成貪心解碼了,因此會(huì)遇到與貪心解碼相同的問(wèn)題。
15Top-K采樣
在 Top-K 采樣中,概率最大的 K 個(gè)詞會(huì)被選出,然后這 K 個(gè)詞的概率會(huì)被重新歸一化,最后就在這重新被歸一化概率后的 K 個(gè)詞中采樣。 GPT2 采用了這種采樣方案,這也是它在故事生成這樣的任務(wù)上取得成功的原因之一。
假設(shè):top_k=6
輸入:the, the的下一個(gè)詞從概率最大的top6里面采樣到car,the car的下一個(gè)詞從概率最大的top6里面采樣??梢钥吹胶竺嬉恍┢婀值脑~就可以被忽略掉。
16Top-P采樣
在 Top-p 中,采樣不只是在最有可能的 K 個(gè)單詞中進(jìn)行,而是在累積概率超過(guò)概率 p 的最小單詞集中進(jìn)行。然后在這組詞中重新分配概率質(zhì)量。這樣,詞集的大小 (又名 集合中的詞數(shù)) 可以根據(jù)下一個(gè)詞的概率分布動(dòng)態(tài)增加和減少。好吧,說(shuō)的很啰嗦,一圖勝千言。
假設(shè) p=0.92 , Top-p 采樣對(duì)單詞概率進(jìn)行降序排列并累加,然后選擇概率和首次超過(guò) p=0.92 的單詞集作為采樣池,可以看出,在單詞比較不可預(yù)測(cè)時(shí),它保留了更多的候選詞。而當(dāng)單詞似乎更容易預(yù)測(cè)時(shí),只保留了幾個(gè)候選詞。
一般而言,結(jié)合top_k和top_p會(huì)有不錯(cuò)的效果。
Part6參考
Text generation strategies (huggingface.co)
transformers/configuration_utils.py at v4.28.1 · huggingface/transformers · GitHub
transformers/text_generation.py at v4.28.1 · huggingface/transformers · GitHub
基于 transformers 的 generate() 方法實(shí)現(xiàn)多樣化文本生成:參數(shù)含義和算法原理解讀_transformers generate_木堯大兄弟的博客-CSDN博客
https://zhuanlan.zhihu.com/p/624636122文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-425006.html
文中部分文字和圖摘自上述文章。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-425006.html
到了這里,關(guān)于LLM(大語(yǔ)言模型)解碼時(shí)是怎么生成文本的?的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!