| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214 |
- """
- Qwen3.5-0.8B 本地模型微调示例
- 这个脚本用于微调本地已下载的 Qwen3.5-0.8B 模型。
- 使用方法:
- python examples/qwen3.5_0.8b_local_finetune.py
- 前提条件:
- - 已在本地下载 Qwen3.5-0.8B 模型
- - 模型路径配置在 local_model_path 变量中
- """
- import os
- import sys
- if hasattr(os, 'environ'):
- os.environ.setdefault("ASCEND_LAUNCH_BLOCKING", "1")
- sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
- from finetunex.models import QwenConfig, load_qwen_model
- from finetunex.data import load_dataset, format_dataset, InstructionDataset
- from finetunex.trainer import FineTuneTrainer
- from finetunex.utils import setup_environment, get_gpu_info, setup_logger
- def main():
- # 设置环境和日志
- setup_environment(seed=42)
- logger = setup_logger("Qwen3.5-0.8B_Local_FineTuning")
-
- logger.info("=" * 60)
- logger.info("Qwen3.5-0.8B 本地模型微调")
- logger.info("=" * 60)
-
- # ==================== 配置区域 ====================
-
- # 本地模型路径(请根据实际情况修改)
- # 可以是绝对路径或相对于项目根目录的路径
- local_model_path = "./Qwen3.5-0.8B"
-
- # 如果模型在其他位置,请修改这里
- # 例如:
- # local_model_path = "/path/to/your/models/Qwen3.5-0.8B"
- # local_model_path = "D:\\AI_Models\\Qwen3.5-0.8B"
-
- # 检查模型路径是否存在
- if not os.path.exists(local_model_path):
- logger.error(f"模型路径不存在:{local_model_path}")
- logger.error("请修改脚本中的 local_model_path 变量为正确的模型路径")
- sys.exit(1)
-
- logger.info(f"使用本地模型:{local_model_path}")
-
- # 数据集路径
- dataset_path = os.path.join(os.path.dirname(__file__), "..", "data", "sample_dataset.json")
-
- # 输出目录
- output_dir = "./outputs/qwen3.5-0.8b-finetuned"
-
- # ==================== 模型配置 ====================
-
- config = QwenConfig(
- model_name=local_model_path, # 使用本地模型路径
- lora_r=16,
- lora_alpha=32,
- lora_dropout=0.05,
- target_modules=[
- "q_proj",
- "k_proj",
- "v_proj",
- "o_proj",
- "gate_proj",
- "up_proj",
- "down_proj",
- ],
- per_device_train_batch_size=1,
- gradient_accumulation_steps=4,
- learning_rate=2e-4,
- num_train_epochs=3,
- max_seq_length=512,
- output_dir=output_dir,
- use_4bit=False, # 华为升腾 NPU 不支持 4bit 量化
- trust_remote_code=True,
- )
-
- logger.info(f"模型配置:{config.model_name}")
- logger.info(f"LoRA 配置:r={config.lora_r}, alpha={config.lora_alpha}")
- logger.info(f"训练配置:epochs={config.num_train_epochs}, lr={config.learning_rate}")
- logger.info(f"输出目录:{output_dir}")
-
- # ==================== GPU 信息 ====================
-
- gpu_info = get_gpu_info()
- if gpu_info["available"]:
- logger.info(f"GPU 可用:{gpu_info['device_count']} 个设备")
- for i, dev in enumerate(gpu_info["devices"]):
- logger.info(f" GPU {i}: {dev['name']} ({dev['max_memory']:.2f} GB)")
- else:
- logger.warning("GPU 不可用,将使用 CPU 训练(不推荐)")
-
- # ==================== 加载数据 ====================
-
- logger.info("\n加载数据集...")
- dataset = load_dataset(dataset_path, format="json")
-
- # 格式化数据集
- formatted_dataset = format_dataset(
- dataset,
- instruction_column="instruction",
- input_column="input",
- output_column="output",
- )
-
- logger.info(f"数据集大小:{len(formatted_dataset)} 样本")
-
- # ==================== 加载模型 ====================
-
- logger.info("\n加载本地模型...")
- model, tokenizer, peft_config = load_qwen_model(config)
-
- # ==================== 创建训练数据集 ====================
-
- logger.info("\n创建训练数据集...")
- train_dataset = InstructionDataset(
- formatted_dataset,
- tokenizer,
- max_length=config.max_seq_length,
- )
-
- # ==================== 创建训练器 ====================
-
- logger.info("\n创建训练器...")
- trainer = FineTuneTrainer(
- model=model,
- tokenizer=tokenizer,
- config=config,
- train_dataset=train_dataset,
- )
-
- # ==================== 设置训练参数 ====================
-
- trainer.setup_training(
- output_dir=config.output_dir,
- num_train_epochs=config.num_train_epochs,
- per_device_train_batch_size=config.per_device_train_batch_size,
- gradient_accumulation_steps=config.gradient_accumulation_steps,
- learning_rate=config.learning_rate,
- warmup_ratio=0.03,
- weight_decay=0.01,
- logging_steps=10,
- save_steps=50,
- bf16=True,
- fp16=False,
- )
-
- # ==================== 开始训练 ====================
-
- logger.info("\n" + "=" * 60)
- logger.info("开始训练...")
- logger.info("=" * 60)
-
- trainer.train()
-
- # ==================== 保存模型 ====================
-
- logger.info("\n保存模型...")
- trainer.save_model()
-
- logger.info("=" * 60)
- logger.info("训练完成!")
- logger.info(f"模型已保存到:{config.output_dir}")
- logger.info("=" * 60)
-
- # ==================== 测试推理 ====================
-
- logger.info("\n测试推理...")
- test_prompts = [
- "请解释什么是机器学习",
- "写一首关于春天的诗",
- ]
-
- for test_prompt in test_prompts:
- logger.info(f"\n输入:{test_prompt}")
-
- inputs = tokenizer(test_prompt, return_tensors="pt")
- if torch.cuda.is_available():
- inputs = inputs.to("cuda")
- elif hasattr(torch, 'npu') and torch.npu.is_available():
- inputs = inputs.to("npu:0")
-
- with torch.no_grad():
- outputs = model.generate(
- **inputs,
- max_new_tokens=150,
- temperature=0.7,
- do_sample=True,
- top_p=0.9,
- )
-
- response = tokenizer.decode(outputs[0], skip_special_tokens=True)
- logger.info(f"输出:{response}")
-
- logger.info("\n" + "=" * 60)
- logger.info("所有任务完成!")
- logger.info("使用以下命令进行推理:")
- logger.info(f" python scripts/inference.py --model_path {output_dir} --interactive")
- logger.info("=" * 60)
- if __name__ == "__main__":
- import torch
- main()
|