当前位置:   article > 正文

Huggingface trainer、model.from_pretrained、tokenizer()简单介绍(笔记)_transformes trainer 如何保存优化器的状态

transformes trainer 如何保存优化器的状态

目录

 一、trainer保存模型的问题

        1.1、在trainer训练时,怎么控制模型保存的数量的同时,还可以保存最优的模型参数呢?

        1.2、使用trainer训练ds ZeRO3或fsdp时,怎么保存模型为huggingface格式呢?

二、PreTrained Model中的from_pretrained常见的参数

三、Traine​​​​​​​r初始化

四、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等文档:​​​​​​​​​​​​​​

https://huggingface.co/docs/transformers/v4.39.3/zh/main_classes/deepspeedicon-default.png?t=N7T8https://huggingface.co/docs/transformers/v4.39.3/zh/main_classes/deepspeed

 一、trainer保存模型的问题

        1.1、在trainer训练时,怎么控制模型保存的数量的同时,还可以保存最优的模型参数呢?

transformers:4.39

在使用Hugging Face的Trainer进行模型训练时,通过设置TrainingArguments中的一些参数,你可以控制保存模型的数量,并确保最优模型不会被删除。主要涉及以下几个参数:

  • save_strategy定义了模型保存的策略,可以是"no"(不保存模型),"epoch"(每个epoch结束时保存),或"steps"(每指定步数后保存)。
  • save_total_limit指定同时保存的模型检查点的最大数量。如果设置了这个参数,当保存新的检查点时,超出这个数量限制的最旧的检查点将被删除。
  • evaluation_strategy定义了评估的策略,与save_strategy类似,可以是"no","epoch"或"steps"。
  • load_best_model_at_end如果设置为True,在训练结束时将加载评价指标最好的模型(需要同时设置evaluation_strategy)。
  • metric_for_best_model:"eval_loss",  指定哪个评价指标用于评估最佳模型,一般用的是自定义的compute_metrics函数返回的字典的某个key。这个设置要求​​​​​​​evaluation_strategy不为"no"。
    • 需要注意的是,"eval_loss" 系统会自己算,无需自定义compute_metrics

  • include_inputs_for_metrics=True    True 表示调用compute_metrics会将输入input_ids 也进行导入,方便计算​​​​​​​​​​​​​​
  • compute_metrics:自定义用于计算评估指标的函数

这里有一个简单的参考示例:

  1. import os
  2. from transformers import TrainingArguments, Trainer
  3. # 设置保存目录
  4. output_dir = "path/to/output/directory"
  5. best_model_dir = os.path.join(output_dir, "best_model")
  6. # 设置 TrainingArguments
  7. training_args = TrainingArguments(
  8. output_dir=output_dir,
  9. evaluation_strategy="epoch", # 每个 epoch 进行一次评估
  10. save_strategy="epoch", # 每个 epoch 保存一次模型
  11. save_total_limit=3,
  12. load_best_model_at_end=True, # 在训练结束时加载最优模型
  13. metric_for_best_model="eval_loss", # 根据验证集的损失值选择最优模型,"eval_loss" 默认会计算,无需指定自定义compute_metrics,但如果是使用其他的指标,需要与compute_metrics 字典对应
  14. greater_is_better=False, # 损失值越小越好
  15. include_inputs_for_metrics=True # True 表示调用compute_metrics会将输入input_ids 也进行导入,方便计算
  16. )
  17. # 创建 Trainer 实例
  18. trainer = Trainer(
  19. model=model,
  20. args=training_args,
  21. train_dataset=train_dataset,
  22. eval_dataset=eval_dataset,
  23. tokenizer=tokenizer,
  24. compute_metrics=compute_metrics, # 请确保compute_metrics函数正确定义并返回一个包含metric_for_best_model指定指标的字典。
  25. )
  26. metrics = train_result.metrics
  27. trainer.log_metrics("train", metrics)
  28. trainer.save_metrics("train", metrics)
  29. trainer.save_state()
  30. # 在训练完成后,最优模型将被自动保存在 best_model_dir 中
  31. # 但是,如果需要手动保存模型,可以使用以下代码:
  32. trainer.save_model(best_model_dir)
  33. # 加载保存的最优模型
  34. best_model = AutoModelForSequenceClassification.from_pretrained(best_model_dir)

        1.2、使用trainer训练ds ZeRO3或fsdp时,怎么保存模型为huggingface格式呢?

transformers:4.39

新版trainer中存在函数self.accelerator.get_state_dict,这个函数可以将ZeRO3切片在其他设备上的参数加载过来,然后使用self._save()保存,具体见下文_save_checkpoint、save_model、_save 函数

二、PreTrained Model中的from_pretrained常见的参数

transformers:4.39

  1. # from_pretrained 是一个类方法,用于从预训练模型中加载模型实例
  2. @classmethod
  3. def from_pretrained(
  4. cls,
  5. # pretrained_model_name_or_path: 预训练模型的名称或路径,可以是本地路径或在线路径
  6. pretrained_model_name_or_path: Optional[Union[str, os.PathLike]],
  7. # model_args: 模型的初始化参数,将传递给模型的构造函数
  8. *model_args,
  9. # config: 模型配置对象或其路径,如果未提供,将尝试从 pretrained_model_name_or_path 加载
  10. config: Optional[Union[PretrainedConfig, str, os.PathLike]] = None,
  11. # cache_dir: 用于缓存下载的模型文件的目录
  12. cache_dir: Optional[Union[str, os.PathLike]] = None,
  13. # ignore_mismatched_sizes: 是否忽略权重大小不匹配的情况
  14. ignore_mismatched_sizes: bool = False,
  15. # force_download: 是否强制重新下载模型权重
  16. force_download: bool = False,
  17. # local_files_only: 是否只使用本地文件,不尝试从远程下载
  18. local_files_only: bool = False,
  19. # token: Hugging Face Hub 的访问令牌,用于下载模型权重
  20. token: Optional[Union[str, bool]] = None,
  21. # revision: 要使用的模型修订版本
  22. revision: str = "main",
  23. # use_safetensors: 是否使用 safetensors 格式加载模型权重
  24. use_safetensors: bool = None,
  25. **kwargs,
  26. ):
  27. # 从 kwargs 中提取一些常用参数
  28. state_dict = kwargs.pop("state_dict", None)
  29. from_tf = kwargs.pop("from_tf", False)
  30. from_flax = kwargs.pop("from_flax", False)
  31. resume_download = kwargs.pop("resume_download", False)
  32. proxies = kwargs.pop("proxies", None)
  33. output_loading_info = kwargs.pop("output_loading_info", False)
  34. use_auth_token = kwargs.pop("use_auth_token", None)
  35. trust_remote_code = kwargs.pop("trust_remote_code", None) # 使用远端加载模型文件
  36. _ = kwargs.pop("mirror", None)
  37. from_pipeline = kwargs.pop("_from_pipeline", None)
  38. from_auto_class = kwargs.pop("_from_auto", False)
  39. _fast_init = kwargs.pop("_fast_init", True)
  40. torch_dtype = kwargs.pop("torch_dtype", None) # 模型加载的数据类型,type.bfloat16 等
  41. low_cpu_mem_usage = kwargs.pop("low_cpu_mem_usage", None) # 低占用
  42. device_map = kwargs.pop("device_map", None) # auto 的话 accelerate 会自动分配设备
  43. max_memory = kwargs.pop("max_memory", None)
  44. offload_folder = kwargs.pop("offload_folder", None)
  45. offload_state_dict = kwargs.pop("offload_state_dict", False)
  46. offload_buffers = kwargs.pop("offload_buffers", False)
  47. load_in_8bit = kwargs.pop("load_in_8bit", False)
  48. load_in_4bit = kwargs.pop("load_in_4bit", False) # 4bit加载(未来删除),现在使用 quantization_config 参数
  49. quantization_config = kwargs.pop("quantization_config", None) # 量化的参数
  50. subfolder = kwargs.pop("subfolder", "")
  51. commit_hash = kwargs.pop("_commit_hash", None)
  52. variant = kwargs.pop("variant", None)
  53. adapter_kwargs = kwargs.pop("adapter_kwargs", {})
  54. adapter_name = kwargs.pop("adapter_name", "default") # peft adapter_name, 默认即可
  55. use_flash_attention_2 = kwargs.pop("use_flash_attention_2", False) # 未来弃用,使用参数 attn_implementation 来控制,使用方法见下文
  56. # 如果启用了 FSDP,则强制启用 low_cpu_mem_usage
  57. if is_fsdp_enabled():
  58. low_cpu_mem_usage = True
  59. # 对于 use_auth_token 参数的处理,已弃用,建议使用 token 参数代替
  60. if use_auth_token is not None:
  61. warnings.warn(
  62. "The `use_auth_token` argument is deprecated and will be removed in v5 of Transformers. Please use `token` instead.",
  63. FutureWarning,
  64. )
  65. if token is not None:
  66. raise ValueError(
  67. "`token` and `use_auth_token` are both specified. Please set only the argument `token`."
  68. )
  69. token = use_auth_token
  70. # 如果提供了 token 和 adapter_kwargs,则将 token 添加到 adapter_kwargs 中
  71. if token is not None and adapter_kwargs is not None and "token" not in adapter_kwargs:
  72. adapter_kwargs["token"] = token
  73. # 处理 use_safetensors 参数
  74. if use_safetensors is None and not is_safetensors_available():
  75. use_safetensors = False
  76. if trust_remote_code is True:
  77. logger.warning(
  78. "The argument `trust_remote_code` is to be used with Auto classes. It has no effect here and is"
  79. " ignored."
  80. )
  81. # 尝试从预训练模型路径获取 commit_hash
  82. if commit_hash is None:
  83. if not isinstance(config, PretrainedConfig):
  84. resolved_config_file = cached_file(
  85. pretrained_model_name_or_path,
  86. CONFIG_NAME,
  87. cache_dir=cache_dir,
  88. force_download=force_download,
  89. resume_download=resume_download,
  90. proxies=proxies,
  91. local_files_only=local_files_only,
  92. token=token,
  93. revision=revision,
  94. subfolder=subfolder,
  95. _raise_exceptions_for_gated_repo=False,
  96. _raise_exceptions_for_missing_entries=False,
  97. _raise_exceptions_for_connection_errors=False,
  98. )
  99. commit_hash = extract_commit_hash(resolved_config_file, commit_hash)
  100. else:
  101. commit_hash = getattr(config, "_commit_hash", None)
  102. # 如果使用了 PEFT 并且可用,则尝试加载适配器配置文件
  103. if is_peft_available():
  104. _adapter_model_path = adapter_kwargs.pop("_adapter_model_path", None)
  105. if _adapter_model_path is None:
  106. _adapter_model_path = find_adapter_config_file(
  107. pretrained_model_name_or_path,
  108. cache_dir=cache_dir,
  109. force_download=force_download,
  110. resume_download=resume_download,
  111. proxies=proxies,
  112. local_files_only=local_files_only,
  113. _commit_hash=commit_hash,
  114. **adapter_kwargs,
  115. )
  116. if _adapter_model_path is not None and os.path.isfile(_adapter_model_path):
  117. with open(_adapter_model_path, "r", encoding="utf-8") as f:
  118. _adapter_model_path = pretrained_model_name_or_path
  119. pretrained_model_name_or_path = json.load(f)["base_model_name_or_path"]
  120. else:
  121. _adapter_model_path = None
  122. # 处理 device_map 参数,将其转换为适当的格式
  123. if isinstance(device_map, torch.device):
  124. device_map = {"": device_map}
  125. elif isinstance(device_map, str) and device_map not in ["auto", "balanced", "balanced_low_0", "sequential"]:
  126. try:
  127. device_map = {"": torch.device(device_map)}
  128. except RuntimeError:
  129. raise ValueError(
  130. "When passing device_map as a string, the value needs to be a device name (e.g. cpu, cuda:0) or "
  131. f"'auto', 'balanced', 'balanced_low_0', 'sequential' but found {device_map}."
  132. )
  133. elif isinstance(device_map, int):
  134. if device_map < 0:
  135. raise ValueError(
  136. "You can't pass device_map as a negative int. If you want to put the model on the cpu, pass device_map = 'cpu' "
  137. )
  138. else:
  139. device_map = {"": device_map}
  140. # 如果提供了 device_map,则强制启用 low_cpu_mem_usage
  141. if device_map is not None:
  142. if low_cpu_mem_usage is None:
  143. low_cpu_mem_usage = True
  144. elif not low_cpu_mem_usage:
  145. raise ValueError("Passing along a `device_map` requires `low_cpu_mem_usage=True`")
  146. # 如果启用了 low_cpu_mem_usage,但未安装 Accelerate,则引发异常
  147. if low_cpu_mem_usage:
  148. if is_deepspeed_zero3_enabled():
  149. raise ValueError(
  150. "DeepSpeed Zero-3 is not compatible with `low_cpu_mem_usage=True` or with passing a `device_map`."
  151. )
  152. elif not is_accelerate_available():
  153. raise ImportError(
  154. "Using `low_cpu_mem_usage=True` or a `device_map` requires Accelerate: `pip install accelerate`"
  155. )
  156. # 处理 quantization_config 参数
  157. if load_in_4bit or load_in_8bit:
  158. if quantization_config is not None:
  159. raise ValueError(
  160. "You can't pass `load_in_4bit`or `load_in_8bit` as a kwarg when passing "
  161. "`quantization_config` argument at the same time."
  162. )
  163. config_dict = {k: v for k, v in kwargs.items() if k in inspect.signature(BitsAndBytesConfig).parameters}
  164. config_dict = {**config_dict, "load_in_4bit": load_in_4bit, "load_in_8bit": load_in_8bit}
  165. quantization_config, kwargs = BitsAndBytesConfig.from_dict(
  166. config_dict=config_dict, return_unused_kwargs=True, **kwargs
  167. )
  168. logger.warning(
  169. "The `load_in_4bit` and `load_in_8bit` arguments are deprecated and will be removed in the future versions. "
  170. "Please, pass a `BitsAndBytesConfig` object in `quantization_config` argument instead."
  171. )
  172. from_pt = not (from_tf | from_flax)
  173. # 设置用户代理字符串,用于下载模型权重
  174. user_agent = {"file_type": "model", "framework": "pytorch", "from_auto_class": from_auto_class}
  175. if from_pipeline is not None:
  176. user_agent["using_pipeline"] = from_pipeline
  177. # 如果处于离线模式,则强制启用 local_files_only
  178. if is_offline_mode() and not local_files_only:
  179. logger.info("Offline mode: forcing local_files_only=True")
  180. local_files_only = True
  181. # 加载模型配置
  182. if not isinstance(config, PretrainedConfig):
  183. config_path = config if config is not None else pretrained_model_name_or_path
  184. config, model_kwargs = cls.config_class.from_pretrained(
  185. config_path,
  186. cache_dir=cache_dir,
  187. return_unused_kwargs=True,
  188. force_download=force_download,
  189. resume_download=resume_download,
  190. proxies=proxies,
  191. local_files_only=local_files_only,
  192. token=token,
  193. revision=revision,
  194. subfolder=subfolder,
  195. _from_auto=from_auto_class,
  196. _from_pipeline=from_pipeline,
  197. **kwargs,
  198. )
  199. else:
  200. # 如果直接提供了配置对象,则复制一份,以免修改原始配置
  201. config = copy.deepcopy(config)
  202. # 处理 attn_implementation 参数
  203. kwarg_attn_imp = kwargs.pop("attn_implementation", None)
  204. if kwarg_attn_imp is not None and config._attn_implementation != kwarg_attn_imp:
  205. config._attn_implementation = kwarg_attn_imp
  206. model_kwargs = kwargs
  207. # 处理量化相关配置
  208. pre_quantized = getattr(config, "quantization_config", None) is not None
  209. if pre_quantized or quantization_config is not None:
  210. if pre_quantized:
  211. config.quantization_config = AutoHfQuantizer.merge_quantization_configs(
  212. config.quantization_config, quantization_config
  213. )
  214. else:
  215. config.quantization_config = quantization_config
  216. hf_quantizer = AutoHfQuantizer.from_config(config.quantization_config, pre_quantized=pre_quantized)
  217. else:
  218. hf_quantizer = None
  219. # 如果启用了量化,则需要验证环境和调整一些参数
  220. if hf_quantizer is not None:
  221. hf_quantizer.validate_environment(
  222. torch_dtype=torch_dtype, from_tf=from_tf, from_flax=from_flax, device_map=device_map
  223. )
  224. torch_dtype = hf_quantizer.update_torch_dtype(torch_dtype)
  225. device_map = hf_quantizer.update_device_map(device_map)
  226. if low_cpu_mem_usage is None:
  227. low_cpu_mem_usage = True
  228. logger.warning("`low_cpu_mem_usage` was None, now set to True since model is quantized.")
  229. is_quantized = hf_quantizer is not None
  230. # 检查是否为分片加载检查点
  231. is_sharded = False
  232. sharded_metadata = None
  233. # 加载模型权重
  234. loading_info = None
  235. keep_in_fp32_modules = None
  236. use_keep_in_fp32_modules = False
  237. (......)

    一些简单的加载案例

  • 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 函数的实现过程​​​​​​​​​​​​​​

transformers/src/transformers/modeling_utils.py at main · huggingface/transformers · GitHub

推荐阅读
相关标签