qwen3_1.7b_local_finetune.py 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. """
  2. Qwen3-1.7B-Base 本地模型微调示例
  3. 这个脚本用于微调本地已下载的 Qwen3-1.7B-Base 模型。
  4. Qwen3 使用标准 attention,在华为升腾 NPU 上兼容性更好。
  5. 使用方法:
  6. python examples/qwen3_1.7b_local_finetune.py
  7. 前提条件:
  8. - 已在本地下载 Qwen3-1.7B-Base 模型
  9. - 模型路径配置在 local_model_path 变量中
  10. """
  11. import os
  12. import sys
  13. if hasattr(os, 'environ'):
  14. os.environ.setdefault("ASCEND_LAUNCH_BLOCKING", "1")
  15. sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
  16. from finetunex.models import QwenConfig, load_qwen_model
  17. from finetunex.data import load_dataset, format_dataset, InstructionDataset
  18. from finetunex.trainer import FineTuneTrainer
  19. from finetunex.utils import setup_environment, get_gpu_info, setup_logger
  20. def main():
  21. setup_environment(seed=42)
  22. logger = setup_logger("Qwen3-1.7B_Local_FineTuning")
  23. logger.info("=" * 60)
  24. logger.info("Qwen3-1.7B-Base 本地模型微调")
  25. logger.info("=" * 60)
  26. # ==================== 配置区域 ====================
  27. local_model_path = "./Qwen3-1.7B-Base"
  28. if not os.path.exists(local_model_path):
  29. logger.error(f"模型路径不存在:{local_model_path}")
  30. logger.error("请修改脚本中的 local_model_path 变量为正确的模型路径")
  31. sys.exit(1)
  32. logger.info(f"使用本地模型:{local_model_path}")
  33. dataset_path = os.path.join(os.path.dirname(__file__), "..", "data", "sample_dataset.json")
  34. output_dir = "./outputs/qwen3-1.7b-finetuned"
  35. # ==================== 模型配置 ====================
  36. config = QwenConfig(
  37. model_name=local_model_path,
  38. lora_r=16,
  39. lora_alpha=32,
  40. lora_dropout=0.05,
  41. target_modules=[
  42. "q_proj",
  43. "k_proj",
  44. "v_proj",
  45. "o_proj",
  46. "gate_proj",
  47. "up_proj",
  48. "down_proj",
  49. ],
  50. per_device_train_batch_size=1,
  51. gradient_accumulation_steps=4,
  52. learning_rate=2e-4,
  53. num_train_epochs=3,
  54. max_seq_length=512,
  55. output_dir=output_dir,
  56. use_4bit=False,
  57. trust_remote_code=True,
  58. )
  59. logger.info(f"模型配置:{config.model_name}")
  60. logger.info(f"LoRA 配置:r={config.lora_r}, alpha={config.lora_alpha}")
  61. logger.info(f"训练配置:epochs={config.num_train_epochs}, lr={config.learning_rate}")
  62. logger.info(f"输出目录:{output_dir}")
  63. # ==================== GPU 信息 ====================
  64. gpu_info = get_gpu_info()
  65. if gpu_info["available"]:
  66. logger.info(f"GPU 可用:{gpu_info['device_count']} 个设备")
  67. for i, dev in enumerate(gpu_info["devices"]):
  68. logger.info(f" GPU {i}: {dev['name']} ({dev['max_memory']:.2f} GB)")
  69. else:
  70. logger.warning("GPU 不可用,将使用 CPU 训练(不推荐)")
  71. # ==================== 加载数据 ====================
  72. logger.info("\n加载数据集...")
  73. dataset = load_dataset(dataset_path, format="json")
  74. formatted_dataset = format_dataset(
  75. dataset,
  76. instruction_column="instruction",
  77. input_column="input",
  78. output_column="output",
  79. )
  80. logger.info(f"数据集大小:{len(formatted_dataset)} 样本")
  81. # ==================== 加载模型 ====================
  82. logger.info("\n加载本地模型...")
  83. model, tokenizer, peft_config = load_qwen_model(config)
  84. # ==================== 创建训练数据集 ====================
  85. logger.info("\n创建训练数据集...")
  86. train_dataset = InstructionDataset(
  87. formatted_dataset,
  88. tokenizer,
  89. max_length=config.max_seq_length,
  90. )
  91. # ==================== 创建训练器 ====================
  92. logger.info("\n创建训练器...")
  93. trainer = FineTuneTrainer(
  94. model=model,
  95. tokenizer=tokenizer,
  96. config=config,
  97. train_dataset=train_dataset,
  98. )
  99. # ==================== 设置训练参数 ====================
  100. trainer.setup_training(
  101. output_dir=config.output_dir,
  102. num_train_epochs=config.num_train_epochs,
  103. per_device_train_batch_size=config.per_device_train_batch_size,
  104. gradient_accumulation_steps=config.gradient_accumulation_steps,
  105. learning_rate=config.learning_rate,
  106. warmup_ratio=0.03,
  107. weight_decay=0.01,
  108. logging_steps=10,
  109. save_steps=50,
  110. bf16=True,
  111. fp16=False,
  112. )
  113. # ==================== 开始训练 ====================
  114. logger.info("\n" + "=" * 60)
  115. logger.info("开始训练...")
  116. logger.info("=" * 60)
  117. trainer.train()
  118. # ==================== 保存模型 ====================
  119. logger.info("\n保存模型...")
  120. trainer.save_model()
  121. logger.info("=" * 60)
  122. logger.info("训练完成!")
  123. logger.info(f"模型已保存到:{config.output_dir}")
  124. logger.info("=" * 60)
  125. # ==================== 测试推理 ====================
  126. logger.info("\n测试推理...")
  127. test_prompts = [
  128. "请解释什么是机器学习",
  129. "写一首关于春天的诗",
  130. ]
  131. for test_prompt in test_prompts:
  132. logger.info(f"\n输入:{test_prompt}")
  133. inputs = tokenizer(test_prompt, return_tensors="pt")
  134. if torch.cuda.is_available():
  135. inputs = inputs.to("cuda")
  136. elif hasattr(torch, 'npu') and torch.npu.is_available():
  137. inputs = inputs.to("npu:0")
  138. with torch.no_grad():
  139. outputs = model.generate(
  140. **inputs,
  141. max_new_tokens=150,
  142. temperature=0.7,
  143. do_sample=True,
  144. top_p=0.9,
  145. )
  146. response = tokenizer.decode(outputs[0], skip_special_tokens=True)
  147. logger.info(f"输出:{response}")
  148. logger.info("\n" + "=" * 60)
  149. logger.info("所有任务完成!")
  150. logger.info("使用以下命令进行推理:")
  151. logger.info(f" python scripts/inference.py --model_path {output_dir} --interactive")
  152. logger.info("=" * 60)
  153. if __name__ == "__main__":
  154. import torch
  155. main()