import mathimport randomfrom collections.abc import Iterable, Iteratorimport dnnlpyimport dnnlpy.models.gpt as gptimport dnnlpy.nn.functional as dFimport dnnlpy.optim as doptimport IPython.display as ipyimport tokenizers as tkimport tokenizers.decoders as tkdimport tokenizers.implementations as tkiimport tokenizers.models as tkmimport tokenizers.normalizers as tknimport tokenizers.pre_tokenizers as tkptimport tokenizers.processors as tkpimport torchimport torch.nn as nnfrom datasets import load_datasetfrom torch import Tensorprint('PyTorch version:', torch.__version__)
NUM_TRAIN_STORIES =10000NUM_VALID_STORIES =1000train_ds = load_dataset('roneneldan/TinyStories', split='train', streaming=True,)valid_ds = load_dataset('roneneldan/TinyStories', split='validation', streaming=True,)ipy.clear_output()train_texts = [ds['text'] for ds in train_ds.take(NUM_TRAIN_STORIES)]valid_texts = [ds['text'] for ds in valid_ds.take(NUM_VALID_STORIES)]idx = random.randrange(len(train_texts))print('Num training stories:', len(train_texts))print('Num validation stories:', len(valid_texts))print('\nExample story:')print(train_texts[idx][:500])
Num training stories: 10000
Num validation stories: 1000
Example story:
Once upon a time there was a rabbit and a mouse who were good friends. The rabbit was always very careful and thought before she moved. The mouse, who was very foolish, was always in a hurry and didn't think before he moved.
One day, the rabbit and mouse were walking along and saw a cactus. The mouse saw the cactus and was very excited. He quickly moved and touched it. But, to his surprise, he felt a sharp prick! He screamed in pain.
The rabbit quickly ran to the mouse. The rabbit said, "You'r
这里的 training set 和 validation set 是基于原数据集的 split,而不是在 token stream 上随机采样。这样可以更清晰地观察模型是否在记忆训练语料,还是学会了某种更一般的语言规律。
18.5.2 Hugging Face Tokenizers 库简介
在实际进行模型训练之前,我们需要先把文本转换成 token ids。Hugging Face 的 Tokenizers (Moi and Patry 2023) 库提供了高性能的 tokenizer 实现,支持多种预训练 tokenizer 结构,也允许我们从头训练一个适合当前语料的小型 tokenizer。
text = train_texts[idx][:150]encoding = tokenizer.encode(text)print('Text:')print(text)print('\nToken ids:')print(encoding.ids[:40])print('\nTokens:')print(encoding.tokens[:40])print('\nDecoded:')print(tokenizer.decode(encoding.ids))
Text:
Once upon a time there was a rabbit and a mouse who were good friends. The rabbit was always very careful and thought before she moved. The mouse, who
Token ids:
[423, 438, 260, 390, 393, 281, 260, 1036, 266, 260, 1245, 595, 432, 610, 478, 15, 302, 1036, 281, 652, 392, 875, 266, 658, 970, 334, 1949, 15, 302, 1245, 13, 595]
Tokens:
['Once', 'Ġupon', 'Ġa', 'Ġtime', 'Ġthere', 'Ġwas', 'Ġa', 'Ġrabbit', 'Ġand', 'Ġa', 'Ġmouse', 'Ġwho', 'Ġwere', 'Ġgood', 'Ġfriends', '.', 'ĠThe', 'Ġrabbit', 'Ġwas', 'Ġalways', 'Ġvery', 'Ġcareful', 'Ġand', 'Ġthought', 'Ġbefore', 'Ġshe', 'Ġmoved', '.', 'ĠThe', 'Ġmouse', ',', 'Ġwho']
Decoded:
Once upon a time there was a rabbit and a mouse who were good friends. The rabbit was always very careful and thought before she moved. The mouse, who
model = gpt.MiniGPT( vocab_size=tokenizer.get_vocab_size(), block_size=128, embed_dim=256, num_layers=4, num_heads=4, dropout=0.1,).to(device)num_parameters =sum(p.numel() for p in model.parameters())print('Num parameters:', f'{num_parameters:,}')
下面先实现最基本的 temperature sampling。Top-k 和 top-p 会在下一节单独解释。
@torch.inference_mode()def generate( model: gpt.MiniGPT, input_ids: Tensor, max_new_tokens: int, temperature: float=1.0, eos_id: int|None=None,) -> Tensor: model.eval()for _ inrange(max_new_tokens): model_input = input_ids[:, -model.block_size :] logits = model(model_input) next_token_logits = logits[:, -1, :] / temperature probs = dF.softmax(next_token_logits, dim=-1) next_token = probs.multinomial(num_samples=1) input_ids = torch.concat([input_ids, next_token], dim=1)if eos_id isnotNoneand torch.all(next_token == eos_id):breakreturn input_idsprompt ='Once upon a time, there was a little girl'prompt_ids = tokenizer.encode(prompt).idsinput_ids = torch.tensor([prompt_ids], dtype=torch.long, device=device)output_ids = generate( model, input_ids, max_new_tokens=150, temperature=0.8, eos_id=eos_id,)generated_text = tokenizer.decode(output_ids[0].tolist())print(generated_text)
Once upon a time, there was a little girl named Lily. She had a favorite toy. One day, Lily's friend, Lily. Lily was playing with her toy. She gave her a big bowl of butter. Lily was happy because she wanted to help her.
Her mom gave her a big hug. "Oh, Lily. You did you find the mumried, Lily and be careful." Lily wanted to rub the store to get her. She said, "Lily, we can use Lily, but you can't wait to clean the store all rain and her mommy."
Lily went back to the park and saw the broken clock. She looked at them and some children playing with her. She was so excited they decided to help her mommy. But she noticed that her