Ji Yaodian

欢迎来到记要点小站

TypeError("'ObjectId' object is not iterable") 解决方法

‘ObjectId’ object is not iterable 使用fastapi,当返回结果里面包含mongodb的id,也就是ObjectId类型的时候,就会报错: TypeError("‘ObjectId’ object is not iterable")。 直接google搜索下,可以得到几种方法: 先使用str()方法将ObjectId转换成字符串 使用bson内置的json_util.dumps()方法将ObjectId转换成字符串 删除ObjectId字段 定义一个JSONEncoder类,将ObjectId转换成字符串 1 2 3 4 5 6 7 8 9 10 import json from bson import ObjectId class JSONEncoder(json.JSONEncoder): def default(self, o): if isinstance(o, ObjectId): return str(o) return json.JSONEncoder.default(self, o) JSONEncoder().encode(analytics) json.dumps(my_obj, default=str) 如果是老版本的fastapi 1 2 3 import pydantic from bson import ObjectId pydantic.json.ENCODERS_BY_TYPE[ObjectId]=str 看起来,第6种方法是比较优雅的,但是,对于没有使用pydantic的返回结果,就不适用了。而且,新版本的pydantic也不是这样的使用方法了。 其实,不管什么类型,只要是json不支持的,都会报错,比如datetime类型也会报错。 但是为什么fastapi返回datetime类型的时候不会报错呢?因为fastapi内部已经做了处理,将datetime类型转换成了字符串类型。 通过报错信息。 1 2 3 4 5 6 7 8 9 │ /xxxx/site-packages/fastapi/encoders....

六月 5, 2024 · 2 分钟 · jyd

看论文:Self-Rewarding Language Models

概述 语言模型通常的训练方法是先收集一大堆人类的反馈,然后基于这些反馈教模型“说话”。但这种依赖外部信号的机制缺点也很明显,模型的能力受限于人类反馈的数据指令。 所以论文提出,我们得让模型自己动手试错、自我完善。具体想法是让模型给自己当老师,让它边生成回复边给自己打分。这样模型就可以根据自己的评价,找出好和不好的回答,进而再基于这些评分来改进模型。 论文里面迭代模型的过程是这样的: Model0: 没有微调的预训练模型 Model1: 基于人类反馈数据的微调模型,使用SFT的方法微调 Model2: 使用Model1生成的回复,然后使用Model1对回复进行打分,选出好的和不好的结果,用这些结果使用DPO的方法对Model2进行微调 Model3: 使用Model2生成的回复,然后使用Model2对回复进行打分,选出好的和不好的结果,用这些结果使用DPO的方法对Model3进行微调 这样,就可以不断的迭代下去,直到模型的能力达到预期的水平。 模型迭代细节 Model0:原始预训练模型 Model1:基于人类反馈数据的微调模型,使用SFT的方法微调 Model2:基于Model1自评分微调 生成新的指令,具体的方法参考Aligning Language Models with Self-Generated Instructions和Tuning Language Models with (Almost) No Human Labor 基于生成的指令,让Model1给每个输入生成N个回复 使用Model1对每个回复进行打分,返回的分数是0-5分。使用如下的Prompt: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Review the user’s question and the corresponding response using the additive 5-point scoring system described below. Points are accumulated based on the satisfaction of each criterion: - Add 1 point if the response is relevant and provides some information related to the user’s inquiry, even if it is incomplete or contains some irrelevant content....

一月 30, 2024 · 2 分钟 · jyd

多卡训练:DP vs DDP

今天聊聊数据并行(DP)和分布式数据并行(DDP)这两个常用的方法。 如果你有2个GPU,那你就可以简单的通过DP和DDP实现更快的训练速度。 Pytorch已经内置这两种方法,官方建议使用DDP。 数据并行(DP) 数据并行是一种简单且常见的方法,它让我们可以在多个GPU上同时进行模型训练。 这个方法的核心思想就是:把一个大批量的数据分成几个小批量,然后让每个GPU处理一个小批量数据。处理完成后,我们把各个GPU计算出来的梯度汇总,然后更新模型权重。 优点: 实现简单:数据并行很容易理解和实现。 加速训练:因为数据是在多个GPU上同时处理的,所以训练速度会比单个GPU快很多。 缺点: 扩展性有限:当GPU数量增加时,通信和同步开销也会增加,这会限制训练速度的提升。 只适用于较小模型:如果模型太大,无法放入单个GPU的内存中,那么数据并行就不适用了。 分布式数据并行(DDP) 分布式数据并行是对数据并行的一种改进。在这个方法中,我们不仅把数据切分成小批量,而且还把模型参数在各个GPU上分片存储。这样一来,每个GPU都处理一部分数据,同时也只更新模型的一部分参数。 这种方法的关键在于,我们需要在所有GPU之间同步梯度和模型参数。 优点: 更好的扩展性:DDP的通信和同步开销相对较小,因此在大量GPU上训练时,它能提供更好的扩展性。 支持更大模型:由于模型参数在各个GPU上分片存储,DDP可以支持无法放入单个GPU内存的大型模型。 缺点: 实现更复杂:与数据并行相比,DDP需要更多的设置和细节处理。 依赖高速网络:DDP需要在各个GPU之间同步梯度和模型参数,这要求有高速的网络连接。 DP与DDP的区别 通常,DDP比DP更快,但并非总是如此,比如显卡之间不支持 nv-link 的时候。 DP基于Python线程,而DDP基于多进程,因此DDP没有诸如全局解释器锁(GIL)之类的Python线程限制。 在GPU卡之间的连接速度较慢时,DDP的实际运行速度可能会更慢。 以下是两种模式之间的主要差异: DDP: 在开始时,主进程将模型从GPU 0复制到其它GPU 然后,对于每个批次: 每个GPU直接计算自己的小批量数据 在反向传播过程中,一旦本地梯度计算好了,它们就会在所有进程之间取平均值 DP: 对于每个批次: GPU 0读取数据,然后将一个小批量发送给每个GPU 从GPU 0将最新的模型复制到每个GPU 执行推理并将结果从每个GPU发送到GPU 0,计算loss 将loss从GPU 0分散到所有GPU,进行反向传播 将梯度从每个GPU发送到GPU 0并取平均值 因此,DDP每个批次只需要进行梯度发送,而DP需要进行5次不同的数据交换。 DP通过Python线程在进程内复制数据,而DDP通过torch.distributed复制数据。 在DP下,GPU 0的工作量远大于其他GPU,导致GPU的利用率降低。 DDP可以在多台机器上使用,但DP则不行。虽然DP和DDP之间还有其他差异,但它们与本讨论无关。 结论 数据并行(DP)和分布式数据并行(DDP)是在深度学习中实现多GPU训练的两种有效方法。通常情况下,DDP比DP更快,但具体差异取决于GPU之间需要同步的数据量。当需要同步的数据越多时,慢速连接可能导致整体运行速度变慢。 在选择使用哪种方法时,要考虑你的硬件条件和实际需求。希望这篇文章能帮助你更好地了解DP和DDP的概念、优缺点以及区别,从而为你的深度学习项目选择合适的多GPU训练策略。 参考 Efficient Training on Multiple GPUs (huggingface.co)

五月 20, 2023 · 1 分钟 · jyd

多卡训练:如何选择合适的并行策略

前言 当我们训练深度学习模型时,有时会遇到问题:单个GPU速度太慢,或者模型权重放不进单个GPU里。这时候,我们就需要考虑使用多个GPU来进行训练。 现在,有很多方法可以实现并行,比如数据、张量和流水线并行。 不过,并没有一个通用的解决方案能适应所有情况。 注意:单GPU的许多策略(比如混合精度训练或梯度累积)都是通用的,也适用于大部分模型训练。 主要概念 下面是一些主要概念的简要概述: 数据并行(DataParallel):就是把模型参数放到所有卡上,每张卡都有完整的模型参数,每张卡都会处理一部分数据。处理过程是同时进行的,然后在每次训练步骤结束时同步所有结果。 张量并行(TensorParallel):这个方法是把每个张量切成好几块,所以不是把整个张量放在一个GPU上,而是让张量的每个部分都放在不同的GPU上。在处理过程中,每个部分都在不同的GPU上同时进行处理,然后在步骤结束时同步结果。这就是所谓的水平并行,因为切分是在水平层面进行的。 流水线并行(PipelineParallel):这个方法是把模型垂直(按层级)切分到不同的GPU上,这样单个GPU上只放置模型的一部分或几个层。每个GPU同时处理流水线的不同阶段,一次处理一小部分批次数据。 零冗余优化器(ZeRO):这个方法也对张量进行分片,但与TP不同的是,在进行正向或反向计算时,整个张量会在适当时候重建。因此,模型不需要进行修改。它还支持各种offloading技术以弥补不足的GPU内存。 分片数据并行(Sharded DDP): 是ZeRO的另一个名称。 如何选择合适的并行策略 ​ 在训练大模型的时候,为了能够训练,或者提高训练速度,我们可以采用各种并行策略。 ​ 以下将针对单GPU、单节点多GPU以及多节点多GPU等不同场景,介绍如何选择合适的并行策略。 一、单GPU 模型可以完全加载到单个GPU中 在这种情况下,可以正常使用单GPU进行训练。 模型无法完全加载到单个GPU中 ZeRO + Offload CPU方案,并可选使用NVMe作为辅助存储。 如果模型中最大的层无法放入单个GPU中,可以考虑使用Memory Centric Tiling, MCT技术。MCT可以通过自动分割并顺序执行大型层来运行任意大小的层。这种方式目前很少用,需要手动覆盖torch.nn.Linear来实现。 二、单节点多GPU场景 模型可以完全加载到单个GPU中 可以使用DDP(Distributed Data Parallel,分布式数据并行)策略 ZeRO(Zero Redundancy Optimizer,零冗余优化器)策略也可以作为一种选择。 模型无法完全加载到单个GPU中 PP(Pipeline Parallelism) ZeRO TP(Tensor Parallelism) 当节点内部,卡与卡之间有NVLINK或NVSwitch连接时,这三种策略的性能基本相当; 若没有,PP通常比TP或ZeRO更快。不同程度的TP对性能的影响可能不同,所以最好通过实验来确定在特定设备上的最佳策略。 最大层无法放入单个GPU中 ZeRO 如果无法使用ZeRO策略,则只能选择TP。 三、多节点多GPU场景 具有快速节点间连接时 选择使用ZeRO策略,因为它几乎不需要对模型进行修改。 还可以考虑使用PP+TP+DP(Data Parallel,数据并行)组合策略,该策略减少了通信量,但需要对模型进行大量修改。 节点间连接速度较慢,且GPU内存仍然不足时 可以尝试使用DP+PP+TP+ZeRO-1组合策略 参考文献 Efficient Training on Multiple GPUs (huggingface.co)

四月 22, 2023 · 1 分钟 · jyd