目录
一、trainer保存模型的问题
1.1、在trainer训练时,怎么控制模型保存的数量的同时,还可以保存最优的模型参数呢?
1.2、使用trainer训练ds ZeRO3或fsdp时,怎么保存模型为huggingface格式呢?
二、PreTrained Model中的from_pretrained常见的参数
三、Trainer初始化
四、Trainer 中的train()
五、Trainer 中的 _inner_training_loop 函数
六、Trainer 中的 _load_best_model函数
七、Trainer 中的_save_checkpoint函数
7.1、_save_checkpoint函数
7.2、保存优化器状态和学习率调度_save_optimizer_and_scheduler
八、Trainer 中的save_model函数
九、Trainer 中的_save函数
十、Trainer 中的compute_loss函数
十一、模型加载函数deepspeed_load_checkpoint与_load_from_checkpoint
11.1、deepspeed_load_checkpoint 加载deepspeed模型
11.2、_load_from_checkpoint 加载除了deepspeed情况的模型
十二、huggingface 常用组件
12.1 梯度检查点(PEFTmodel,PreTrainedModel)
12.2 transformer logger、set_seed()
12.3 模型结构、参数、设备等打印
12.4 tokenizer 初始化与使用
12.4.1 tokenizer 初始化的常见参数
12.4.2 tokenizer 参数及使用方法(encode,encode_plus,batch_encode_plus,decode...)
a) __call__() 方法
b) tokenizer. 常用函数与案例
c) _pad 方法(适合重写)
十三、TrainingArguments 与Seq2SeqTrainingArguments 常见的参数
13.1 Seq2SeqTrainingArguments 参数
13.2 Seq2SeqTrainingArguments 参数中GenerationConfig的常见参数(用于 generate 推理函数)
十四、Seq2SeqTrainer 类
本文主要简单介绍 huggingface 中常见函数的使用
torch版本:2.1
Transformers 版本:4.39-4.40.1、4.30
huggingface transformers 中文deepspeed、trainer等文档:
1.1、在trainer训练时,怎么控制模型保存的数量的同时,还可以保存最优的模型参数呢?
transformers:4.39
在使用Hugging Face的进行模型训练时,通过设置中的一些参数,你可以控制保存模型的数量,并确保最优模型不会被删除。主要涉及以下几个参数:
- :定义了模型保存的策略,可以是"no"(不保存模型),"epoch"(每个epoch结束时保存),或"steps"(每指定步数后保存)。
- :指定同时保存的模型检查点的最大数量。如果设置了这个参数,当保存新的检查点时,超出这个数量限制的最旧的检查点将被删除。
- :定义了评估的策略,与类似,可以是"no","epoch"或"steps"。
- :如果设置为,在训练结束时将加载评价指标最好的模型(需要同时设置)。
- :"eval_loss", 指定哪个评价指标用于评估最佳模型,一般用的是自定义的compute_metrics函数返回的字典的某个key。这个设置要求不为"no"。
- 需要注意的是,"eval_loss" 系统会自己算,无需自定义compute_metrics
- include_inputs_for_metrics=True True 表示调用compute_metrics会将输入input_ids 也进行导入,方便计算
- compute_metrics:自定义用于计算评估指标的函数
- 可以参考chatglm3的代码:https://github.com/THUDM/ChatGLM3/blob/main/finetune_demo/finetune_hf.py
这里有一个简单的参考示例:
1.2、使用trainer训练ds ZeRO3或fsdp时,怎么保存模型为huggingface格式呢?
transformers:4.39
新版trainer中存在函数
transformers:4.39
一些简单的加载案例
- attn_implementation 为新的参数, 使用类型有“spda”,“eager”(原生的attention),“flash attention”,需要注意的,attn_implementation = "eager",需要config 额外指定config._attn_implementation_internal = "eager" 才会生效,具体用法见下面例子:
- 为什么需要额外指定config._attn_implementation_internal = "eager",可以看源码PreTrainedModel中 ._autoset_attn_implementation 函数的实现过程:
model tokenizer 更多初始化设置详情见(章节2.2):
transformers:4.39
这部分代码主要涉及以下几个方面:
- 处理 SageMaker 模型并行时的混合精度设置
- 根据设备自动选择合适的半精度后端(FP16 或 BF16)
- 设置标签平滑
- 初始化训练器状态和控制器
- 统计浮点运算数的内部变量
- 设置标签名和判断模型是否可返回损失
- 执行初始化结束回调
- 内部变量用于自动批大小调整
- 停止并更新内存跟踪器的指标
- 检查是否支持 torch.compile
- 设置 FSDP XLA V2 相关配置
transformers:4.39
好的,我将罗列代码的执行步骤,并对重要部分进行解析。
- 检查 参数,如果为 False,则将其设置为 None。
- 启动内存跟踪器,用于跟踪训练过程中的内存使用情况。
- 获取训练参数 。
- 设置 标志为 True,表示当前处于训练模式。
- 如果 参数不为 None,则调用 方法,为模型添加 NeFTune 噪声。NeFTune 是一种用于训练鲁棒神经网络的技术,可以提高模型对噪声的鲁棒性。
- 如果指定了全精度(fp16或bf16)评估,且不进行训练,则将模型移动到指定的设备(如GPU)上。这种情况通常用于评估或推理。
- 检查 中是否包含 键,如果包含,则将其值赋给 ,并发出警告,提示 参数已被弃用。
- 如果 不为空,则抛出 异常,提示 函数收到了意外的关键字参数。
- 重要步骤: 调用 方法,传入 参数,用于超参数搜索的设置。超参数搜索是机器学习中一种常用的技术,用于自动搜索模型的最佳超参数组合。
- 设置训练批次大小为 。
- 检查是否需要重新初始化模型。如果 不为 None,则执行以下操作:
a. 根据 的值,启用完全确定性模式或设置随机种子。
b. 调用 方法,传入 参数,获取新的模型实例。
c. 将优化器和学习率调度器重置为 None。- 检查是否需要从检查点恢复训练。如果 是布尔值且为 True,则从 中获取最新的检查点路径。如果没有找到有效的检查点,则抛出 异常。
- 如果 不为 None,则执行以下操作:
a. 如果没有启用 SageMaker 模型并行、DeepSpeed 或 PyTorch FSDP,则调用 方法,从检查点加载模型、优化器和学习率调度器的状态。也就是说train函数默认的SageMaker 模型或 DeepSpeed模型。但是train函数中_inner_training_loop()函数提供了deepspeed断点续传的加载方法(详情见下文)。
b. 从检查点中加载 对象,如果其中包含 信息,则将训练批次大小设置为该值。- 如果模型已重新加载,则执行以下操作:
a. 如果需要将模型放置到设备上,则调用 方法,将模型移动到指定的设备上。
b. 将 设置为新的模型实例。- 重要步骤: 调用 函数,获取可执行的内部训练循环函数。该函数根据训练批次大小和是否自动查找批次大小的设置,返回合适的内部训练循环函数。
- 检查是否需要将模型推送到 Hugging Face Hub。
a. 如果需要推送,则在 块中禁用进度条,调用内部训练循环函数,并在 块中重新启用进度条。
b. 如果不需要推送,则直接调用内部训练循环函数。解析重要步骤:
- 方法用于超参数搜索的设置。在进行超参数搜索时,需要根据给定的 对象或超参数字典,对模型或训练过程进行相应的配置和初始化。这个步骤是机器学习中自动化超参数调优的关键。
- 函数用于查找可执行的训练批次大小。在训练过程中,批次大小的选择很重要,它需要综合考虑GPU内存大小、模型复杂度等因素。该函数会根据指定的训练批次大小和是否自动查找批次大小的设置,返回一个合适的内部训练循环函数,以确保训练过程可以顺利执行。
这两个重要步骤体现了 Hugging Face Transformers 库对于超参数调优和资源利用的优化,有助于提高模型训练的效率和性能。
transformers:4.39
transformers:4.39
- 这个函数的主要作用是加载模型的最佳检查点。它首先构建最佳检查点文件的路径,然后根据不同的配置(如是否启用DeepSpeed、FSDP等)选择不同的加载方式。
- 如果启用了DeepSpeed,则使用函数加载检查点;如果启用了FSDP,则使用函数加载检查点。如果存在模型权重文件或安全模型权重文件,则直接加载对应的权重。
- 在加载过程中,代码还考虑了一些特殊情况,如是否启用了SageMaker多进程、是否使用了PEFT和LoRA等。如果模型使用了PEFT和LoRA,则需要单独加载适配器权重。
- 此外,代码还支持加载分片检查点(sharded checkpoint),用于分布式训练场景。
- 最后,如果找不到最佳检查点文件,则会打印相应的警告信息。
总的来说,这个函数涉及了一些高级的深度学习训练技术,如DeepSpeed、FSDP、PEFT等,用于加速训练或减小模型大小。同时,它也考虑了不同的模型权重格式(PyTorch、SafeTensors等)和分布式训练场景,提供了相应的加载方式。
transformers:4.39
7.1、_save_checkpoint函数
- 这个方法的主要作用是保存模型的检查点,包括模型权重、优化器状态、调度器状态和RNG状态等。它首先构建检查点文件夹的路径,并根据指定的条件(如是否进行超参数搜索、是否保存浮点运算数等)执行相应的操作。
- 然后,该方法会创建一个暂存输出目录,用于临时保存检查点文件。它调用方法将模型权重保存到暂存目录中()。如果需要,还会保存优化器、调度器和RNG状态。
- 接下来,该方法会根据指定的指标和参数,确定是否需要更新最佳指标和最佳模型检查点。如果需要更新,则会更新相应的状态变量。
- 之后,该方法会保存Trainer的状态,并在需要时将检查点推送到Hugging Face Hub。
- 在所有进程完成写入操作后,主进程会将暂存输出目录重命名为最终输出目录。如果指定了参数,则每个节点都会执行此操作;否则,只有世界进程0会执行。同时,主进程还会根据需要删除一些较旧的检查点,以节省磁盘空间。
- 最后,该方法会等待所有进程完成相关操作。
总的来说,这个方法涉及了分布式训练、检查点保存和管理等多个方面的功能,确保了模型的检查点可以在各种环境和配置下正常保存和加载。
7.2、保存优化器状态和学习率调度_save_optimizer_and_scheduler
该函数的主要作用是保存模型训练过程中使用的优化器和学习率调度器的状态,以便在后续的训练或推理过程中继续使用。它支持多种不同的训练环境和加速技术,包括:
- PyTorch XLA: 用于加速模型训练和推理的技术,提供了分布式同步功能。
- SageMaker Model Parallelism (SMP): Amazon SageMaker提供的模型并行库,用于分布式训练。
- DeepSpeed: 用于加速大型模型训练的库,提供了优化器状态保存和检查点保存功能。
- FSDP (Fully Sharded Data Parallelism): PyTorch中用于数据并行的技术,可以减少内存占用。
- PEFT (Parameter-Efficient Transfer Learning): 一种高效fine-tuning技术,可以选择排除冻结的参数。
根据当前的训练环境和设置,该函数会使用相应的方式来保存优化器和学习率调度器的状态。例如,如果启用了DeepSpeed,它会使用DeepSpeed提供的函数来保存检查点;如果启用了FSDP,它会使用FSDP提供的和函数来保存模型和优化器。
在保存过程中,该函数还会处理一些特殊情况,如捕获PyTorch警告、排除冻结参数等。
该函数的主要目的是确保在训练过程中,优化器和学习率调度器的状态能够被正确地保存下来,以便在后续的训练或推理过程中继续使用,从而提高模型训练的可靠性和灵活性。
transformers:4.39
该代码定义了一个方法,用于将训练好的模型保存到磁盘。具体来说:
- 该方法首先检查输出目录,如果没有指定则使用作为输出目录。
- 接下来,根据使用的硬件和框架,分别采取不同的保存策略:
- 如果使用TPU设备,调用方法保存模型。
- 如果启用了SageMaker多进程训练,需要在所有进程上获取模型的,然后调用保存。
- 如果启用了FSDP,需要使用获取模型状态字典,然后调用保存。
- 如果启用了DeepSpeed,同样需要使用获取模型状态字典,然后调用保存(新版的trainer ZeRO3的参数也会通过)。如果出现异常,则保存完整的检查点,并提示使用脚本恢复权重。
- 如果没有启用上述特殊功能,直接调用保存模型。
- 最后,如果为True,且该方法不是由内部调用,则将模型推送到Hugging Face Hub。
新版本的transformers
transformers:4.39
transformers:4.39
该代码定义了一个方法,用于计算模型训练过程中的损失值。具体来说:
- 首先检查是否设置了标签平滑()以及输入中是否包含"labels"。如果同时满足,则从输入中弹出"labels"。
- 使用输入调用模型,获取模型输出()。
- 如果,则保存模型输出中对应索引处的值,这可能与模型的过去状态()有关,但需要后续优化该部分代码。
- 如果输入中包含"labels":
- 获取模型的名称,判断是否为PEFT模型。
- 如果模型属于因果语言模型类型,则在计算损失时应用标签平滑并进行标签移位()。
- 否则直接应用标签平滑。
- 如果输入中不包含"labels":
- 检查模型输出是否为字典且包含"loss"键。如果不包含,则抛出异常。
- 从模型输出中获取损失值,因为有些模型可能返回元组而不是对象。
- 如果设置了为,则同时返回损失值和模型输出,否则只返回损失值。
下面是一个自定义compute_loss函数的例子做参考, 可以继承trainer后重写compute_loss函数里使用
transformers:4.39
11.1、deepspeed_load_checkpoint 加载deepspeed模型
该函数的主要作用是从指定的检查点路径加载DeepSpeed引擎的模型、优化器和学习率调度器的状态。它首先检查给定的检查点路径是否包含DeepSpeed检查点的目录结构(以"global_step"开头的目录)。
11.2、_load_from_checkpoint 加载除了deepspeed情况的模型
该函数的主要作用是从指定的检查点路径加载模型的权重和配置,支持多种不同的检查点格式,包括:
- 普通格式: 将模型权重、配置等信息存储在多个文件中。
- FSDP (Fully Sharded Data Parallelism) 格式: 用于数据并行训练,将模型权重分散到多个文件夹或文件中,以节省内存。
- PEFT (Parameter-Efficient Transfer Learning) 格式: 用于高效fine-tuning,只需加载适配器权重。
- 分片 (Sharded) 格式: 将模型权重分割成多个分片,分别存储在不同文件中。
12.1 梯度检查点(PEFTmodel,PreTrainedModel)
查看是否开启了梯度检查点
开启梯度检查点
12.2 transformer logger、set_seed()
transformer logger with seed
第一种:
第二种
12.3 模型结构、参数、设备等打印
12.4 tokenizer 初始化与使用
12.4.1 tokenizer 初始化的常见参数
更多详情见: 下文中章节2.2
12.4.2 tokenizer 参数及使用方法(encode,encode_plus,batch_encode_plus,decode...)
a) __call__() 方法
b) tokenizer. 常用函数与案例
选择搭配 add_special_tokens=False/True 或 skip_special_tokens=False/True 使用
- - 这是tokenizer的主要功能,用于对输入文本进行标记化,生成token id序列。上面提到的参数如、、等都可以在这里设置
- - 与类似,也用于对输入文本进行标记化,但返回值略有不同。
- 功能: 对输入文本进行编码,返回token id序列
- 返回值: , 仅返回的token id序列, 不包含
- - 在的基础上增加了一些功能,如生成注意力掩码和标记类型id。
- 功能: 在的基础上,增加了一些用于构建模型输入的特性
- 返回值: , 包含以下字段:
- : token id序列
- : 注意力掩码,用于区分实际token和padding token
- : 标记类型id,用于区分句子边界(仅BERT等模型需要)
- - 对一批文本进行标记化,返回已padding和截断的编码序列。
- 功能: 对一批文本进行编码,并自动执行padding和截断操作
- 返回值: , 与类似,但对应一批输入
- - 将token id序列解码为原始文本。
- 功能: 将token id序列解码为原始文本
- 返回值: , 解码后的文本字符串
- tokenize(text, ...)
- 功能: 对输入文本进行tokenize,将其分割成token序列
- 返回值: , 表示token序列,每个元素是一个字符串token
总的来说:
- encode只返回token id序列,适合简单的标记化场景
- encode_plus和batch_encode_plus返回模型输入所需的各种编码,用于序列分类、序列到序列等任务
- decode用于将模型输出(token id)解码为可读文本
- tokenizer是最通用和灵活的编码函数,可满足大多数需求
c) _pad 方法(适合重写)
Hugging Face tokenizer中的函数用于对一批编码后的序列进行padding(填充)操作,使它们具有相同的长度,便于批量输入模型进行处理。
具体用法可以看:Chatglm3 代码 中 class FinetuningConfig(object) 类
https://github.com/THUDM/ChatGLM3/blob/main/finetune_demo/finetune_hf.py
13.1 Seq2SeqTrainingArguments 参数
Transformers 版本:4.39
13.2 Seq2SeqTrainingArguments 参数中GenerationConfig的常见参数(用于 generate 推理函数)
覆盖权限:.generation_config > model.generation_config > default GenerationConfig.
这段代码主要定义了 类的以下几个核心方法:
- 方法是执行预测的核心。如果 被设置为 True,则使用模型的 方法进行生成式预测;否则直接调用模型的 方法进行前向计算。该方法返回预测损失、生成的 token 和标签(如果存在)。
- 方法用于在评估数据集上进行评估。它会根据 和 等参数设置生成配置,然后调用 进行预测并计算相关指标。
- 方法与 方法类似,但是在测试数据集上进行预测,并返回预测结果和可能的指标。
- 是一个辅助方法,用于将张量填充到指定的最大长度。它首先尝试从标记器(tokenizer)或模型配置中获取填充 token ID,如果两者都没有指定,则抛出 ValueError。
待更新..............