| import torch |
| import os |
| from transformers import AutoModelForCausalLM, AutoTokenizer |
| from peft import PeftModel |
|
|
| |
| BASE_MODEL_PATH = "./Qwen3-4B-Thinking-2507" |
| LORA_PATH = "./Qwen3-4B-Thinking-2507_FTtrained_lora" |
| OUTPUT_PRUNED_PATH = "./QiMing-Polaris-Qwen3-4B-HardPruned" |
|
|
| |
| LAYERS_TO_REMOVE = [29, 30, 31, 32] |
|
|
| print("🚀 阶段 1/4: 正在加载基础模型与分词器...") |
| tokenizer = AutoTokenizer.from_pretrained(BASE_MODEL_PATH, trust_remote_code=True) |
| base_model = AutoModelForCausalLM.from_pretrained( |
| BASE_MODEL_PATH, |
| dtype=torch.bfloat16, |
| device_map="cpu", |
| trust_remote_code=True, |
| ) |
|
|
| print("🔗 阶段 2/4: 加载并融合 LoRA 适配器...") |
| lora_model = PeftModel.from_pretrained(base_model, LORA_PATH) |
| merged_model = lora_model.merge_and_unload() |
| print("✅ LoRA 权重融合成功!") |
|
|
| print("✂️ 阶段 3/4: 正在执行硬剪枝 (Hard Pruning)...") |
| original_layers_count = len(merged_model.model.layers) |
| print(f"原模型总层数: {original_layers_count} 层") |
|
|
| |
| keep_indices = [i for i in range(original_layers_count) if i not in LAYERS_TO_REMOVE] |
| print(f"准备移除的层: {LAYERS_TO_REMOVE}") |
| print(f"保留的层索引数量: {len(keep_indices)} 层") |
|
|
| |
| pruned_layers = torch.nn.ModuleList( |
| [merged_model.model.layers[i] for i in keep_indices] |
| ) |
| merged_model.model.layers = pruned_layers |
|
|
| |
| configs_to_update = [merged_model.config] |
| if ( |
| hasattr(merged_model.config, "text_config") |
| and merged_model.config.text_config is not None |
| ): |
| configs_to_update.append(merged_model.config.text_config) |
|
|
| for cfg in configs_to_update: |
| cfg.num_hidden_layers = len(keep_indices) |
|
|
| |
| if hasattr(cfg, "layer_types") and cfg.layer_types is not None: |
| cfg.layer_types = [cfg.layer_types[i] for i in keep_indices] |
|
|
| print(f"剪枝完成!新模型总层数: {len(merged_model.model.layers)} 层") |
|
|
| print(f"💾 阶段 4/4: 正在保存硬剪枝后的全新模型至 {OUTPUT_PRUNED_PATH}...") |
| os.makedirs(OUTPUT_PRUNED_PATH, exist_ok=True) |
| merged_model.save_pretrained(OUTPUT_PRUNED_PATH, safe_serialization=True) |
| tokenizer.save_pretrained(OUTPUT_PRUNED_PATH) |
|
|
| print("🎉 恭喜!硬剪枝独立模型已成功保存导出!") |
|
|