当前位置: 首页 > news >正文

7.3 Organizing data into training batches

Chapter 7-Fine-tuning to follow instructions

7.3 Organizing data into training batches

  • 下一步是构建训练批次

    定义一种方法,以确保我们的模型在微调过程中接收格式化的训练数据。如下图所示,我们通过几个步骤处理此数据集批处理。

  • 首先,我们实现一个“InstructionDataset”类,该类对数据集中的所有输入进行预标记,类似于第6章中的“SpamDataset”

    import torch
    from torch.utils.data import Datasetclass InstructionDataset(Dataset):def __init__(self, data, tokenizer):self.data = data# Pre-tokenize textsself.encoded_texts = []for entry in data:instruction_plus_input = format_input(entry)response_text = f"\n\n### Response:\n{entry['output']}"full_text = instruction_plus_input + response_textself.encoded_texts.append(tokenizer.encode(full_text))def __getitem__(self, index):return self.encoded_texts[index]def __len__(self):return len(self.data)
    

    与第 6 章类似,我们希望批量收集多个训练示例以加速训练;这需要将所有输入填充到相似的长度,使用 ‘<|endftext|>’ 标记作为填充标记。

    import tiktoken
    tokenizer = tiktoken.get_encoding("gpt2")print(tokenizer.encode("<|endoftext|>", allowed_special={"<|endoftext|>"}))"""输出"""
    [50256]
    
  • 我们通过开发一个可以传递给数据加载器的自定义排序函数来采用更复杂的方法。这个自定义排序函数将每个批次中的训练示例填充到相同的长度,同时允许不同批次具有不同的长度。这种方法 minimizesunnecessary 填充,只扩展序列以匹配每个批次中最长的一个,而不是整个数据集,如下图所示

    def custom_collate_draft_1(batch,pad_token_id=50256,device="cpu"
    ):# Find the longest sequence in the batch# and increase the max length by +1, which will add one extra# padding token belowbatch_max_length = max(len(item)+1 for item in batch)# Pad and prepare inputsinputs_lst = []for item in batch:new_item = item.copy()# Add an <|endoftext|> tokennew_item += [pad_token_id]# Pad sequences to batch_max_lengthpadded = (new_item + [pad_token_id] *(batch_max_length - len(new_item)))# Via padded[:-1], we remove the extra padded token# that has been added via the +1 setting in batch_max_length# (the extra padding token will be relevant in later codes)inputs = torch.tensor(padded[:-1])inputs_lst.append(inputs)# Convert list of inputs to tensor and transfer to target deviceinputs_tensor = torch.stack(inputs_lst).to(device)return inputs_tensor
    

    我们实现的custom_collate_draft_1被设计为集成到PyTorch DataLoader中,但它也可以作为一个独立的工具。在这里,我们独立地使用它来测试和验证它是否按预期运行。让我们在三个不同的输入上尝试一下,我们希望将它们组装成一个批处理,其中每个示例都被填充到相同的长度

    inputs_1 = [0, 1, 2, 3, 4]
    inputs_2 = [5, 6]
    inputs_3 = [7, 8, 9]batch = (inputs_1,inputs_2,inputs_3
    )print(custom_collate_draft_1(batch))"""输出"""
    tensor([[    0,     1,     2,     3,     4],[    5,     6, 50256, 50256, 50256],[    7,     8,     9, 50256, 50256]])
    

  • 到目前为止我们只将输入返回给 LLM;但是,对于 LLM 训练,我们还需要目标值,与预先训练 LLM 类似,目标是向右移动 1 个位置的输入,因此 LLM 学会预测下一个令牌。

    以下更新的排序函数从输入token ID生成目标tokenID:

    def custom_collate_draft_2(batch,pad_token_id=50256,device="cpu"
    ):# Find the longest sequence in the batchbatch_max_length = max(len(item)+1 for item in batch)# Pad and prepare inputsinputs_lst, targets_lst = [], []for item in batch:new_item = item.copy()# Add an <|endoftext|> tokennew_item += [pad_token_id]# Pad sequences to max_lengthpadded = (new_item + [pad_token_id] *(batch_max_length - len(new_item)))inputs = torch.tensor(padded[:-1])  # Truncate the last token for inputstargets = torch.tensor(padded[1:])  # Shift +1 to the right for targetsinputs_lst.append(inputs)targets_lst.append(targets)# Convert list of inputs to tensor and transfer to target deviceinputs_tensor = torch.stack(inputs_lst).to(device)targets_tensor = torch.stack(targets_lst).to(device)return inputs_tensor, targets_tensor
    
    inputs, targets = custom_collate_draft_2(batch)
    print('inputs:\n', inputs)
    print('targets:\n', targets)"""输出"""
    inputs:tensor([[    0,     1,     2,     3,     4],[    5,     6, 50256, 50256, 50256],[    7,     8,     9, 50256, 50256]])targets:tensor([[    1,     2,     3,     4, 50256],[    6, 50256, 50256, 50256, 50256],[    8,     9, 50256, 50256, 50256]])
    
  • 接下来,我们引入一个ignore_index值,用一个新值替换所有填充tokenID;这个ignore_index的目的是我们可以忽略损失函数中的填充值(稍后会详细介绍)

    具体来说,这意味着我们将与’50256’对应的令牌ID替换为’-100’,如下所示

    此外,我们还引入了“允许的最大长度”(allowed_max_length)这一参数,以便在需要时对样本长度加以限制。如果您打算使用长度超过 GPT-2 模型所支持的 1024 个词元上下文大小的自有数据集,这个参数就会派上用场 。

    inputs, targets = custom_collate_fn(batch)
    print('inputs:\n', inputs)
    print('targets:\n', targets)"""输出"""
    inputs:tensor([[    0,     1,     2,     3,     4],[    5,     6, 50256, 50256, 50256],[    7,     8,     9, 50256, 50256]])targets:tensor([[    1,     2,     3,     4, 50256],[    6, 50256,  -100,  -100,  -100],[    8,     9, 50256,  -100,  -100]])
    
  • 修改后的排序函数按预期工作,通过插入令牌ID-100来更改目标列表。这种调整背后的逻辑是什么?让我们探索一下这种修改的潜在目的。

    为了说明的目的,让我们假设我们有一个小分类任务,有 2 个类标签,0 和 1,类似于第 6 章、如果我们有以下 logits 值(模型最后一层的输出),我们计算以下损失

    logits_1 = torch.tensor([[-1.0, 1.0],  # 1st training example[-0.5, 1.5]]  # 2nd training example
    )
    targets_1 = torch.tensor([0, 1])loss_1 = torch.nn.functional.cross_entropy(logits_1, targets_1)
    print(loss_1)"""输出"""
    tensor(1.1269)
    

    现在,如预期的那样,再添加一个训练示例将影响损失

    logits_2 = torch.tensor([[-1.0, 1.0],[-0.5, 1.5],[-0.5, 1.5]]  # New 3rd training example
    )
    targets_2 = torch.tensor([0, 1, 1])loss_2 = torch.nn.functional.cross_entropy(logits_2, targets_2)
    print(loss_2)"""输出"""
    tensor(0.7936)
    

    让我们看看如果我们将其中一个示例的类标签替换为-100会发生什么

    targets_3 = torch.tensor([0, 1, -100])loss_3 = torch.nn.functional.cross_entropy(logits_2, targets_3)
    print(loss_3)
    print("loss_1 == loss_3:", loss_1 == loss_3)"""输出"""
    tensor(1.1269)
    loss_1 == loss_3: tensor(True)
    

    我们可以看到,3个训练示例的结果损失与从2个训练示例计算的损失相同,这表明交叉熵损失函数忽略了带有 -100 标签的训练示例,默认情况下PyTorch有 cross_entropy(..., ignore_index=-100) 设置来忽略与标签 -100 对应的示例,利用 -100 ignore_index 能忽略用于将训练示例填充到等长的批次中额外的文本结束(填充)令牌,但我们不想忽略文本结束(填充)令牌(50256)的第一个实例,因其能在响应完成时向LLM发出信号 (说白了就是标注每句话的最后一个字符)。

    在实践中,掩盖与指令对应的目标token ID也很常见,如下图所示


7.4-Creating data loaders for an instruction dataset

相关文章:

  • 20250530-C#知识:String与StringBuilder
  • 算力租赁革命:弹性模式如何重构数字时代的创新门槛​
  • shadcn/ui
  • Python+requests+pytest接口自动化测试框架的搭建(全)
  • C# MySQL 实现多层级联数据迁移
  • 数据结构:导论
  • RK3399 Android7.1增加应用安装白名单机制
  • python进程hung住如何找到问题所在
  • 内存池学习(一)
  • 腾讯云开发者社区文章内容提取免费API接口教程
  • Hive的存储格式如何优化?
  • 计算机视觉入门:OpenCV与YOLO目标检测
  • CSS3前端入门(第三天)2D转换 transform
  • CAD多边形密堆积2D插件
  • 强化学习笔记总结(结合论文)
  • 设备远程调试新利器:御控网关开启PLC高效运维新时代
  • 书送希望 智启未来 —— 赛力斯超级工厂携手渝北和合家园小学校开展公益赠书活动
  • Python训练day34
  • 边缘计算网关在管网压力远程调控中的通信协议配置
  • 未来技术展望
  • h5可以做网站吗/百度灰色关键词代发
  • 黄州做网站的/seovip培训
  • 网站建设简单点的/东莞做网站哪家公司好
  • 怎样在在农行网站上做风险评估/百度2020新版下载
  • 佛山做网站建设公司/seo公司排名
  • 在家做网站或ps挣钱接活/百度搜索风云排行榜