18 KiB
Text generation strategiestext-generation-strategies
ํ ์คํธ ์์ฑ์ ๊ฐ๋ฐฉํ ํ ์คํธ ์์ฑ, ์์ฝ, ๋ฒ์ญ ๋ฑ ๋ค์ํ ์์ฐ์ด ์ฒ๋ฆฌ(NLP) ์์ ์ ํ์์ ์ ๋๋ค. ์ด๋ ๋ํ ์์ฑ-ํ ์คํธ ๋ณํ, ์๊ฐ-ํ ์คํธ ๋ณํ๊ณผ ๊ฐ์ด ํ ์คํธ๋ฅผ ์ถ๋ ฅ์ผ๋ก ํ๋ ์ฌ๋ฌ ํผํฉ ๋ชจ๋ฌ๋ฆฌํฐ ์์ฉ ํ๋ก๊ทธ๋จ์์๋ ์ค์ํ ์ญํ ์ ํฉ๋๋ค. ํ ์คํธ ์์ฑ์ ๊ฐ๋ฅํ๊ฒ ํ๋ ๋ช๋ช ๋ชจ๋ธ๋ก๋ GPT2, XLNet, OpenAI GPT, CTRL, TransformerXL, XLM, Bart, T5, GIT, Whisper ๋ฑ์ด ์์ต๋๋ค.
[~generation.GenerationMixin.generate] ๋ฉ์๋๋ฅผ ํ์ฉํ์ฌ ๋ค์๊ณผ ๊ฐ์ ๋ค์ํ ์์
๋ค์ ๋ํด ํ
์คํธ ๊ฒฐ๊ณผ๋ฌผ์ ์์ฑํ๋ ๋ช ๊ฐ์ง ์์๋ฅผ ์ดํด๋ณด์ธ์:
generate ๋ฉ์๋์ ์ ๋ ฅ๋๋ ๊ฐ๋ค์ ๋ชจ๋ธ์ ๋ฐ์ดํฐ ํํ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋๋ค. ์ด ๊ฐ๋ค์ AutoTokenizer๋ AutoProcessor์ ๊ฐ์ ๋ชจ๋ธ์ ์ ์ฒ๋ฆฌ ํด๋์ค์ ์ํด ๋ฐํ๋ฉ๋๋ค. ๋ชจ๋ธ์ ์ ์ฒ๋ฆฌ ์ฅ์น๊ฐ ํ๋ ์ด์์ ์ ๋ ฅ ์ ํ์ ์์ฑํ๋ ๊ฒฝ์ฐ, ๋ชจ๋ ์ ๋ ฅ์ generate()์ ์ ๋ฌํด์ผ ํฉ๋๋ค. ๊ฐ ๋ชจ๋ธ์ ์ ์ฒ๋ฆฌ ์ฅ์น์ ๋ํด์๋ ํด๋น ๋ชจ๋ธ์ ๋ฌธ์์์ ์์ธํ ์์๋ณผ ์ ์์ต๋๋ค.
ํ
์คํธ๋ฅผ ์์ฑํ๊ธฐ ์ํด ์ถ๋ ฅ ํ ํฐ์ ์ ํํ๋ ๊ณผ์ ์ ๋์ฝ๋ฉ์ด๋ผ๊ณ ํ๋ฉฐ, generate() ๋ฉ์๋๊ฐ ์ฌ์ฉํ ๋์ฝ๋ฉ ์ ๋ต์ ์ฌ์ฉ์๊ฐ ์ปค์คํฐ๋ง์ด์งํ ์ ์์ต๋๋ค. ๋์ฝ๋ฉ ์ ๋ต์ ์์ ํ๋ ๊ฒ์ ํ๋ จ ๊ฐ๋ฅํ ๋งค๊ฐ๋ณ์์ ๊ฐ๋ค์ ๋ณ๊ฒฝํ์ง ์์ง๋ง, ์์ฑ๋ ์ถ๋ ฅ์ ํ์ง์ ๋์ ๋๋ ์ํฅ์ ์ค ์ ์์ต๋๋ค. ์ด๋ ํ
์คํธ์์ ๋ฐ๋ณต์ ์ค์ด๊ณ , ๋ ์ผ๊ด์ฑ ์๊ฒ ๋ง๋๋ ๋ฐ ๋์์ ์ค ์ ์์ต๋๋ค.
์ด ๊ฐ์ด๋์์๋ ๋ค์๊ณผ ๊ฐ์ ๋ด์ฉ์ ๋ค๋ฃน๋๋ค:
- ๊ธฐ๋ณธ ์์ฑ ์ค์
- ์ผ๋ฐ์ ์ธ ๋์ฝ๋ฉ ์ ๋ต๊ณผ ์ฃผ์ ํ๋ผ๋ฏธํฐ
- ๐ค Hub์์ ๋ฏธ์ธ ์กฐ์ ๋ ๋ชจ๋ธ๊ณผ ํจ๊ป ์ฌ์ฉ์ ์ ์ ์์ฑ ์ค์ ์ ์ ์ฅํ๊ณ ๊ณต์ ํ๋ ๋ฐฉ๋ฒ
๊ธฐ๋ณธ ํ ์คํธ ์์ฑ ์ค์ default-text-generation-configuration
๋ชจ๋ธ์ ๋์ฝ๋ฉ ์ ๋ต์ ์์ฑ ์ค์ ์์ ์ ์๋ฉ๋๋ค. ์ฌ์ ํ๋ จ๋ ๋ชจ๋ธ์ [pipeline] ๋ด์์ ์ถ๋ก ์ ์ฌ์ฉํ ๋, ๋ชจ๋ธ์ ๋ด๋ถ์ ์ผ๋ก ๊ธฐ๋ณธ ์์ฑ ์ค์ ์ ์ ์ฉํ๋ PreTrainedModel.generate() ๋ฉ์๋๋ฅผ ํธ์ถํฉ๋๋ค. ์ฌ์ฉ์๊ฐ ๋ชจ๋ธ๊ณผ ํจ๊ป ์ฌ์ฉ์ ์ ์ ์ค์ ์ ์ ์ฅํ์ง ์์์ ๊ฒฝ์ฐ์๋ ๊ธฐ๋ณธ ์ค์ ์ด ์ฌ์ฉ๋ฉ๋๋ค.
๋ชจ๋ธ์ ๋ช
์์ ์ผ๋ก ๋ก๋ํ ๋, model.generation_config์ ํตํด ์ ๊ณต๋๋ ์์ฑ ์ค์ ์ ๊ฒ์ฌํ ์ ์์ต๋๋ค.
>>> from transformers import AutoModelForCausalLM
>>> model = AutoModelForCausalLM.from_pretrained("distilbert/distilgpt2")
>>> model.generation_config
GenerationConfig {
"bos_token_id": 50256,
"eos_token_id": 50256,
}
model.generation_config๋ฅผ ์ถ๋ ฅํ๋ฉด ๊ธฐ๋ณธ ์ค์ ๊ณผ ๋ค๋ฅธ ๊ฐ๋ค๋ง ํ์๋๊ณ , ๊ธฐ๋ณธ๊ฐ๋ค์ ๋์ด๋์ง ์์ต๋๋ค.
๊ธฐ๋ณธ ์์ฑ ์ค์ ์ ์ ๋ ฅ ํ๋กฌํํธ์ ์ถ๋ ฅ์ ํฉ์น ์ต๋ ํฌ๊ธฐ๋ฅผ 20 ํ ํฐ์ผ๋ก ์ ํํ์ฌ ๋ฆฌ์์ค ๋ถ์กฑ์ ๋ฐฉ์งํฉ๋๋ค. ๊ธฐ๋ณธ ๋์ฝ๋ฉ ์ ๋ต์ ํ์ ํ์(greedy search)์ผ๋ก, ๋ค์ ํ ํฐ์ผ๋ก ๊ฐ์ฅ ๋์ ํ๋ฅ ์ ๊ฐ์ง ํ ํฐ์ ์ ํํ๋ ๊ฐ์ฅ ๋จ์ํ ๋์ฝ๋ฉ ์ ๋ต์ ๋๋ค. ๋ง์ ์์ ๊ณผ ์์ ์ถ๋ ฅ ํฌ๊ธฐ์ ๋ํด์๋ ์ด ๋ฐฉ๋ฒ์ด ์ ์๋ํ์ง๋ง, ๋ ๊ธด ์ถ๋ ฅ์ ์์ฑํ ๋ ์ฌ์ฉํ๋ฉด ๋งค์ฐ ๋ฐ๋ณต์ ์ธ ๊ฒฐ๊ณผ๋ฅผ ์์ฑํ๊ฒ ๋ ์ ์์ต๋๋ค.
ํ ์คํธ ์์ฑ ์ฌ์ฉ์ ์ ์customize-text-generation
ํ๋ผ๋ฏธํฐ์ ํด๋น ๊ฐ์ [generate] ๋ฉ์๋์ ์ง์ ์ ๋ฌํ์ฌ generation_config์ ์ฌ์ ์ํ ์ ์์ต๋๋ค:
>>> my_model.generate(**inputs, num_beams=4, do_sample=True) # doctest: +SKIP
๊ธฐ๋ณธ ๋์ฝ๋ฉ ์ ๋ต์ด ๋๋ถ๋ถ์ ์์ ์ ์ ์๋ํ๋ค ํ๋๋ผ๋, ์กฐ์ ํ ์ ์๋ ๋ช ๊ฐ์ง ํ๋ผ๋ฏธํฐ๊ฐ ์์ต๋๋ค. ์ผ๋ฐ์ ์ผ๋ก ์กฐ์ ๋๋ ํ๋ผ๋ฏธํฐ์๋ ๋ค์๊ณผ ๊ฐ์ ๊ฒ๋ค์ด ํฌํจ๋ฉ๋๋ค:
max_new_tokens: ์์ฑํ ์ต๋ ํ ํฐ ์์ ๋๋ค. ์ฆ, ํ๋กฌํํธ์ ์๋ ํ ํฐ์ ์ ์ธํ ์ถ๋ ฅ ์ํ์ค์ ํฌ๊ธฐ์ ๋๋ค. ์ถ๋ ฅ์ ๊ธธ์ด๋ฅผ ์ค๋จ ๊ธฐ์ค์ผ๋ก ์ฌ์ฉํ๋ ๋์ , ์ ์ฒด ์์ฑ๋ฌผ์ด ์ผ์ ์๊ฐ์ ์ด๊ณผํ ๋ ์์ฑ์ ์ค๋จํ๊ธฐ๋ก ์ ํํ ์๋ ์์ต๋๋ค. ๋ ์์๋ณด๋ ค๋ฉด [StoppingCriteria]๋ฅผ ํ์ธํ์ธ์.num_beams: 1๋ณด๋ค ํฐ ์์ ๋น์ ์ง์ ํจ์ผ๋ก์จ, ํ์ ํ์(greedy search)์์ ๋น ํ์(beam search)์ผ๋ก ์ ํํ๊ฒ ๋ฉ๋๋ค. ์ด ์ ๋ต์ ๊ฐ ์๊ฐ ๋จ๊ณ์์ ์ฌ๋ฌ ๊ฐ์ค์ ํ๊ฐํ๊ณ ๊ฒฐ๊ตญ ์ ์ฒด ์ํ์ค์ ๋ํด ๊ฐ์ฅ ๋์ ํ๋ฅ ์ ๊ฐ์ง ๊ฐ์ค์ ์ ํํฉ๋๋ค. ์ด๋ ์ด๊ธฐ ํ ํฐ์ ํ๋ฅ ์ด ๋ฎ์ ํ์ ํ์์ ์ํด ๋ฌด์๋์์ ๋์ ํ๋ฅ ์ ์ํ์ค๋ฅผ ์๋ณํ ์ ์๋ ์ฅ์ ์ ๊ฐ์ง๋๋ค.do_sample: ์ด ๋งค๊ฐ๋ณ์๋ฅผTrue๋ก ์ค์ ํ๋ฉด, ๋คํญ ์ํ๋ง, ๋น ํ์ ๋คํญ ์ํ๋ง, Top-K ์ํ๋ง ๋ฐ Top-p ์ํ๋ง๊ณผ ๊ฐ์ ๋์ฝ๋ฉ ์ ๋ต์ ํ์ฑํํฉ๋๋ค. ์ด๋ฌํ ์ ๋ต๋ค์ ์ ์ฒด ์ดํ์ ๋ํ ํ๋ฅ ๋ถํฌ์์ ๋ค์ ํ ํฐ์ ์ ํํ๋ฉฐ, ์ ๋ต๋ณ๋ก ํน์ ์กฐ์ ์ด ์ ์ฉ๋ฉ๋๋ค.num_return_sequences: ๊ฐ ์ ๋ ฅ์ ๋ํด ๋ฐํํ ์ํ์ค ํ๋ณด์ ์์ ๋๋ค. ์ด ์ต์ ์ ๋น ํ์(beam search)์ ๋ณํ๊ณผ ์ํ๋ง๊ณผ ๊ฐ์ด ์ฌ๋ฌ ์ํ์ค ํ๋ณด๋ฅผ ์ง์ํ๋ ๋์ฝ๋ฉ ์ ๋ต์๋ง ์ฌ์ฉํ ์ ์์ต๋๋ค. ํ์ ํ์(greedy search) ๊ฐ์ ๋์ฝ๋ฉ ์ ๋ต์ ๋จ์ผ ์ถ๋ ฅ ์ํ์ค๋ฅผ ๋ฐํํฉ๋๋ค.
๋ชจ๋ธ์ ์ฌ์ฉ์ ์ ์ ๋์ฝ๋ฉ ์ ๋ต ์ ์ฅsave-a-custom-decoding-strategy-with-your-model
ํน์ ์์ฑ ์ค์ ์ ๊ฐ์ง ๋ฏธ์ธ ์กฐ์ ๋ ๋ชจ๋ธ์ ๊ณต์ ํ๊ณ ์ ํ ๋, ๋ค์ ๋จ๊ณ๋ฅผ ๋ฐ๋ฅผ ์ ์์ต๋๋ค:
- [
GenerationConfig] ํด๋์ค ์ธ์คํด์ค๋ฅผ ์์ฑํฉ๋๋ค. - ๋์ฝ๋ฉ ์ ๋ต ํ๋ผ๋ฏธํฐ๋ฅผ ์ค์ ํฉ๋๋ค.
- ์์ฑ ์ค์ ์ [
GenerationConfig.save_pretrained]๋ฅผ ์ฌ์ฉํ์ฌ ์ ์ฅํ๋ฉฐ,config_file_name์ธ์๋ ๋น์๋ก๋๋ค. - ๋ชจ๋ธ์ ์ ์ฅ์์ ์ค์ ์ ์
๋ก๋ํ๊ธฐ ์ํด
push_to_hub๋ฅผTrue๋ก ์ค์ ํฉ๋๋ค.
>>> from transformers import AutoModelForCausalLM, GenerationConfig
>>> model = AutoModelForCausalLM.from_pretrained("my_account/my_model") # doctest: +SKIP
>>> generation_config = GenerationConfig(
... max_new_tokens=50, do_sample=True, top_k=50, eos_token_id=model.config.eos_token_id
... )
>>> generation_config.save_pretrained("my_account/my_model", push_to_hub=True) # doctest: +SKIP
๋จ์ผ ๋๋ ํ ๋ฆฌ์ ์ฌ๋ฌ ์์ฑ ์ค์ ์ ์ ์ฅํ ์ ์์ผ๋ฉฐ, ์ด๋ [GenerationConfig.save_pretrained]์ config_file_name ์ธ์๋ฅผ ์ฌ์ฉํฉ๋๋ค. ๋์ค์ [GenerationConfig.from_pretrained]๋ก ์ด๋ค์ ์ธ์คํด์คํํ ์ ์์ต๋๋ค. ์ด๋ ๋จ์ผ ๋ชจ๋ธ์ ๋ํด ์ฌ๋ฌ ์์ฑ ์ค์ ์ ์ ์ฅํ๊ณ ์ถ์ ๋ ์ ์ฉํฉ๋๋ค(์: ์ํ๋ง์ ์ด์ฉํ ์ฐฝ์์ ํ
์คํธ ์์ฑ์ ์ํ ํ๋, ๋น ํ์์ ์ด์ฉํ ์์ฝ์ ์ํ ๋ค๋ฅธ ํ๋ ๋ฑ). ๋ชจ๋ธ์ ์ค์ ํ์ผ์ ์ถ๊ฐํ๊ธฐ ์ํด ์ ์ ํ Hub ๊ถํ์ ๊ฐ์ง๊ณ ์์ด์ผ ํฉ๋๋ค.
>>> from transformers import AutoModelForSeq2SeqLM, AutoTokenizer, GenerationConfig
>>> tokenizer = AutoTokenizer.from_pretrained("google-t5/t5-small")
>>> model = AutoModelForSeq2SeqLM.from_pretrained("google-t5/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,
... )
>>> # ํ: Hub์ pushํ๋ ค๋ฉด `push_to_hub=True`๋ฅผ ์ถ๊ฐ
>>> translation_generation_config.save_pretrained("/tmp", "translation_generation_config.json")
>>> # ๋ช
๋ช
๋ ์์ฑ ์ค์ ํ์ผ์ ์ฌ์ฉํ์ฌ ์์ฑ์ ๋งค๊ฐ๋ณ์ํํ ์ ์์ต๋๋ค.
>>> generation_config = GenerationConfig.from_pretrained("/tmp", "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))
['Les fichiers de configuration sont faciles ร utiliser!']
์คํธ๋ฆฌ๋ฐstreaming
generate() ๋ฉ์๋๋ streamer ์
๋ ฅ์ ํตํด ์คํธ๋ฆฌ๋ฐ์ ์ง์ํฉ๋๋ค. streamer ์
๋ ฅ์ put()๊ณผ end() ๋ฉ์๋๋ฅผ ๊ฐ์ง ํด๋์ค์ ์ธ์คํด์ค์ ํธํ๋ฉ๋๋ค. ๋ด๋ถ์ ์ผ๋ก, put()์ ์ ํ ํฐ์ ์ถ๊ฐํ๋ ๋ฐ ์ฌ์ฉ๋๋ฉฐ, end()๋ ํ
์คํธ ์์ฑ์ ๋์ ํ์ํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.
์คํธ๋ฆฌ๋จธ ํด๋์ค์ API๋ ์์ง ๊ฐ๋ฐ ์ค์ด๋ฉฐ, ํฅํ ๋ณ๊ฒฝ๋ ์ ์์ต๋๋ค.
์ค์ ๋ก ๋ค์ํ ๋ชฉ์ ์ ์ํด ์์ฒด ์คํธ๋ฆฌ๋ฐ ํด๋์ค๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค! ๋ํ, ๊ธฐ๋ณธ์ ์ธ ์คํธ๋ฆฌ๋ฐ ํด๋์ค๋ค๋ ์ค๋น๋์ด ์์ด ๋ฐ๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, [TextStreamer] ํด๋์ค๋ฅผ ์ฌ์ฉํ์ฌ generate()์ ์ถ๋ ฅ์ ํ๋ฉด์ ํ ๋จ์ด์ฉ ์คํธ๋ฆฌ๋ฐํ ์ ์์ต๋๋ค:
>>> from transformers import AutoModelForCausalLM, AutoTokenizer, TextStreamer
>>> tok = AutoTokenizer.from_pretrained("openai-community/gpt2")
>>> model = AutoModelForCausalLM.from_pretrained("openai-community/gpt2")
>>> inputs = tok(["An increasing sequence: one,"], return_tensors="pt")
>>> streamer = TextStreamer(tok)
>>> # ์คํธ๋ฆฌ๋จธ๋ ํ์์ ๊ฐ์ ์ถ๋ ฅ๊ฐ์ ๋ฐํํ ๋ฟ๋ง ์๋๋ผ ์์ฑ๋ ํ
์คํธ๋ ํ์ค ์ถ๋ ฅ(stdout)์ผ๋ก ์ถ๋ ฅํฉ๋๋ค.
>>> _ = model.generate(**inputs, streamer=streamer, max_new_tokens=20)
An increasing sequence: one, two, three, four, five, six, seven, eight, nine, ten, eleven,
๋์ฝ๋ฉ ์ ๋ตdecoding-strategies
generate() ๋งค๊ฐ๋ณ์์ ๊ถ๊ทน์ ์ผ๋ก generation_config์ ํน์ ์กฐํฉ์ ์ฌ์ฉํ์ฌ ํน์ ๋์ฝ๋ฉ ์ ๋ต์ ํ์ฑํํ ์ ์์ต๋๋ค. ์ด ๊ฐ๋
์ด ์ฒ์์ด๋ผ๋ฉด, ํํ ์ฌ์ฉ๋๋ ๋์ฝ๋ฉ ์ ๋ต์ด ์ด๋ป๊ฒ ์๋ํ๋์ง ์ค๋ช
ํ๋ ์ด ๋ธ๋ก๊ทธ ํฌ์คํธ๋ฅผ ์ฝ์ด๋ณด๋ ๊ฒ์ ์ถ์ฒํฉ๋๋ค.
์ฌ๊ธฐ์๋ ๋์ฝ๋ฉ ์ ๋ต์ ์ ์ดํ๋ ๋ช ๊ฐ์ง ๋งค๊ฐ๋ณ์๋ฅผ ๋ณด์ฌ์ฃผ๊ณ , ์ด๋ฅผ ์ด๋ป๊ฒ ์ฌ์ฉํ ์ ์๋์ง ์ค๋ช ํ๊ฒ ์ต๋๋ค.
ํ์ ํ์(Greedy Search)greedy-search
[generate]๋ ๊ธฐ๋ณธ์ ์ผ๋ก ํ์ ํ์ ๋์ฝ๋ฉ์ ์ฌ์ฉํ๋ฏ๋ก ์ด๋ฅผ ํ์ฑํํ๊ธฐ ์ํด ๋ณ๋์ ๋งค๊ฐ๋ณ์๋ฅผ ์ง์ ํ ํ์๊ฐ ์์ต๋๋ค. ์ด๋ num_beams๊ฐ 1๋ก ์ค์ ๋๊ณ do_sample=False๋ก ๋์ด ์๋ค๋ ์๋ฏธ์
๋๋ค."
>>> from transformers import AutoModelForCausalLM, AutoTokenizer
>>> prompt = "I look forward to"
>>> checkpoint = "distilbert/distilgpt2"
>>> tokenizer = AutoTokenizer.from_pretrained(checkpoint)
>>> inputs = tokenizer(prompt, return_tensors="pt")
>>> model = AutoModelForCausalLM.from_pretrained(checkpoint)
>>> outputs = model.generate(**inputs)
>>> tokenizer.batch_decode(outputs, skip_special_tokens=True)
['I look forward to seeing you all again!\n\n\n\n\n\n\n\n\n\n\n']
๋คํญ ์ํ๋ง(Multinomial sampling)multinomial-sampling
ํ์ ํ์(greedy search)์ด ํญ์ ๊ฐ์ฅ ๋์ ํ๋ฅ ์ ๊ฐ์ง ํ ํฐ์ ๋ค์ ํ ํฐ์ผ๋ก ์ ํํ๋ ๊ฒ๊ณผ ๋ฌ๋ฆฌ, ๋คํญ ์ํ๋ง(multinomial sampling, ์กฐ์ ์ํ๋ง(ancestral sampling)์ด๋ผ๊ณ ๋ ํจ)์ ๋ชจ๋ธ์ด ์ ๊ณตํ๋ ์ ์ฒด ์ดํ์ ๋ํ ํ๋ฅ ๋ถํฌ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋ค์ ํ ํฐ์ ๋ฌด์์๋ก ์ ํํฉ๋๋ค. 0์ด ์๋ ํ๋ฅ ์ ๊ฐ์ง ๋ชจ๋ ํ ํฐ์ ์ ํ๋ ๊ธฐํ๊ฐ ์์ผ๋ฏ๋ก, ๋ฐ๋ณต์ ์ํ์ ์ค์ผ ์ ์์ต๋๋ค.
๋คํญ ์ํ๋ง์ ํ์ฑํํ๋ ค๋ฉด do_sample=True ๋ฐ num_beams=1์ ์ค์ ํ์ธ์.
>>> from transformers import AutoTokenizer, AutoModelForCausalLM, set_seed
>>> set_seed(0) # ์ฌํ์ฑ์ ์ํด
>>> checkpoint = "openai-community/gpt2-large"
>>> tokenizer = AutoTokenizer.from_pretrained(checkpoint)
>>> model = AutoModelForCausalLM.from_pretrained(checkpoint)
>>> prompt = "Today was an amazing day because"
>>> inputs = tokenizer(prompt, return_tensors="pt")
>>> outputs = model.generate(**inputs, do_sample=True, num_beams=1, max_new_tokens=100)
>>> tokenizer.batch_decode(outputs, skip_special_tokens=True)
['Today was an amazing day because when you go to the World Cup and you don\'t, or when you don\'t get invited,
that\'s a terrible feeling."']
๋น ํ์(Beam-search) ๋์ฝ๋ฉbeam-search-decoding
ํ์ ๊ฒ์(greedy search)๊ณผ ๋ฌ๋ฆฌ, ๋น ํ์(beam search) ๋์ฝ๋ฉ์ ๊ฐ ์๊ฐ ๋จ๊ณ์์ ์ฌ๋ฌ ๊ฐ์ค์ ์ ์งํ๊ณ ๊ฒฐ๊ตญ ์ ์ฒด ์ํ์ค์ ๋ํด ๊ฐ์ฅ ๋์ ํ๋ฅ ์ ๊ฐ์ง ๊ฐ์ค์ ์ ํํฉ๋๋ค. ์ด๋ ๋ฎ์ ํ๋ฅ ์ ์ด๊ธฐ ํ ํฐ์ผ๋ก ์์ํ๊ณ ๊ทธ๋ฆฌ๋ ๊ฒ์์์ ๋ฌด์๋์์ ๊ฐ๋ฅ์ฑ์ด ๋์ ์ํ์ค๋ฅผ ์๋ณํ๋ ์ด์ ์ด ์์ต๋๋ค.
์ด ๋์ฝ๋ฉ ์ ๋ต์ ํ์ฑํํ๋ ค๋ฉด num_beams (์ถ์ ํ ๊ฐ์ค ์๋ผ๊ณ ๋ ํจ)๋ฅผ 1๋ณด๋ค ํฌ๊ฒ ์ง์ ํ์ธ์.
>>> from transformers import AutoModelForCausalLM, AutoTokenizer
>>> prompt = "It is astonishing how one can"
>>> checkpoint = "openai-community/gpt2-medium"
>>> tokenizer = AutoTokenizer.from_pretrained(checkpoint)
>>> inputs = tokenizer(prompt, return_tensors="pt")
>>> model = AutoModelForCausalLM.from_pretrained(checkpoint)
>>> outputs = model.generate(**inputs, num_beams=5, max_new_tokens=50)
>>> tokenizer.batch_decode(outputs, skip_special_tokens=True)
['It is astonishing how one can have such a profound impact on the lives of so many people in such a short period of
time."\n\nHe added: "I am very proud of the work I have been able to do in the last few years.\n\n"I have']
๋น ํ์ ๋คํญ ์ํ๋ง(Beam-search multinomial sampling)beam-search-multinomial-sampling
์ด ๋์ฝ๋ฉ ์ ๋ต์ ์ด๋ฆ์์ ์ ์ ์๋ฏ์ด ๋น ํ์๊ณผ ๋คํญ ์ํ๋ง์ ๊ฒฐํฉํ ๊ฒ์
๋๋ค. ์ด ๋์ฝ๋ฉ ์ ๋ต์ ์ฌ์ฉํ๊ธฐ ์ํด์๋ num_beams๋ฅผ 1๋ณด๋ค ํฐ ๊ฐ์ผ๋ก ์ค์ ํ๊ณ , do_sample=True๋ก ์ค์ ํด์ผ ํฉ๋๋ค.
>>> from transformers import AutoTokenizer, AutoModelForSeq2SeqLM, set_seed
>>> set_seed(0) # ์ฌํ์ฑ์ ์ํด
>>> prompt = "translate English to German: The house is wonderful."
>>> checkpoint = "google-t5/t5-small"
>>> tokenizer = AutoTokenizer.from_pretrained(checkpoint)
>>> inputs = tokenizer(prompt, return_tensors="pt")
>>> model = AutoModelForSeq2SeqLM.from_pretrained(checkpoint)
>>> outputs = model.generate(**inputs, num_beams=5, do_sample=True)
>>> tokenizer.decode(outputs[0], skip_special_tokens=True)
'Das Haus ist wunderbar.'
์ถ๋ก ๋์ฝ๋ฉ(Speculative Decoding)speculative-decoding
์ถ๋ก ๋์ฝ๋ฉ(๋ณด์กฐ ๋์ฝ๋ฉ(assisted decoding)์ผ๋ก๋ ์๋ ค์ง)์ ๋์ผํ ํ ํฌ๋์ด์ ๋ฅผ ์ฌ์ฉํ๋ ํจ์ฌ ์์ ๋ณด์กฐ ๋ชจ๋ธ์ ํ์ฉํ์ฌ ๋ช ๊ฐ์ง ํ๋ณด ํ ํฐ์ ์์ฑํ๋ ์์ ๋ชจ๋ธ์ ๋์ฝ๋ฉ ์ ๋ต์ ์์ ํ ๊ฒ์
๋๋ค. ์ฃผ ๋ชจ๋ธ์ ๋จ์ผ ์ ๋ฐฉ ํต๊ณผ๋ก ํ๋ณด ํ ํฐ์ ๊ฒ์ฆํจ์ผ๋ก์จ ๋์ฝ๋ฉ ๊ณผ์ ์ ๊ฐ์ํํฉ๋๋ค. do_sample=True์ผ ๊ฒฝ์ฐ, ์ถ๋ก ๋์ฝ๋ฉ ๋
ผ๋ฌธ์ ์๊ฐ๋ ํ ํฐ ๊ฒ์ฆ๊ณผ ์ฌ์ํ๋ง ๋ฐฉ์์ด ์ฌ์ฉ๋ฉ๋๋ค.
ํ์ฌ, ํ์ ๊ฒ์(greedy search)๊ณผ ์ํ๋ง๋ง์ด ์ง์๋๋ ๋ณด์กฐ ๋์ฝ๋ฉ(assisted decoding) ๊ธฐ๋ฅ์ ํตํด, ๋ณด์กฐ ๋์ฝ๋ฉ์ ๋ฐฐ์น ์ ๋ ฅ์ ์ง์ํ์ง ์์ต๋๋ค. ๋ณด์กฐ ๋์ฝ๋ฉ์ ๋ํด ๋ ์๊ณ ์ถ๋ค๋ฉด, ์ด ๋ธ๋ก๊ทธ ํฌ์คํธ๋ฅผ ํ์ธํด ์ฃผ์ธ์.
๋ณด์กฐ ๋์ฝ๋ฉ์ ํ์ฑํํ๋ ค๋ฉด ๋ชจ๋ธ๊ณผ ํจ๊ป assistant_model ์ธ์๋ฅผ ์ค์ ํ์ธ์.
>>> from transformers import AutoModelForCausalLM, AutoTokenizer
>>> prompt = "Alice and Bob"
>>> checkpoint = "EleutherAI/pythia-1.4b-deduped"
>>> assistant_checkpoint = "EleutherAI/pythia-160m-deduped"
>>> tokenizer = AutoTokenizer.from_pretrained(checkpoint)
>>> inputs = tokenizer(prompt, return_tensors="pt")
>>> model = AutoModelForCausalLM.from_pretrained(checkpoint)
>>> assistant_model = AutoModelForCausalLM.from_pretrained(assistant_checkpoint)
>>> outputs = model.generate(**inputs, assistant_model=assistant_model)
>>> tokenizer.batch_decode(outputs, skip_special_tokens=True)
['Alice and Bob are sitting in a bar. Alice is drinking a beer and Bob is drinking a']
์ํ๋ง ๋ฐฉ๋ฒ๊ณผ ํจ๊ป ๋ณด์กฐ ๋์ฝ๋ฉ์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ๋คํญ ์ํ๋ง๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก temperature ์ธ์๋ฅผ ์ฌ์ฉํ์ฌ ๋ฌด์์์ฑ์ ์ ์ดํ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ๋ณด์กฐ ๋์ฝ๋ฉ์์๋ temperature๋ฅผ ๋ฎ์ถ๋ฉด ๋๊ธฐ ์๊ฐ์ ๊ฐ์ ํ๋ ๋ฐ ๋์์ด ๋ ์ ์์ต๋๋ค.
>>> from transformers import AutoModelForCausalLM, AutoTokenizer, set_seed
>>> set_seed(42) # ์ฌํ์ฑ์ ์ํด
>>> prompt = "Alice and Bob"
>>> checkpoint = "EleutherAI/pythia-1.4b-deduped"
>>> assistant_checkpoint = "EleutherAI/pythia-160m-deduped"
>>> tokenizer = AutoTokenizer.from_pretrained(checkpoint)
>>> inputs = tokenizer(prompt, return_tensors="pt")
>>> model = AutoModelForCausalLM.from_pretrained(checkpoint)
>>> assistant_model = AutoModelForCausalLM.from_pretrained(assistant_checkpoint)
>>> outputs = model.generate(**inputs, assistant_model=assistant_model, do_sample=True, temperature=0.5)
>>> tokenizer.batch_decode(outputs, skip_special_tokens=True)
['Alice and Bob, who were both in their early twenties, were both in the process of']