trainer.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. """
  2. 微调训练器
  3. """
  4. import os
  5. from typing import Optional, Any
  6. from dataclasses import dataclass
  7. import torch
  8. from transformers import (
  9. TrainingArguments,
  10. Trainer,
  11. DataCollatorForLanguageModeling,
  12. AutoTokenizer,
  13. )
  14. from peft import PeftModel
  15. @dataclass
  16. class FineTuneTrainer:
  17. """
  18. 微调训练器
  19. """
  20. model: Any
  21. tokenizer: AutoTokenizer
  22. config: Any
  23. train_dataset: Optional[Any] = None
  24. eval_dataset: Optional[Any] = None
  25. def __post_init__(self):
  26. self.training_args = None
  27. self.trainer = None
  28. def setup_training(
  29. self,
  30. output_dir: str = "./outputs",
  31. num_train_epochs: float = 3.0,
  32. per_device_train_batch_size: int = 1,
  33. gradient_accumulation_steps: int = 4,
  34. learning_rate: float = 2e-4,
  35. warmup_ratio: float = 0.03,
  36. weight_decay: float = 0.01,
  37. logging_steps: int = 10,
  38. save_steps: int = 100,
  39. eval_strategy: str = "no",
  40. save_total_limit: int = 3,
  41. fp16: bool = True,
  42. **kwargs
  43. ):
  44. """
  45. 设置训练参数
  46. Args:
  47. output_dir: 输出目录
  48. num_train_epochs: 训练轮数
  49. per_device_train_batch_size: 每设备训练批次大小
  50. gradient_accumulation_steps: 梯度累积步数
  51. learning_rate: 学习率
  52. warmup_ratio: 预热比例
  53. weight_decay: 权重衰减
  54. logging_steps: 日志步数
  55. save_steps: 保存步数
  56. eval_strategy: 评估策略 (no, steps, epoch)
  57. save_total_limit: 保存总数限制
  58. fp16: 是否使用混合精度训练
  59. """
  60. self.training_args = TrainingArguments(
  61. output_dir=output_dir,
  62. num_train_epochs=num_train_epochs,
  63. per_device_train_batch_size=per_device_train_batch_size,
  64. gradient_accumulation_steps=gradient_accumulation_steps,
  65. learning_rate=learning_rate,
  66. warmup_ratio=warmup_ratio,
  67. weight_decay=weight_decay,
  68. logging_steps=logging_steps,
  69. save_steps=save_steps,
  70. eval_strategy=eval_strategy,
  71. save_total_limit=save_total_limit,
  72. fp16=fp16 if torch.cuda.is_available() else False,
  73. optim="paged_adamw_32bit",
  74. lr_scheduler_type="cosine",
  75. report_to="none",
  76. remove_unused_columns=False,
  77. **kwargs
  78. )
  79. # 数据 collator
  80. data_collator = DataCollatorForLanguageModeling(
  81. tokenizer=self.tokenizer,
  82. mlm=False,
  83. )
  84. # 创建 Trainer
  85. self.trainer = Trainer(
  86. model=self.model,
  87. args=self.training_args,
  88. train_dataset=self.train_dataset,
  89. eval_dataset=self.eval_dataset,
  90. data_collator=data_collator,
  91. )
  92. print("训练设置完成!")
  93. def train(self, resume_from_checkpoint: Optional[str] = None):
  94. """
  95. 开始训练
  96. Args:
  97. resume_from_checkpoint: 从检查点恢复训练
  98. """
  99. if self.trainer is None:
  100. raise ValueError("请先调用 setup_training() 设置训练参数")
  101. print("开始训练...")
  102. self.trainer.train(resume_from_checkpoint=resume_from_checkpoint)
  103. print("训练完成!")
  104. def save_model(self, output_dir: Optional[str] = None):
  105. """
  106. 保存模型
  107. Args:
  108. output_dir: 输出目录
  109. """
  110. if output_dir is None:
  111. output_dir = self.training_args.output_dir
  112. print(f"保存模型到:{output_dir}")
  113. # 保存 LoRA 权重
  114. self.model.save_pretrained(output_dir)
  115. # 保存 tokenizer
  116. self.tokenizer.save_pretrained(output_dir)
  117. print("模型保存完成!")
  118. def push_to_hub(self, repo_id: str, **kwargs):
  119. """
  120. 推送模型到 HuggingFace Hub
  121. Args:
  122. repo_id: 仓库 ID
  123. """
  124. print(f"推送模型到 HuggingFace Hub: {repo_id}")
  125. # 保存并推送
  126. self.model.push_to_hub(repo_id, **kwargs)
  127. self.tokenizer.push_to_hub(repo_id, **kwargs)
  128. print("推送完成!")